【问题标题】:Python + Theano: Logistic regression weights do not updatePython + Theano:逻辑回归权重不更新
【发布时间】:2015-09-20 19:06:48
【问题描述】:

我已经与现有教程进行了广泛的比较,但我无法弄清楚为什么我的权重没有更新。这是返回更新列表的函数:

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 函数,我在每个 epoch 期间为每个 minibatch 调用它:

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(看起来并不多);如果你已经读到这里,谢谢。

已修复:我已确定不能使用均方误差作为成本函数。将其替换为负对数似然后,它照常工作。

【问题讨论】:

  • 我查看了代码,但没有发现明显的问题。你怎么知道你的权重没有更新?它们是完全没有变化,还是只是很小的变化?成本有没有变化(即使很小)?
  • 你能在你的代码中添加一个测试来证明你的声明是正确的吗? IE。 from numpy.testing import assert_array_equal 然后使用它将每个参数与其先前的值进行比较,例如与[param.get_value() for param in mlp.params]。因为正如@DanielRenshaw 所说,太小的学习率可能会使任何变化变得不可见。
  • 我将这一行放入小批量循环中:print(np.mean(mlp.layers[0].get_params())) 只是作为一种查看权重是否发生变化的贫民窟方式。不幸的是,即使学习率为 10,它也总是打印相同的数字。 get_params() 为层定义为self.get_params = theano.function([], self.W)
  • 所以在您的代码中train 肯定会被调用多次,如果更新设置正确,则应该执行它们。请首先在调用theano.function 之外创建一个更新列表,并检查它是否包含相关更新。如果更新正确,但功能没有更新,这很奇怪。仅用一个更新替换更新,例如[(param, param -1.)] 看看是否可行。否则,在 MLP 框架之外手动创建一个更新失败的最小示例。

标签: python machine-learning logistic-regression theano


【解决方案1】:

这种行为是由一些原因引起的,但归结为未正确计算成本。在您的实现中,LogisticRegression 层的输出是每个输入数字的预测类别(通过 argmax 操作获得),并且您将其与预期预测之间的平方差。

这将为您的模型中的任何参数提供 0s 的梯度,因为 argmax(预测类)的输出与 argmax(类概率)的输入的梯度将为 0。

相反,LogisticRegression 应该输出类的概率:

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 类中,您计算​​成本。您可以在每个类的期望概率和模型计算的概率之间使用均方误差,但人们倾向于使用期望类的负对数似然,您可以在 MLP 类中实现它:

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 类中那样将所有权重初始化为 0。权重的原始值应不同,以帮助打破对称性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 2011-11-22
    • 2018-09-20
    • 2020-03-22
    • 2016-12-01
    • 2016-08-13
    • 2019-02-14
    相关资源
    最近更新 更多