NNDL 作业11 LSTM

习题6-4  推导LSTM网络中参数的梯度, 并分析其避免梯度消失的效果

LSTM(长短期记忆)网络是一种常用的循环神经网络(RNN)变体,用于处理序列数据。为了推导LSTM网络中参数的梯度,我们需要考虑网络的前向传播和反向传播过程。

首先,让我们回顾LSTM的基本结构。一个标准的LSTM单元由三个门控单元组成:输入门(input gate)、遗忘门(forget gate)和输出门(output gate)。这些门控单元帮助网络决定如何处理输入数据并记住/遗忘相关信息。

LSTM的前向传播过程如下:

        1.输入门的计算:

        2.遗忘门的计算:

        3.细胞状态更新:

        4.输出门的计算:

        5.隐藏状态更新:

这是LSTM的前向传播过程。接下来,我们可以使用反向传播算法计算参数的梯度。

首先,我们定义损失函数(如交叉熵损失函数)并计算相对于输出h_tht​的梯度。然后,我们根据链式法则逐层传播梯度,计算每个参数的梯度。

对于隐藏状态h_tht​的梯度,我们首先计算相对于损失函数的梯度,然后应用链式法则逐层传播梯度:

        1.相对于输出门的梯度:

        2.相对于细胞状态的梯度:

        3.相对于输入门的梯度:

        4.相对于遗忘门的梯度:

        5.相对于候选细胞状态的梯度:

然后,我们可以计算参数的梯度:

        1.输入门参数的梯度:

        2.遗忘门参数的梯度:

        3.输出门参数的梯度:

        4.候选细胞状态参数的梯度:

以上是LSTM网络中参数的梯度推导过程。

LSTM网络的设计使其能够有效地缓解梯度消失问题。

习题6-3P  编程实现下图LSTM运行过程

1. 使用Numpy实现LSTM算子

import numpy as np
 
x = np.array([[1, 0, 0, 1],
              [3, 1, 0, 1],
              [2, 0, 0, 1],
              [4, 1, 0, 1],
              [2, 0, 0, 1],
              [1, 0, 1, 1],
              [3, -1, 0, 1],
              [6, 1, 0, 1],
              [1, 0, 1, 1]])
# x = np.array([
#               [3, 1, 0, 1],
#
#               [4, 1, 0, 1],
#               [2, 0, 0, 1],
#               [1, 0, 1, 1],
#               [3, -1, 0, 1]])
inputGate_W = np.array([0, 100, 0, -10])
outputGate_W = np.array([0, 0, 100, -10])
forgetGate_W = np.array([0, 100, 0, 10])
c_W = np.array([1, 0, 0, 0])
 
 
def sigmoid(x):
    y = 1 / (1 + np.exp(-x))
    if y >= 0.5:
        return 1
    else:
        return 0
 
 
temp = 0
y = []
c = []
for input in x:
    c.append(temp)
    temp_c = np.sum(np.multiply(input, c_W))
    temp_input = sigmoid(np.sum(np.multiply(input, inputGate_W)))
    temp_forget = sigmoid(np.sum(np.multiply(input, forgetGate_W)))
    temp_output = sigmoid(np.sum(np.multiply(input, outputGate_W)))
    temp = temp_c * temp_input + temp_forget * temp
    y.append(temp_output * temp)
print("memory:",c)
print("y     :",y)

结果:

2. 使用nn.LSTMCell实现

import torch
from torch import nn
import numpy as np

print('one layer lstm')
cell = nn.LSTMCell(input_size=100, hidden_size=20)
h = torch.zeros(3, 20)
c = torch.zeros(3, 20)
x = torch.randn(10, 3, 100)
for xt in x:
    h, c = cell(xt, [h, c])

print('h.shape: ', h.shape)
print('c.shape: ', c.shape)

结果:

3. 使用nn.LSTM实现

import torch
import torch.nn as nn
 
input_size = 4
hidden_size = 1
num_layers = 1
 
xt = torch.tensor([[1, 0, 0, 1], [3, 1, 0, 1], [2, 0, 0, 1], [4, 1, 0, 1], [2, 0, 0, 1], [1, 0, 1, 1], [3, -1, 0, 1], [6, 1, 0, 1], [1, 0, 1, 1]], dtype=torch.float32)
 
lstm = nn.LSTM(input_size, hidden_size, num_layers,bias=False)
 
# 手动设置参数权重
lstm.weight_ih_l0.data = torch.Tensor([[0.,100.,0.,10.],[0.,100.,0.,-10.],[1.,0.,0.,0.],[0.,0.,100.,-10.]])
lstm.weight_hh_l0.data = torch.zeros([4,1])
 
 
hx = torch.zeros(num_layers, 1, hidden_size)
cx = torch.zeros(num_layers, 1, hidden_size)
 
output,_= lstm(xt.unsqueeze(1), (hx, cx))
k=0
for i in output.squeeze(1).detach().numpy():
    print(k," output y is : ",round(i[0]))
    k=k+1

结果:

 结果是使用相同的参数和激活函数,三种方法得到的结果都是一样的。

参考:

深度学习常用数学知识-CSDN博客

LSTMCell — PyTorch 2.1 documentation

DL Homework 11-CSDN博客

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值