【问题标题】:Why derivatives are set to zero for LSTM为什么 LSTM 的导数设置为零
【发布时间】:2020-01-28 11:10:20
【问题描述】:

我正在查看下面的代码:


class LstmParam:
    def __init__(self, mem_cell_ct, x_dim):
        self.mem_cell_ct = mem_cell_ct
        self.x_dim = x_dim
        concat_len = x_dim + mem_cell_ct
        # weight matrices
        self.wg = rand_arr(-0.1, 0.1, mem_cell_ct, concat_len)
        self.wi = rand_arr(-0.1, 0.1, mem_cell_ct, concat_len) 
        self.wf = rand_arr(-0.1, 0.1, mem_cell_ct, concat_len)
        self.wo = rand_arr(-0.1, 0.1, mem_cell_ct, concat_len)
        # bias terms
        self.bg = rand_arr(-0.1, 0.1, mem_cell_ct) 
        self.bi = rand_arr(-0.1, 0.1, mem_cell_ct) 
        self.bf = rand_arr(-0.1, 0.1, mem_cell_ct) 
        self.bo = rand_arr(-0.1, 0.1, mem_cell_ct) 
        # diffs (derivative of loss function w.r.t. all parameters)
        self.wg_diff = np.zeros((mem_cell_ct, concat_len)) 
        self.wi_diff = np.zeros((mem_cell_ct, concat_len)) 
        self.wf_diff = np.zeros((mem_cell_ct, concat_len)) 
        self.wo_diff = np.zeros((mem_cell_ct, concat_len)) 
        self.bg_diff = np.zeros(mem_cell_ct) 
        self.bi_diff = np.zeros(mem_cell_ct) 
        self.bf_diff = np.zeros(mem_cell_ct) 
        self.bo_diff = np.zeros(mem_cell_ct) 

    def apply_diff(self, lr = 1):
        self.wg -= lr * self.wg_diff
        self.wi -= lr * self.wi_diff
        self.wf -= lr * self.wf_diff
        self.wo -= lr * self.wo_diff
        self.bg -= lr * self.bg_diff
        self.bi -= lr * self.bi_diff
        self.bf -= lr * self.bf_diff
        self.bo -= lr * self.bo_diff
        # reset diffs to zero
        self.wg_diff = np.zeros_like(self.wg)
        self.wi_diff = np.zeros_like(self.wi) 
        self.wf_diff = np.zeros_like(self.wf) 
        self.wo_diff = np.zeros_like(self.wo) 
        self.bg_diff = np.zeros_like(self.bg)
        self.bi_diff = np.zeros_like(self.bi) 
        self.bf_diff = np.zeros_like(self.bf) 
        self.bo_diff = np.zeros_like(self.bo) 

我不明白为什么要这么早地为self.wg_diff = np.zeros((mem_cell_ct, concat_len)) 应用导数。我不确定这里发生了什么。我也很困惑为什么它们被设置为零。如果有人能解释为什么会很感激。

【问题讨论】:

    标签: python machine-learning neural-network lstm


    【解决方案1】:

    一行如

    self.wg_diff = np.zeros((mem_cell_ct, concat_len)) 
    

    不是应用导数,它只是初始化一个数组,该数组稍后将保存损失函数相对于wg数组中的值的导数。

    apply_diff 中,此处应用了渐变:

    self.wg -= lr * self.wg_diff
    

    至关重要:在调用__init__ 函数创建LstmParam 的实例和调用apply_diff 应用渐变之间,不同的代码(你没有显示)必须修改self.wg_diff 以便它实际上包含衍生物。

    为了计算梯度,

    • 前向传递需要使用一些数据作为输入并计算输出,其中计算涉及wg 中的值。
    • 然后将输出与具有损失函数的所需正确输出进行比较。
    • 计算损失后,反向传递计算梯度(损失函数相对于计算输出所涉及的所有权重的导数)。向后传递用实际值填充self.wg_diff

    为了完整起见,下一行

    self.wg_diff = np.zeros_like(self.wg)
    

    正在为下一次反向传递重置梯度数组。

    【讨论】:

    • @Mathis Muller 非常感谢。这就是我认为可能会发生但不确定的事情。整个代码很长(200 行),所以虽然我只是展示了我感到困惑的部分。那么apply_diff是根据导数和学习率来改变权重吗?
    • 这是我试图理解的代码github.com/Manik9/LSTMs/blob/master/lstm.py
    • @user218030 "所以 apply_diff 正在根据导数和学习率改变权重?" - 是的。对于权重数组中的每个权重值,从权重中减去的是learning_rate * gradient
    • @Muller 谢谢。所以基本上每个门都有自己的权重,一旦发生前向传播,然后从权重中减去导数和学习率,以获得每个门的新权重。一个问题 - 这是在 LSTM 的一个单元完成之后还是在所有输入都输入到每个单独的单元之后发生?
    • @user218030 我不明白,对不起! “gate”和“cell”在LSTMs中有技术含义,不知道你说的“一个LSTM的cell”和“每个gate”,“all input”是什么意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    相关资源
    最近更新 更多