为什么 MNLogit returns `classes_num - 1` 参数以及如何获取所有参数?
Why MNLogit returns `classes_num - 1` params and how get them all?
如果我有几个 类,即 3。我希望得到 3 个广义线性回归系数数组,如 sklearn.linear_model.LogisticRegression
中那样,但 statsmodels.discrete.discrete_model.MNLogit
提供 classes_num - 1 个系数(在本例中为 -- 2)。
示例:
import statsmodels.api as st
from sklearn.linear_model import LogisticRegression
iris = st.datasets.get_rdataset('iris','datasets')
y = iris.data.Species
x = iris.data.iloc[:, :-1]
mdl = st.MNLogit(y, x)
# mdl_fit = mdl.fit()
mdl_fit = mdl.fit(method='bfgs' , maxiter=1000)
print(mdl_fit.params.shape) # (4, 2)
model = LogisticRegression(fit_intercept = False, C = 1e9)
mdl = model.fit(x, y)
print(model.coef_.shape) # (3, 4)
我应该如何使用 MNLogit 获得所有 3 类 的回归系数?
预测概率必须在 class 上加起来为 1。因此,我们在整个模型中放宽了一个自由参数以施加这一约束。
参考 class 的预测概率是一减去所有其他 class 的概率之和。
这类似于二元情况,在这种情况下我们没有单独的成功和失败参数,因为一个概率只是一个减去另一个概率。
未计算这些系数以强制模型的可识别性。换句话说,不计算它们可以确保其他 class 的系数是 唯一的 。如果您有三组系数,则有无数个模型给出相同的预测但系数值不同。如果您想知道标准误差、p 值等,这就很糟糕了。
缺失的 class 的对数假定为零。演示:
mm = st.MNLogit(
np.random.randint(1, 5, size=(100,)),
np.random.normal(size=(100, 3))
)
res = mm.fit()
xt = np.random.normal(size=(2, 3))
res.predict(xt)
结果:
array([[0.19918096, 0.34265719, 0.21307297, 0.24508888],
[0.33974178, 0.21649687, 0.20971884, 0.23404251]])
现在这些是对数,加上第一个零 class
logits = np.hstack([np.zeros((xt.shape[0], 1)), xt.dot(res.params)])
array([[ 0. , 0.54251673, 0.06742093, 0.20740715],
[ 0. , -0.45060978, -0.4824181 , -0.37268309]])
以及通过 softmax 的预测:
np.exp(logits) / (np.sum(np.exp(logits), axis=1, keepdims=1))
array([[0.19918096, 0.34265719, 0.21307297, 0.24508888],
[0.33974178, 0.21649687, 0.20971884, 0.23404251]])
与模型的预测相匹配。
重申一下:你找不到那些系数。对第一个 class 使用常数 logit 零。而且你无法找到有多少特征对第一个 class 有影响。这实际上是一个不适定的问题:特征不能对参考 class 产生影响,因为参考 class 从未被直接预测过。系数告诉您的是,与参考值 class 相比,给定 class 的对数优势因特定特征的单位增加而发生变化。
如果我有几个 类,即 3。我希望得到 3 个广义线性回归系数数组,如 sklearn.linear_model.LogisticRegression
中那样,但 statsmodels.discrete.discrete_model.MNLogit
提供 classes_num - 1 个系数(在本例中为 -- 2)。
示例:
import statsmodels.api as st
from sklearn.linear_model import LogisticRegression
iris = st.datasets.get_rdataset('iris','datasets')
y = iris.data.Species
x = iris.data.iloc[:, :-1]
mdl = st.MNLogit(y, x)
# mdl_fit = mdl.fit()
mdl_fit = mdl.fit(method='bfgs' , maxiter=1000)
print(mdl_fit.params.shape) # (4, 2)
model = LogisticRegression(fit_intercept = False, C = 1e9)
mdl = model.fit(x, y)
print(model.coef_.shape) # (3, 4)
我应该如何使用 MNLogit 获得所有 3 类 的回归系数?
预测概率必须在 class 上加起来为 1。因此,我们在整个模型中放宽了一个自由参数以施加这一约束。
参考 class 的预测概率是一减去所有其他 class 的概率之和。
这类似于二元情况,在这种情况下我们没有单独的成功和失败参数,因为一个概率只是一个减去另一个概率。
未计算这些系数以强制模型的可识别性。换句话说,不计算它们可以确保其他 class 的系数是 唯一的 。如果您有三组系数,则有无数个模型给出相同的预测但系数值不同。如果您想知道标准误差、p 值等,这就很糟糕了。
缺失的 class 的对数假定为零。演示:
mm = st.MNLogit(
np.random.randint(1, 5, size=(100,)),
np.random.normal(size=(100, 3))
)
res = mm.fit()
xt = np.random.normal(size=(2, 3))
res.predict(xt)
结果:
array([[0.19918096, 0.34265719, 0.21307297, 0.24508888],
[0.33974178, 0.21649687, 0.20971884, 0.23404251]])
现在这些是对数,加上第一个零 class
logits = np.hstack([np.zeros((xt.shape[0], 1)), xt.dot(res.params)])
array([[ 0. , 0.54251673, 0.06742093, 0.20740715],
[ 0. , -0.45060978, -0.4824181 , -0.37268309]])
以及通过 softmax 的预测:
np.exp(logits) / (np.sum(np.exp(logits), axis=1, keepdims=1))
array([[0.19918096, 0.34265719, 0.21307297, 0.24508888],
[0.33974178, 0.21649687, 0.20971884, 0.23404251]])
与模型的预测相匹配。
重申一下:你找不到那些系数。对第一个 class 使用常数 logit 零。而且你无法找到有多少特征对第一个 class 有影响。这实际上是一个不适定的问题:特征不能对参考 class 产生影响,因为参考 class 从未被直接预测过。系数告诉您的是,与参考值 class 相比,给定 class 的对数优势因特定特征的单位增加而发生变化。