通过例子理解 LSTM
Understanding LSTM through example
我想在 LSTM 中编写一个时间步长。我的重点是理解忘记门层、输入门层、候选值的功能现在和未来 细胞状态.
假设我在 t-1 和 xt 的隐藏状态如下。为简单起见,我们假设权重矩阵是单位矩阵,并且所有偏差都为零。
htminus1 = np.array( [0, 0.5, 0.1, 0.2, 0.6] )
xt = np.array( [-0.1, 0.3, 0.1, -0.25, 0.1] )
我知道忘记状态是 htminus1
和 xt
的 sigmoid
所以,是吗?
ft = 1 / ( 1 + np.exp( -( htminus1 + xt ) ) )
>> ft = array([0.47502081, 0.68997448, 0.549834 , 0.4875026 , 0.66818777])
我指的是 this link 来实现一个块 LSTM 的一次迭代。 link 说 ft
应该是 0 或 1。我在这里遗漏了什么吗?
如何按照下图中给出的模式获取遗忘门层?一个例子对我来说是说明性的。
同理,如何获得输入门层it
和新候选值向量\tilde{C}_t
,如下图所示?
最后,如何根据下图给出的方案得到新的隐藏状态ht
?
一个简单的例子将有助于我理解。提前致谢。
所以这从数字上看并不明显,但它是这样工作的-
如果您看到两条线连接成一条线,这是一个串联操作。您已将其解释为添加。
无论你在哪里看到 sigmoid
或 tanh
块,都暗示了与可训练权重矩阵的乘法。
如果两行通过显式 x
或 +
连接,则分别进行元素明智的乘法和加法。
因此,正确的操作应该是 sigmoid(Wf * np.concatenate(htminus1+xt)) + bf
,而不是您所拥有的 sigmoid(htminus1+xt)
。 Wf
是可训练参数矩阵,bf
是相应的偏置项。
请注意,我只是用 numpy 在图像的右侧写了方程式,其他的不多。将 [a, b]
解释为 a
和 b
之间的连接操作。
您可以类似地定义其他操作。
ft = sigmoid(Wf * np.concatenate(htminus1, xt)) + bf
it = sigmoid(Wi * np.concatenate(htminus1, xt)) + bi
Ctt = tanh(Wc * np.concatenate(htminus1, xt)) + bc
Ot = sigmoid(Wo * np.concatenate(htminus1, xt)) + bo
Ct = (C_{t-1} * ft) + (Ctt * it)
ht = Ot * tanh(Ct)
注意:我将 C^{tilda}
表示为 Ctt
除了已经涵盖的细节之外,我还想阐明计算和发生的串联的一些更精细的方面。
权重矩阵W_f
实际上由两个并排连接的权重矩阵组成,即沿轴=1,每个权重矩阵处理先前的时间步长激活(htminus1
) 和当前输入 (xt
)。而符号 [htminus1, xt]
表示通过垂直堆叠 htminus1
和 xt
获得的矩阵,即沿 axis=0.
这些忽略偏差的矩阵计算可以这样表示-
了解这些计算是如何在 tensorflow LSTM 模型中进行的也很有帮助。下面的代码块仅包含与此处讨论相关的主要计算,完整代码请遵循此 link
# gate layers calculations on current inputs
x_i = K.dot ( inputs_i , self.kernel_i )
x_f = K.dot ( inputs_f , self.kernel_f )
x_c = K.dot ( inputs_c , self.kernel_c )
x_o = K.dot ( inputs_o , self.kernel_o )
# adding biases
if self.use_bias :
x_i = K.bias_add ( x_i , self.bias_i)
x_f = K.bias_add ( x_f , self.bias_f)
x_c = K.bias_add ( x_c , self.bias_c)
x_o = K.bias_add ( x_o , self.bias_o)
# gate layers calculations using previous output ---> h_tm1 i.e htminus1
i = self.recurrent_activation (x_i + K.dot(h_tm1 , self.recurrent_kernel_i) )
f = self.recurrent_activation (x_f + K . dot( h_tm1 , self.recurrent_kernel_f) )
c = f * c_tm1 + i * self.activation (x_c + K.dot(h_tm1, self.recurrent_kernel_c) )
o = self.recurrent_activation (x_o + K.dot(h_tm1 , self.recurrent_kernel_o) )
遗忘门在这张图上解释的很清楚
.将 ct-1 称为 at-1
我想在 LSTM 中编写一个时间步长。我的重点是理解忘记门层、输入门层、候选值的功能现在和未来 细胞状态.
假设我在 t-1 和 xt 的隐藏状态如下。为简单起见,我们假设权重矩阵是单位矩阵,并且所有偏差都为零。
htminus1 = np.array( [0, 0.5, 0.1, 0.2, 0.6] )
xt = np.array( [-0.1, 0.3, 0.1, -0.25, 0.1] )
我知道忘记状态是 htminus1
和 xt
所以,是吗?
ft = 1 / ( 1 + np.exp( -( htminus1 + xt ) ) )
>> ft = array([0.47502081, 0.68997448, 0.549834 , 0.4875026 , 0.66818777])
我指的是 this link 来实现一个块 LSTM 的一次迭代。 link 说 ft
应该是 0 或 1。我在这里遗漏了什么吗?
如何按照下图中给出的模式获取遗忘门层?一个例子对我来说是说明性的。
同理,如何获得输入门层it
和新候选值向量\tilde{C}_t
,如下图所示?
最后,如何根据下图给出的方案得到新的隐藏状态ht
?
一个简单的例子将有助于我理解。提前致谢。
所以这从数字上看并不明显,但它是这样工作的-
如果您看到两条线连接成一条线,这是一个串联操作。您已将其解释为添加。
无论你在哪里看到
sigmoid
或tanh
块,都暗示了与可训练权重矩阵的乘法。如果两行通过显式
x
或+
连接,则分别进行元素明智的乘法和加法。
因此,正确的操作应该是 sigmoid(Wf * np.concatenate(htminus1+xt)) + bf
,而不是您所拥有的 sigmoid(htminus1+xt)
。 Wf
是可训练参数矩阵,bf
是相应的偏置项。
请注意,我只是用 numpy 在图像的右侧写了方程式,其他的不多。将 [a, b]
解释为 a
和 b
之间的连接操作。
您可以类似地定义其他操作。
ft = sigmoid(Wf * np.concatenate(htminus1, xt)) + bf
it = sigmoid(Wi * np.concatenate(htminus1, xt)) + bi
Ctt = tanh(Wc * np.concatenate(htminus1, xt)) + bc
Ot = sigmoid(Wo * np.concatenate(htminus1, xt)) + bo
Ct = (C_{t-1} * ft) + (Ctt * it)
ht = Ot * tanh(Ct)
注意:我将 C^{tilda}
表示为 Ctt
除了已经涵盖的细节之外,我还想阐明计算和发生的串联的一些更精细的方面。
权重矩阵W_f
实际上由两个并排连接的权重矩阵组成,即沿轴=1,每个权重矩阵处理先前的时间步长激活(htminus1
) 和当前输入 (xt
)。而符号 [htminus1, xt]
表示通过垂直堆叠 htminus1
和 xt
获得的矩阵,即沿 axis=0.
这些忽略偏差的矩阵计算可以这样表示-
了解这些计算是如何在 tensorflow LSTM 模型中进行的也很有帮助。下面的代码块仅包含与此处讨论相关的主要计算,完整代码请遵循此 link
# gate layers calculations on current inputs
x_i = K.dot ( inputs_i , self.kernel_i )
x_f = K.dot ( inputs_f , self.kernel_f )
x_c = K.dot ( inputs_c , self.kernel_c )
x_o = K.dot ( inputs_o , self.kernel_o )
# adding biases
if self.use_bias :
x_i = K.bias_add ( x_i , self.bias_i)
x_f = K.bias_add ( x_f , self.bias_f)
x_c = K.bias_add ( x_c , self.bias_c)
x_o = K.bias_add ( x_o , self.bias_o)
# gate layers calculations using previous output ---> h_tm1 i.e htminus1
i = self.recurrent_activation (x_i + K.dot(h_tm1 , self.recurrent_kernel_i) )
f = self.recurrent_activation (x_f + K . dot( h_tm1 , self.recurrent_kernel_f) )
c = f * c_tm1 + i * self.activation (x_c + K.dot(h_tm1, self.recurrent_kernel_c) )
o = self.recurrent_activation (x_o + K.dot(h_tm1 , self.recurrent_kernel_o) )
遗忘门在这张图上解释的很清楚
.将 ct-1 称为 at-1