【问题标题】:Multiple matrix multiplication loses weight updates多重矩阵乘法减重更新
【发布时间】:2018-08-20 21:15:23
【问题描述】:

forward 方法中,我只执行一组torch.add(torch.bmm(x, exp_w), self.b),然后我的模型会正确返回传播。当我添加另一层时 - torch.add(torch.bmm(out, exp_w2), self.b2) - 然后梯度不会更新,模型也不会学习。如果我将激活函数从nn.Sigmoid 更改为nn.ReLU,那么它适用于两层。

现在一直在思考这个问题,但不明白为什么它不能与 nn.Sigmoid 一起工作。

我尝试了不同的学习率、损失函数和优化函数,但似乎没有任何组合有效。当我将训练前后的权重相加时,它们是相同的。

代码:

class MyModel(nn.Module):

    def __init__(self, input_dim, output_dim):
        torch.manual_seed(1)
        super(MyModel, self).__init__()
        self.input_dim = input_dim
        self.output_dim = output_dim
        hidden_1_dimentsions = 20
        self.w = torch.nn.Parameter(torch.empty(input_dim, hidden_1_dimentsions).uniform_(0, 1))
        self.b = torch.nn.Parameter(torch.empty(hidden_1_dimentsions).uniform_(0, 1))

        self.w2 = torch.nn.Parameter(torch.empty(hidden_1_dimentsions, output_dim).uniform_(0, 1))
        self.b2 = torch.nn.Parameter(torch.empty(output_dim).uniform_(0, 1))

    def activation(self):
        return torch.nn.Sigmoid()

    def forward(self, x):
        x = x.view((x.shape[0], 1, self.input_dim))

        exp_w = self.w.expand(x.shape[0], self.w.size(0), self.w.size(1))
        out = torch.add(torch.bmm(x, exp_w), self.b)
        exp_w2 = self.w2.expand(out.shape[0], self.w2.size(0), self.w2.size(1))
        out = torch.add(torch.bmm(out, exp_w2), self.b2)
        out = self.activation()(out)
        return out.view(x.shape[0])

【问题讨论】:

    标签: neural-network pytorch


    【解决方案1】:

    除了损失函数、激活函数和学习率之外,参数初始化也很重要。我建议你看看 Xavier 初始化:https://pytorch.org/docs/stable/nn.html#torch.nn.init.xavier_uniform_

    此外,对于广泛的问题和网络架构批量标准化,可确保您的激活具有零均值和标准偏差,有助于:https://pytorch.org/docs/stable/nn.html#torch.nn.BatchNorm1d

    如果您有兴趣了解更多原因,这主要是由于梯度消失问题,这意味着您的梯度变得非常小,以至于您的权重没有更新。它是如此普遍,以至于它在维基百科上有自己的页面:https://en.wikipedia.org/wiki/Vanishing_gradient_problem

    【讨论】:

    • 但是我怎么能测试,它是消失梯度问题?现在,当我查看渐变时,我根本看不到它们正在更新,即使我将学习设置得更大,所以渐变应该更大。
    • @MihkelL。学习率不会影响梯度本身,它会影响梯度如何应用于权重。所以增加学习率不会影响梯度。您可以在将激活传递给 sigmoid 函数之前检查激活的大小。如果它们的量级很大,则梯度将非常小。此外,我刚刚发现您没有在两层之间应用激活(即在torch.add(torch.bmm(x, exp_w), self.b) 之后),因此您只是连接两个线性运算,从而产生一个矩阵乘法。
    • 对,我把它留到最后。感谢您指出。批量标准化确实有帮助。如果我自己能看到消失的梯度症状,我会查一下。 :)
    猜你喜欢
    • 2017-05-25
    • 2020-04-02
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    相关资源
    最近更新 更多