Python + Theano:逻辑回归权重不更新
Python + Theano: Logistic regression weights do not update
我已经与现有教程进行了广泛比较,但我无法弄清楚为什么我的权重没有更新。这是 return 更新列表的函数:
def get_updates(cost, params, learning_rate):
updates = []
for param in params:
updates.append((param, param - learning_rate * T.grad(cost, param)))
return updates
它在顶层定义,在任何 类 之外。这是每个参数的标准梯度下降。这里的 'params' 参数作为 mlp.params 输入,它只是每一层的参数列表的串联列表。我删除了除逻辑回归层之外的每一层,以找出我的成本没有降低的原因。下面是MLP的构造函数中mlp.params的定义。它遵循每一层的定义及其各自的参数列表。
self.params = []
for layer in self.layers:
self.params += layer.params
以下是训练函数,我在每个时期为每个小批量调用:
train = theano.function([minibatch_index], cost,
updates=get_updates(cost, mlp.params, learning_rate),
givens= {
x: train_set_x[minibatch_index * batch_size : (minibatch_index + 1) * batch_size],
y: train_set_y[minibatch_index * batch_size : (minibatch_index + 1) * batch_size]
})
如果您需要更多详细信息,可在此处获取整个文件:http://pastebin.com/EeNmXfGD
我不知道有多少人使用 Theano(好像不多);如果你已经读到这里,谢谢。
修正:我已经确定我不能使用平均平方误差作为成本函数。将其替换为负对数似然后,它照常工作。
这种行为是由几件事引起的,但归结为成本计算不当。在您的实现中,LogisticRegression 层的输出是每个输入数字(通过 argmax 操作获得)的预测 class,您将其与预期预测之间的平方差计算出来。
这将为您提供模型中任何参数的 0 梯度,因为 argmax 的输出梯度(预测 class)与 argmax 的输入(class 概率)将为 0。
相反,LogisticRegression 应该输出 classes 的概率:
def output(self, input):
input = input.flatten(2)
self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
return self.p_y_given_x
然后在 MLP class 中计算成本。您可以在每个 class 的期望概率与模型计算的概率之间使用均方误差,但人们倾向于使用预期 classes 的负对数似然,您可以在MLP class :
def neg_log_likelihood(self, x, y):
p_y_given_x = self.output(x)
return -T.mean(T.log(p_y_given_x)[T.arange(y.shape[0]), y])
然后你可以使用这个函数来计算你的成本和模型训练:
cost = mlp.neg_log_likelihood(x_, y)
一些额外的事情:
- 在第 215 行,打印成本时,将其格式化为整数值,但它是浮点值;这将失去监控的准确性。
- 通常不建议像在 LogisticRegression class 中那样将所有权重初始化为 0。权重的原始值应该不同,以帮助打破对称性
我已经与现有教程进行了广泛比较,但我无法弄清楚为什么我的权重没有更新。这是 return 更新列表的函数:
def get_updates(cost, params, learning_rate):
updates = []
for param in params:
updates.append((param, param - learning_rate * T.grad(cost, param)))
return updates
它在顶层定义,在任何 类 之外。这是每个参数的标准梯度下降。这里的 'params' 参数作为 mlp.params 输入,它只是每一层的参数列表的串联列表。我删除了除逻辑回归层之外的每一层,以找出我的成本没有降低的原因。下面是MLP的构造函数中mlp.params的定义。它遵循每一层的定义及其各自的参数列表。
self.params = []
for layer in self.layers:
self.params += layer.params
以下是训练函数,我在每个时期为每个小批量调用:
train = theano.function([minibatch_index], cost,
updates=get_updates(cost, mlp.params, learning_rate),
givens= {
x: train_set_x[minibatch_index * batch_size : (minibatch_index + 1) * batch_size],
y: train_set_y[minibatch_index * batch_size : (minibatch_index + 1) * batch_size]
})
如果您需要更多详细信息,可在此处获取整个文件:http://pastebin.com/EeNmXfGD
我不知道有多少人使用 Theano(好像不多);如果你已经读到这里,谢谢。
修正:我已经确定我不能使用平均平方误差作为成本函数。将其替换为负对数似然后,它照常工作。
这种行为是由几件事引起的,但归结为成本计算不当。在您的实现中,LogisticRegression 层的输出是每个输入数字(通过 argmax 操作获得)的预测 class,您将其与预期预测之间的平方差计算出来。
这将为您提供模型中任何参数的 0 梯度,因为 argmax 的输出梯度(预测 class)与 argmax 的输入(class 概率)将为 0。
相反,LogisticRegression 应该输出 classes 的概率:
def output(self, input):
input = input.flatten(2)
self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)
return self.p_y_given_x
然后在 MLP class 中计算成本。您可以在每个 class 的期望概率与模型计算的概率之间使用均方误差,但人们倾向于使用预期 classes 的负对数似然,您可以在MLP class :
def neg_log_likelihood(self, x, y):
p_y_given_x = self.output(x)
return -T.mean(T.log(p_y_given_x)[T.arange(y.shape[0]), y])
然后你可以使用这个函数来计算你的成本和模型训练:
cost = mlp.neg_log_likelihood(x_, y)
一些额外的事情:
- 在第 215 行,打印成本时,将其格式化为整数值,但它是浮点值;这将失去监控的准确性。
- 通常不建议像在 LogisticRegression class 中那样将所有权重初始化为 0。权重的原始值应该不同,以帮助打破对称性