为什么这个条件 logit 梯度的实现会失败?
Why is this implementation of the conditional logit gradient failing?
我已经为条件 logit 模型编写了一个非常简单的 likelihood/gradient 实现(已解释 here)- 似然法工作正常,但梯度不正确。我的两个问题是:我对梯度的推导是否正确,如果是这样,我在 Python 中的实现是否正确?如果在数学论坛上问这个更好,请随意移动。
型号:
对数似然:
最后,渐变:
这里,i是每个观察,j是观察i中的备选方案,c是观察i中选择的备选方案,Xij是i中选择j的特征向量,B是对应的系数。 似然公式应该是特征向量乘以系数向量。我的错误
我对可能性和梯度的实现如下:
可能性:
def log_likelihood(coefs, observations, config, lasso):
def func(grp):
mtrx = grp.as_matrix(config.features)
dp = np.dot(mtrx, coefs)
sub = np.log(np.exp(dp).sum())
inc = (dp * grp['choice']).sum()
return inc - sub
ll = observations.groupby(['observation_id']).apply(func).sum()
if lasso is not None:
ll -= (np.abs(coefs).sum() * lasso)
neg_log = ll * -1
return neg_log
渐变:
def gradient(coefs, observations, config, lasso):
def func(grp):
mtrx = grp.as_matrix([config.features])
tmtrx = mtrx.transpose()
tmp = np.exp(tmtrx * coefs[:, np.newaxis])
sub = (tmp * tmtrx).sum(1) / tmp.sum(1)
inc = (mtrx * grp['choice'][:, np.newaxis]).sum(0)
ret = inc - sub
return ret
return -1 * observations.groupby(['observation_id']).apply(func).sum()
在这里,coefs 是一个包含系数的 numpy 数组,observations 是一个数据框,其中每一行代表观察中的一个替代方案,列是一个选择列,表示列内的选择为 0/1,并且 observation_id 列,其中观察中的所有备选方案都具有相同的 id,最后 config 是一个包含成员 'features' 的字典,它是包含特征的观察 df 中的列列表。 请注意,我在不使用套索参数的情况下进行测试。下面是数据的示例。
我已经验证了可能性是正确的;但是,使用 scipy.optimize.check_grad 时梯度的误差非常大。当不将梯度传递给 scipy.optimize.minimize 时,我也能够求解 B。梯度的计算符合我的预期,所以在这一点上我只能认为我的推导不正确,但我不确定为什么。
In [27]: df.head(14)
Out[27]:
x1 x2 x3 observation_id choice
0 0.187785 0.435922 -0.475349 211 1
1 -0.935956 -0.405833 -1.753128 211 0
2 0.210424 0.141579 0.415933 211 0
3 0.507025 0.307965 -0.198089 211 0
4 0.080658 -0.125473 -0.592301 211 0
5 0.605302 0.239491 0.287094 293 1
6 0.259580 0.415388 -0.396969 293 0
7 -0.637267 -0.984442 -1.376066 293 0
8 0.241874 0.435922 0.855742 293 0
9 0.831534 0.650425 0.930592 293 0
10 -1.682565 0.435922 -2.517229 293 0
11 -0.149186 0.300299 0.494513 293 0
12 -1.918179 -9.967421 -2.774450 293 0
13 -1.185817 0.295601 -1.974923 293 0
推导不正确。在求幂中,我只包括给定系数的偏导数的特征和系数。相反,它应该是所有特征和系数的点积。
我已经为条件 logit 模型编写了一个非常简单的 likelihood/gradient 实现(已解释 here)- 似然法工作正常,但梯度不正确。我的两个问题是:我对梯度的推导是否正确,如果是这样,我在 Python 中的实现是否正确?如果在数学论坛上问这个更好,请随意移动。
型号:
对数似然:
最后,渐变:
这里,i是每个观察,j是观察i中的备选方案,c是观察i中选择的备选方案,Xij是i中选择j的特征向量,B是对应的系数。 似然公式应该是特征向量乘以系数向量。我的错误
我对可能性和梯度的实现如下:
可能性:
def log_likelihood(coefs, observations, config, lasso):
def func(grp):
mtrx = grp.as_matrix(config.features)
dp = np.dot(mtrx, coefs)
sub = np.log(np.exp(dp).sum())
inc = (dp * grp['choice']).sum()
return inc - sub
ll = observations.groupby(['observation_id']).apply(func).sum()
if lasso is not None:
ll -= (np.abs(coefs).sum() * lasso)
neg_log = ll * -1
return neg_log
渐变:
def gradient(coefs, observations, config, lasso):
def func(grp):
mtrx = grp.as_matrix([config.features])
tmtrx = mtrx.transpose()
tmp = np.exp(tmtrx * coefs[:, np.newaxis])
sub = (tmp * tmtrx).sum(1) / tmp.sum(1)
inc = (mtrx * grp['choice'][:, np.newaxis]).sum(0)
ret = inc - sub
return ret
return -1 * observations.groupby(['observation_id']).apply(func).sum()
在这里,coefs 是一个包含系数的 numpy 数组,observations 是一个数据框,其中每一行代表观察中的一个替代方案,列是一个选择列,表示列内的选择为 0/1,并且 observation_id 列,其中观察中的所有备选方案都具有相同的 id,最后 config 是一个包含成员 'features' 的字典,它是包含特征的观察 df 中的列列表。 请注意,我在不使用套索参数的情况下进行测试。下面是数据的示例。
我已经验证了可能性是正确的;但是,使用 scipy.optimize.check_grad 时梯度的误差非常大。当不将梯度传递给 scipy.optimize.minimize 时,我也能够求解 B。梯度的计算符合我的预期,所以在这一点上我只能认为我的推导不正确,但我不确定为什么。
In [27]: df.head(14)
Out[27]:
x1 x2 x3 observation_id choice
0 0.187785 0.435922 -0.475349 211 1
1 -0.935956 -0.405833 -1.753128 211 0
2 0.210424 0.141579 0.415933 211 0
3 0.507025 0.307965 -0.198089 211 0
4 0.080658 -0.125473 -0.592301 211 0
5 0.605302 0.239491 0.287094 293 1
6 0.259580 0.415388 -0.396969 293 0
7 -0.637267 -0.984442 -1.376066 293 0
8 0.241874 0.435922 0.855742 293 0
9 0.831534 0.650425 0.930592 293 0
10 -1.682565 0.435922 -2.517229 293 0
11 -0.149186 0.300299 0.494513 293 0
12 -1.918179 -9.967421 -2.774450 293 0
13 -1.185817 0.295601 -1.974923 293 0
推导不正确。在求幂中,我只包括给定系数的偏导数的特征和系数。相反,它应该是所有特征和系数的点积。