【23-24 秋学期】NNDL 作业11 LSTM

目录

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

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

(一)numpy实现 

(二)使用nn.LSTMCell实现

(三) 使用nn.LSTM实现

总结

(一)推荐

 (二)关于LSTM的有关推导

(三)有关LSTM的代码


参考【【23-24 秋学期】NNDL 作业11 LSTM-CSDN博客

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

在我的上一篇博客【【23-24 秋学期】NNDL 作业10 BPTT-CSDN博客】中:

可以看到对于梯度爆炸/消失的推导,其中关键部分就在于递归梯度:\frac{\partial h_{t}}{\partial h_{t-1}}这一部分。

对于求解LSTM网络中的梯度消失也同理-----关键部分也就是内部状态递归梯度\frac{\partial C_{t}}{\partial C_{t-1}} 的变化。

先求解一下这个\frac{\partial C_{t}}{\partial C_{t-1}} 如下:

 然后假设损失为E,与上上图求解类似,如下:

参考【LSTM 如何避免梯度消失问题 - 知乎 (zhihu.com)】 这个作者的那个参考网址我点不开,看不了更原始的。

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

(一)numpy实现 

简单分析一下,这个LSTM的运行过程:主要包括三个门,加一个输入,中间层,以及输出层。

输入门的作用是:是否要保存输入结果

遗忘门的作用是:是否要把得到的输入结果存到延迟器中去,也就是隐藏层中

输出门的作用是是否把隐藏层的结果输出

需要强调的是,1)输入这一块也是有一个激活的,但是没使用,隐藏层向输出也是,所以我在实现的时候就没有写这一块激活。

2)对于中间隐藏层而言,他就是一个延迟器,所以当遗忘门为1时,它就会累加输入;为0时会清零。

3)对于激活函数sigmoid,它最后的结果类似一个概率,是处于【0,1】之间的一个数,但是由于这道题中最开始的要求,所以我在实现激活函数时,使用np.round(),把结果>0.5作为1输出,结果<0.5的作为0输出,这是特殊情况。

代码如下:

import numpy as np

# x=[x1,x2,x3,bias]
x = [[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]]
# input
input_w = [1, 0, 0, 0]
# 输入门
inputGate_w = [0, 100, 0, -10]
# 遗忘门
forgetGate_w = [0, 100, 0, 10]
# 输出门
outputGate_w = [0, 0, 100, -10]

# 激活
def sigmoid(x):
    return np.round(1 / (1 + np.exp(-x)))

# 延时器
hidden = []
y = []
temp = 0.0

for input in x:
    hidden.append(temp)
    # 输入与与对应权值相乘再相加
    temp_input = np.sum(np.multiply(input, input_w))
    # 输入门【得 1 or 得 0】
    temp_inputGate = sigmoid(np.sum(np.multiply(input, inputGate_w)))
    # 遗忘门
    temp_forgetGate = sigmoid(np.sum(np.multiply(input, forgetGate_w)))
    # 延时器
    temp = temp_input * temp_inputGate + temp * temp_forgetGate
    # 输出门
    temp_outputGate = sigmoid(np.sum(np.multiply(input, outputGate_w)))
    # 输出
    temp_y = temp * temp_outputGate
    y.append(temp_y)

print("延时器:", hidden)
print("输出y: ", y)

得到的结果为:

我就止步到此了。

参考了我们班学霸博客【指路:DL Homework 11-CSDN博客

 发现他对于输入和输出的激活函数有研究,在他博客里提到:

课程指路【 李宏毅手撕LSTM_哔哩哔哩_bilibili

我自己的理解就是:在LSTM的模型中,规定了输入输出状态的激活函数 是tanh函数,与我们实现的代码有一些区别。并且nn.LSTM的内部激活函数,没办法修改,所以仿照学霸的,写了一个检验版【也就是加上tanh版本的】

代码如下:

import numpy as np

# x=[x1,x2,x3,bias]
x = [[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]]
# input
input_w = [1, 0, 0, 0]
# 输入门
inputGate_w = [0, 100, 0, -10]
# 遗忘门
forgetGate_w = [0, 100, 0, 10]
# 输出门
outputGate_w = [0, 0, 100, -10]

# 激活
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 延时器
hidden = []
y = []
temp = 0

for input in x:
    hidden.append(temp)
    # 输入与与对应权值相乘再相加
    #加tanh激活
    temp_input = np.tanh(np.sum(np.multiply(input, input_w)))
    # 输入门【得 1 or 得 0】
    temp_inputGate = sigmoid(np.sum(np.multiply(input, inputGate_w)))
    # 遗忘门
    temp_forgetGate = sigmoid(np.sum(np.multiply(input, forgetGate_w)))
    # 延时器
    #加tanh激活
    temp = np.tanh(temp_input * temp_inputGate + temp * temp_forgetGate)
    # 输出门
    temp_outputGate = sigmoid(np.sum(np.multiply(input, outputGate_w)))
    # 输出
    temp_y = temp * temp_outputGate
    y.append(temp_y)

rounded_hidden = [round(x) for x in hidden]
print("检验版延时器:", rounded_hidden)

rounded_y = [round(x) for x in y]
print("检验版输出y: ", rounded_y)

其中按照下图:

将tanh函数加到输入以及输出之前。 

得到输出为:

 

(二)使用nn.LSTMCell实现

参考【PyTorch - torch.nn.LSTMCell (runebook.dev)】【汉语版,感觉比网页英转汉好用多了】

 可知我们实现的各个值为:

input_size=4

hidden_size=1

偏差bias=False

细胞状态cx=(1,hidden_size)#因为每次运算都是输入的一个批次

同理隐藏状态=(1,hidden_size)

import torch
import torch.nn as nn
#x 维度需要变换,因为LSTMcell接收的是(time_steps,batch_size,input_size)
x = 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.float)
x = x.unsqueeze(1)
#权重
input_w = [1, 0, 0, 0]# input
inputGate_w = [0, 100, 0, -10]# 输入门
forgetGate_w = [0, 100, 0, 10]# 遗忘门
outputGate_w = [0, 0, 100, -10]# 输出门
#输入形状每次一组,一组是【x1,x2,x3,bias】
input_size=4
hidden_size=1
#定义LSTM
cell=nn.LSTMCell(input_size=input_size,hidden_size=hidden_size,bias=False)
#输入隐藏权重,形状为 (4*hidden_size, input_size)
cell.weight_ih.data = torch.tensor([forgetGate_w, inputGate_w, input_w, outputGate_w], dtype=torch.float)
#隐藏权重,形状为 (4*hidden_size, hidden_size)
cell.weight_hh.data=torch.zeros([4*hidden_size,hidden_size])

#hx 和 cx 的初始值都需要初始化为全零张量,表示没有历史信息。
hx=torch.zeros(1,hidden_size)#hx 表示隐藏状态
cx=torch.zeros(1,hidden_size)#cx 表示细胞状态
outputs=[]
for i in range(len(x)):
    #这里没有区分c0,n0和c1,h1:因为使用了递归,也就是这次的输出是下次的输入
    hx, cx = cell(x[i], (hx, cx))
    outputs.append(hx.detach().numpy()[0][0])
#约数
outputs_rounded = [round(x) for x in outputs]
print("使用nn.LSTMCell的输出为:",outputs_rounded)

得到输出为:

(三) 使用nn.LSTM实现

参考【PyTorch - torch.nn.LSTM (runebook.dev)

 与Cell不同的是隐藏状态和细胞状态,其中多加了一个有关序列长度的维度。

代码如下:

import torch
import torch.nn as nn

#x 维度需要变换,因为LSTMcell接收的是(time_steps,batch_size,input_size)
x = 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.float)
x = x.unsqueeze(1)
#权重
input_w = [1, 0, 0, 0]# input
inputGate_w = [0, 100, 0, -10]# 输入门
forgetGate_w = [0, 100, 0, 10]# 遗忘门
outputGate_w = [0, 0, 100, -10]# 输出门
#输入形状每次一组,一组是【x1,x2,x3,bias】
input_size=4
hidden_size=1
#定义LSTM模型
lstm=nn.LSTM(input_size=input_size,hidden_size=hidden_size,bias=False)
#设置LSTM的权重矩阵
#输入隐藏权重,形状为 (4*hidden_size, input_size)
lstm.weight_ih_l0.data = torch.tensor([forgetGate_w, inputGate_w, input_w, outputGate_w], dtype=torch.float)
#隐藏权重,形状为 (4*hidden_size, hidden_size)
lstm.weight_hh_l0.data=torch.zeros([4*hidden_size,hidden_size])
# 初始化隐藏状态和记忆状态
hx = torch.zeros(1, 1, hidden_size)
cx = torch.zeros(1, 1, hidden_size)

# 前向传播
outputs, (hx, cx) = lstm(x, (hx, cx))
#所有维度值为 1 的维度都删除
outputs = outputs.squeeze().tolist()

#约数
outputs_rounded = [round(x) for x in outputs]
print("使用nn.LSTM计算的结果为:",outputs_rounded)

结果为:

总结

(一)推荐

首先是给大家推荐一下课程,有老师上课讲的下边这种动图:

然后我在推导有关Ct的递归梯度时,也是参考了这个视频,博主【苏坡爱豆的笑容】讲的很清楚!!!

 【清晰图解LSTM、BPTT、RNN的梯度消失问题】

 还有上个博客听的那个视频【也有关于LSTM推导的内容】:【循环神经网络讲解|随时间反向传播推导(BPTT)|RNN梯度爆炸和梯度消失的原因|LSTM及GRU(解决RNN中的梯度爆炸和梯度消失)-跟李沐老师动手学深度学习】

都非常nice!

还有一篇知乎的文章解释有关避免梯度消失的也特别好!地址如下:LSTM 如何避免梯度消失问题 - 知乎 (zhihu.com)

然后在看了博客:DL Homework 11-CSDN博客 后,感觉可以推荐一下关于pytorch的汉化版【我读英语头昏脑胀,适合不喜欢学英语的同学,指路:PyTorch 1.8 简体中文 (runebook.dev)】

 (二)关于LSTM的有关推导

这个与上一个作业关联挺大的,很类似,都是在递归推导。可以发现,这个模型中减少梯度消失现象的很重要的一个点就是对于门控单元【遗忘门】的把控。可以及时的缓解梯度消失。

(三)有关LSTM的代码

第一个numpy能写出来,但是关于输出输出位置的激活函数没有多想,参考了学霸的代码后发现他研究了关于这一部分,学到了很多---也就是有激活tanh函数只是写的例子里边把激活函数换成了一个输入几输出几的这样一个激活而已【我自己觉得跟去掉了激活没什么区别】

在pytorch默认的模型里是tanh激活函数。

自己在网上搜关于使用LSTM相关模型时写不出来,学会使用现成的工具是一种能力,然后这个LSTM模型好像没有手写过,我还是不太会内部结构【下几个实验有这个内容,我好好+认真写】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/253558.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

神经网络可以计算任何函数的可视化证明

神经网络可以计算任何函数的可视化证明 对于神经网络&#xff0c;一个显著的事实就是它可以计算任何函数。 如下&#xff1a;不管该函数如何&#xff0c;总有神经网络能够对任何可能的输入x&#xff0c;输出值f&#xff08;x&#xff09; 即使函数有很多输入和输出&#xff0…

vue2入门

vue2官方文档&#xff1a;安装 — Vue.js 1、安装 新建"vue"文件夹——>新建vue1.html 直接用<script>标签引入vue&#xff1a; <script src"https://cdn.jsdelivr.net/npm/vue2.7.14/dist/vue.js"></script> tips: CDN:一个网络…

uniapp中uni-data-select下拉框组件如何去除边框?

在目录中找到文件夹。 找到下拉框组件文件夹 注释该文件夹以下代码就能实现下拉框不带边框。

前端对接 —— 周末

1.点击校验 点击校验 宇哥 记得过滤 不能校验的数据&#xff08;我后端还要检验吗&#xff1f;&#xff09; 2.前端数据对接 这个可以吗&#xff1f; 这种的可以吗&#xff1f;

uniapp实现地图电子围栏功能

该功能使用uniapp中内置组件map实现 效果图预览&#xff1a; 实现过程&#xff1a; 1.文档&#xff1a; 2.代码&#xff1a; <template><view><map :style"width: 100%; height:screenHeight" :latitude"latitude" :longitude"longit…

免费在线markdown语法编辑器

本地用习惯了Typora&#xff0c;但是上传的图片保存在本地&#xff0c;其他电脑想查看必须连本地的图片也拷贝过去。虽然Typora可以用PicGo保存远程的图片&#xff0c;但电脑离线之后看不到图片&#xff0c;不能接受。所以想找一款在线版的编辑器&#xff0c;方便记笔记。 我之…

二叉树前,中序推后续_中,后续推前序

文章目录 介绍思路例子 介绍 二叉树是由根、左子树、右子树三部分组成。 二叉树的遍历方式又可以分为前序遍历&#xff0c;中序遍历&#xff0c;后序遍历。 前序遍历&#xff1a;根&#xff0c;左子树&#xff0c;右子树 中序遍历&#xff1a;左子树&#xff0c;根&#xff0…

【JVM】4.运行时数据区(程序计数器、虚拟机栈)

文章目录 4.JVM的运行时数据区4.1 程序计数器4.2 Java虚拟机栈4.3 虚拟机栈内存溢出 4.JVM的运行时数据区 4.1 程序计数器 程序计数器&#xff08;PC&#xff09;会记录着下一行字节码指令的地址。执行完当前指令后&#xff0c;PC刷新&#xff0c;JVM的执行引擎根据程序计数器…

饥荒Mod 开发(十一):修改物品堆叠

饥荒Mod 开发(十)&#xff1a;制作一把AOE武器 饥荒Mod 开发(十二)&#xff1a;一键制作 饥荒中物品栏有限&#xff0c;要拾取的物品有很多&#xff0c;经常装不下要忍痛丢掉各种东西&#xff0c;即使可以将物品放在仓库但是使用不方便&#xff0c;所以可以将物品的堆叠个数设…

GitHub入门介绍:从小白到大佬的旅程

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【MySQL】MySQL表的操作-创建查看删除和修改

文章目录 1.创建表2.查看表结构3.修改表4.删除表 1.创建表 语法&#xff1a; CREATE TABLE table_name (field1 datatype,field2 datatype,field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;说明&#xff1a; field 表示列名datatype 表示列的类型…

第7章 排序

前言 在这一章&#xff0c;我们讨论数组元素的排序问题。为简单起见&#xff0c;假设在我们的例子中数组只包含整数&#xff0c;虽然更复杂的结构显然也是可能的。对于本章的大部分内容&#xff0c;我们还假设整个排序工作能够在主存中完成&#xff0c;因此&#xff0c;元素的个…

【TB作品】51单片机,语音出租车计价器

西交大题目 1.语音出租车计价器 一、功能要求: 1.具有可模拟出租车车轮转速传感器的硬件设计,可计量出租车所走的公 里数。 2.显示和语音播报里程、价格和等待红灯或堵车的计时价格: 3.具有等待计时功能 4.具有实时年月日显示和切换功能。 5.操作简单、界面友好。 二、设计建议…

机器学习算法---异常检测

类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统计学检验箱…

计算机网络:自顶向下第八版学习指南笔记和课后实验--运输层

记录一些学习计算机网络:自顶向下的学习笔记和心得 Github地址&#xff0c;欢迎star ⭐️⭐️⭐️⭐️⭐️ 运输层 TCP&#xff1a; 传输控制协议 报文段 UDP&#xff1a; 用户数据包协议 数据报 将主机间交付扩展到进程间交付被称为运输层的多路复用与多路分解 将运输层…

饥荒Mod 开发(十三):木牌传送

饥荒Mod 开发(十二)&#xff1a;一键制作 饥荒Mod 开发(十四)&#xff1a;制作屏幕弹窗 一键传送源码 饥荒的地图很大&#xff0c;跑地图太耗费时间和饥饿值&#xff0c;如果大部分时间都在跑图真的是很无聊&#xff0c;所以需要有一个能够传送的功能&#xff0c;不仅可以快速…

docker文档转译1

写在最前面 本文主要是转译docker官方文档。主题是Docker overview&#xff0c;这里是链接 Docker概述 Docker是一个用于开发、发布和运行应用程序的开放平台。Docker使你能够将应用程序与基础设施分离&#xff0c;从而可以快速交付软件。你可以使用相同的方法像管理应用程序…

HarmonyOS4.0从零开始的开发教程18HarmonyOS应用/元服务上架

HarmonyOS&#xff08;十六&#xff09;HarmonyOS应用/元服务上架 简介 随着生活节奏的加快&#xff0c;我们有时会忘记一些重要的事情或日子&#xff0c;所以提醒功能必不可少。应用可能需要在指定的时刻&#xff0c;向用户发送一些业务提醒通知。例如购物类应用&#xff0c…

急速上手搭建单节点 k8s集群实战

Minikube搭建 是一种轻量化的Kubernetes集群&#xff0c;是k8s社区为了帮助开发者和学习者能够更好学习和体验k8s功能而推出的&#xff0c;使用个人PC的虚拟化环境就快速构建启动单节点k8s机器准备&#xff1a;阿里云 CentOS 7.x &#xff0c;2核4g 安装 安装Docker # 1.先…

Eclipse 自动生成注解,如果是IDEA可以参考编译器自带模版进行修改

IDEA添加自动注解 左上角选择 File -> Settings -> Editor -> File and Code Templates&#xff1b; 1、添加class文件自动注解&#xff1a; ​/*** <b>Function: </b> todo* program: ${NAME}* Package: ${PACKAGE_NAME}* author: Jerry* date: ${YEA…