pytorch 神经网络笔记-RNN和LSTM

news2024/9/25 7:25:09

文章目录

  • 时间序列表示方法
      • 一般过程
  • RNN
    • RNN原理1
    • RNN原理2
  • RNN layer使用
  • pytorch实现nn.RNN
    • __init__
    • forward
    • Single layer RNN
    • 2 layer RNN
  • pytorch实现nn.RNNCell
  • 时间序列波形预测例子
  • LSTM
    • nn.LSTM
    • nn.LSTMCell
    • Single layer
    • Two Layers

b站课程链接课时自己找一下

时间序列表示方法

  • 卷积神经网络

    • 一般都是二维的图像数据
  • 循环神经网络

    • sequence类型数据
    • 时间序列
    • 文本
      • 一个句子是连续的单词,一个单词是连续的字母这样
      • 编码
      • one—hot编码很稀疏
      • 一般会通过语义相关性进行编码
  • 输入数据类型

    • 对于CNN,一般是[batch_size,channels,Height,width]
    • 对于sequence,分两种
      • [word num ,batch_size, word vec]
        • 从图像上更好理解
          • 这里word num 就是横轴
          • batch_size就是几条曲线
          • word vec就是每个点有几个特征,这里就一个值,所以 word vec就是1
      • [batch_size,word num , word vec]
        • 可以理解为第batch_size个句子,里面有word num个单词,每个单词有word vec个表达方式
    • word vec 就是词向量,比如情感相关度

一般过程

先找到单词的索引

embed一般是下载好的,存储每个词的特征,这里例子举例是随机的,实际上是由官方编制,下载word2vec或者GloVe,到本地使用

通过索引,查找到对应单词的词向量

注意:这种官网的embed是不能直接算梯度进行优化的

  • 比如这里直接调用GloVe,查找“Hello”,由一个100维度的词向量表示

RNN

RNN原理1

  • 说明:

    • 这句话就是一个[5,100]的tensor
    • 每一个时间戳(单词)是100维的向量,作为输入x,输入到一个Linear线性层里,进行一个特征的抽取,比如说输出一个2维的
    • 加起来就是[5,2]的向量
    • 然后再去做positive/negative的二分类
  • 上述存在的问题

    • Long sentence
      • 100 + words
      • too much parameters[w,b]
      • 每个词都有一个w和b
    • no context information
      • Consistent tensor
  • 解决办法

    • 减少参数数量

      • weight sharing
      • 一个[w,b]表示5个词,相当于是5个词都过一遍这个线性层,所以一个[w,b]就能提取出这句话,而不是一个单词一个
    • 保存语境信息

      • 比如“不喜欢”,不能只看到了“喜欢”没看到“不”

      • 需要一个语境单元,来贯穿整个网络,保存整个语境信息

      • consistent memory

      • h t h_{t} ht,记忆单元,会不断根据输入,循环更新自身,而不是像CNN一直往前冲[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LoOCU8cf-1674398676089)(/Users/xuan/Library/Application Support/typora-user-images/image-20230120173037729.png)]

      • 上述的模型非常合理

      • 至于最后选择输出的话,可以选择最后的 h t h_{t} ht,或者中间的 h t h_{t} ht,或者做一个融合,非常自由

RNN原理2

  • memory是如何更新的

  • 根据上一次的memory和这次输入的x,两个参数,两组矩阵想乘再相加,一般用tanh作为激活函数。最后那个得到y就是可以再加一个linear层,不用看

  • 这里E就是error

  • h0一般是[0,0…0]

这里表示方式有所不同

W R W_{R} WR就是 W h h W_{hh} Whh

W I W_{I} WI就是 W x h W_{xh} Wxh

  • 是累加的,每一步都有影响
  • 使用链式法则是为了把每一个单元的导数都很好的推导出来
  • 感受到这个大概的推导过程后,主要是推导一个这个梯度是怎么求的,说明是能更新的

  • (因为 W R W_{R} WR就是 W h h W_{hh} Whh,且这里算梯度是累乘)所以这里就有 W h h k − i W_{hh}^{k-i} Whhki ,如果i=0,就是 W h h k W_{hh}^{k} Whhk ,这个比较关键,在后面会阐释

RNN layer使用

回顾:

  • X[总共多少个词,总共几句,特征数]

  • 某一时刻的输入 X t X_{t} Xt,是每句话输入一个单词,这里就是[3,100]

  • 这里用20维的memory来表示,每一步的memory更新是这样的,所以初始的memory设置应该是[batch_size,20]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5NGZd8o1-1674398676094)(/Users/xuan/Library/Application Support/typora-user-images/image-20230120203200543.png)]

  • 调用pytorch代码验证一下

pytorch实现nn.RNN

init

  • Input_size
    • 对于一个单词,你用100维的向量来表示,那这个就是100
    • 对于预测房价,只有一个价格,那这个就是1
    • 是X[seq,batch_size,vec]里面的vec
  • hidden_size
    • 是隐藏层的维度
    • 是前面的h[batch_size,h_dim]里面的h_dim,应该是纯自己设置的,跟输入无关
  • num_layers
    • 不使用,默认是1
    • 使用,可以是1,2,4等

forward

  • 这里是把数据一步喂到位,而不是前面分解的,比如对于X[5,3,100](3句话,每句五个词,每个词100维度表示),是自动在时间上进行五次展开的。输入的是X,不是一步步的 X t X_{t} Xt

  • h t h_{t} ht的参数是,第一个是几层,第二个是batch_size,第三个是h_dim。

    • h0一般不设,就是初始化为0
    • 对于返回的ht,其实就是最后一个时刻的ht,就是[layer_num,batch_size,h_dim]
  • out

    • Out是每一个时间戳,的最后一个ht(memory)的状态,[ h 0 h_{0} h0, h 1 h_{1} h1,…, h t h_{t} ht]
  • 对于X[5,3,100],h[1,3,10]来说

    • h t h_{t} ht就是[1,3,10]
    • out就是[5,3,10]

Single layer RNN

h是最后一个时刻的,维度是[1,3,20]

out是所有时刻的,维度是[10,3,20]

2 layer RNN

两层的话,out还是跟以前一样,代表是最后一层的,而h则是两层都有,二者是不同方向的,一个横着一个竖的

  • 2层

  • 4 层

pytorch实现nn.RNNCell

前面是一次全部喂进去,这个是手动一次一次喂,相当于没有循环的步骤,没有在时间上展开

  • 初始化参数,跟前面完全一样

  • 然后后面类似forward方法这有一点不一样

  • 一层的

  • 两层的
    • 先把100特征变为30,再从30变为20

时间序列波形预测例子

通过前一段波形,能很好的预测下一段的曲线形状

因为很简单,所以batch设置为1,假设总长为50个点,那X就是[50,1,1]

import torch
import numpy as np
num_time_steps = 1
start = np.random.randint(3,size=1)[0]
time_steps = np.linspace(start, start+10, num_time_steps)
data = np.sin(time_steps)
data = data.reshape(num_time_steps, 1)
x = torch.tensor(data[:-1]).float().view(1, num_time_steps-1,1)
y = torch.tensor(data[1:]).float().view(1, num_time_steps-1,1)

  • 随机初始化start,不然会记住

  • x,y比如说,这里x是0~48之间的曲线,y就是要预测的1~49的曲线。当然也可以通过0~40的点去预测10~50的点

  • 网络结构

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn = nn.RNN(
            input_size=input_size,
            hidden_size=hidden_size,
            num_layers=1,
            batch_first=True,     # 让输入X是[b,seq,f]的结构
        )
        for p in self.rnn.parameters():
            nn.init.normal_(p,mean=0.0,std = 0.001)
        self.linear = nn.Linear(hidden_size, output_size)  #output_size为1

    def forward(self,x,hidden_prev):
        out, hidden_prev = self.rnn(x,hidden_prev) # hidden_prev就是ht
        out = out.view(-1,hidden_size)  # 将[1,seq,h]reshape为[seq,h]
        out = self.linear(out)   # 线性层 [seq,h]->[seq,1]
        out = out.unsqueeze(dim=0)  # [seq,1]->[1,seq,1]方便和真实值算mse
        return out, hidden_prev


  • 整体代码
import torch
import numpy as np
import torch.nn as nn
import matplotlib.pyplot as plt
num_time_steps = 50 # 点的数量
input_size = 1
hidden_size = 16  # memory的维度
output_size = 1
lr = 0.01


# 训练过程
model = Net()
criterion = nn.MSELoss()

optimizer = torch.optim.Adam(model.parameters(), lr)


hidden_prev = torch.zeros(1,1,hidden_size) # h0 是[b,1,10] 这里batch设为1
for iter in range(6000):
    start = np.random.randint(3, size=1)[0]
    time_steps = np.linspace(start, start + 10, num_time_steps)
    data = np.sin(time_steps)
    data = data.reshape(num_time_steps, 1)
    x = torch.tensor(data[:-1]).float().view(1, num_time_steps - 1, 1)
    y = torch.tensor(data[1:]).float().view(1, num_time_steps - 1, 1)

    output, hidden_prev = model(x,hidden_prev)
    hidden_prev = hidden_prev.detach()

    loss = criterion(output,y)
    model.zero_grad()
    loss.backward()
    optimizer.step()

    if iter % 100 == 0:
        print(f"Iteration:{iter} loss:{loss.item()}")

# 预测代码,给定一个点。后面会一个一个将预测值作为输入值,一个一个预测
prediction = []
input = x[:,0,:]
for _ in range(x.shape[1]):
    input = input.view(1,1,1)
    pred, hidden_prev = model(input,hidden_prev)
    input = pred
    prediction.append(pred.detach().numpy().ravel()[0])

x = x.data.numpy().ravel()
y = y.data.numpy()
plt.scatter(time_steps[:-1], x.ravel(), s=90)
plt.plot(time_steps[:-1], x.ravel())

plt.scatter(time_steps[1:], prediction)
plt.show()
  • 效果

LSTM

nn.LSTM

因为LSTM中,ht充当了输出的角色,中间流通的memory用C表示(C经过一定筛选才作为h输出),所以C和H的size是一样的

所以这里输入每个size,跟RNN是一样的,上面的代表x的特征维,第二个是h/c的维度,第三个是有几层

forward函数里,其余都跟RNN的一样,就是把h变为了h和c

  • 例子

3句话,每句10个单词

nn.LSTMCell

只有一层,所以这里第一个参数不写

Single layer

Two Layers

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自注意力(Self-Attention)机制浅析

一、自注意力机制概述循环神经网络由于信息传递的容量以及梯度消失问题,实际上也只能建立短距离依赖关系。为了建立长距离的依赖关系,可以增加网络的层数或者使用全连接网络。但是全连接网络无法处理变长的输入序列,另外,不同的输…

字节青训前端笔记 | Web安全

在网络时代下,Web 安全随处可见并且危害极大,Web 安全问题也越来越受到重视。本节课将讲述Web中的攻击和防御 XSS 利用开发者盲目信任客户提交的内容来实现的工具,恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页面…

机器视觉(十二):二维条码识别

目录: 机器视觉(一):概述 机器视觉(二):机器视觉硬件技术 机器视觉(三):摄像机标定技术 机器视觉(四):空域图像增强 …

【16】C语言 | 初识函数递归 | 几个练习

目录 什么是递归? 练习1: 练习2: 练习3、 练习4 什么是递归? 程序调用自身的编程技巧称为递归( recursion )。递归做为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化…

生物化学 电阻抗成像OpenEIT,Dbar算法,数据集等(暂记)

Electrical Impedance Tomography,EIT 电阻抗成像(Electrical Impedance Tomography,EIT)是一种无创的以人体内部的电阻率分布为目标的重建体内组织图像的技术。人体是一个大的生物电导体,各组织、器官均有一定的阻抗,当人体的局部…

SLF4J基本使用

文章目录1. 日志门面2. SLF4J的使用2.1 SLF4J入门2.2 为什么要使用SLF4J作为日志门面?2.3 绑定日志的实现(Binding)2.4 logback 整合 slf4j2.5 log4j 整合 slf4j2.6 jul 整合 slf4j3. 桥接旧的日志框架(Bridging)3.1 S…

完全二叉树的权值

题目描述 给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从 上到下、从左到右的顺序依次是 A1​,A2​,⋅⋅⋅AN​,如下图所示: 现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点 权值之和最大?如果有多个深度的权值和同为最大,请你输…

react用高阶组件优化文件结构 帮助建立高阶组件应用思路

其实高阶组件是一个将组件写的更灵活的方式,他的应用场景在业务开发中会非常多样 这里 我们演示一种 主要还是解决问题的思想最重要 或者是 这个不叫解决问题 而是设计组件结构的思路 我们来模拟一个场景 在src下有一个 components 文件夹目录 在 components 下有…

3.开发社区首页

数据库设计如下: 任务:开发社区首页,显示前十个帖子;开发分页组件,分页显示所有帖子。 开发流程:entity->dao->mapper.xml->service->controller 由于关注后端,所以未使用前后分离…

【Potplayer】如何用Potplayer实现对视频的局部缩放播放?如何用potplayer更舒心地播放竖屏视频?

一、问题背景 有时候我们从互联网上下载得到一个竖屏视频,用电脑播放时,左右两边都是黑的,电脑屏幕的高宽度没有得到良好应用。而如果恰好这个竖屏视频其实只有一小部分才是有效区域/重点内容,比如中央区域,上下区域都…

win10怎么玩经典扫雷?繁星软件园推荐大家试试Windows7Games吧,亲测好用的扫雷Win10电脑版下载!!!

扫雷Win10电脑版(Windows7Games)是专门为微软最新版本的Windows 10/11操作系统打造的一款非常不错的消除类PC休闲小游戏安装包, Windows7Games游戏安装包为中文版,包含经典扫雷、空当接龙、红心大战、国际象棋等微软低版本操作系统Windows自带的多款超级…

我的硕士前半生

本篇文章属于随笔类,它可能无法对你起到直接帮助,它只是我这个普通学生一年半以来的一些足迹与思考。本文首发于我的个人博客 Forever Young 我的本科像硕士,有实验室有工位,桌子超级大,有老师带有学长可以问。 我的硕…

分享122个ASP源码,总有一款适合您

ASP源码 分享122个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 122个ASP源码下载链接:https://pan.baidu.com/s/1-hwBdIxuv1NvpapRJsGAcQ?pwdgs1l 提取码&#x…

设计模式_行为型模式 -《迭代器模式》

设计模式_行为型模式 -《迭代器模式》 笔记整理自 黑马程序员Java设计模式详解, 23种Java设计模式(图解框架源码分析实战) 概述 定义 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 结构 迭代器…

手撕Pytorch源码#3.Dataset类 part3

写在前面手撕Pytorch源码系列目的:通过手撕源码复习了解高级python语法熟悉对pytorch框架的掌握在每一类完成源码分析后,会与常规深度学习训练脚本进行对照本系列预计先手撕python层源码,再进一步手撕c源码版本信息python:3.6.13p…

Couplet | 用Python写一副对联送给诸位科研汪!~

1写在前面 小伙伴们大家新年好啊!!!🥰 又是一年新春到,玉兔祝福要记牢:蹦蹦跳跳身体棒,平平淡淡精神爽,红红火火财运旺,和和气气朋友广,简简单单幸福长。&…

Windows SDK编程 初学笔记

#include "windows.h"int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdShow) {MessageBox(NULL, TEXT("来见见世面"), TEXT("Say Hi"), MB_OK);return 0; } MessageBox第一个参数为句柄,第…

Socket通信

什么是Socket?

Java基础——运算符与表达式

目录 Eclipse下载 安装 使用 运算符 键盘录入 Eclipse下载 安装 使用 Eclipse的概述(磨刀不误砍柴工)——是一个IDE(集成开发环境)Eclipse的特点描述(1)免费 (2)纯Java语言编写 (3)免安装 &#xff08…

【手把手教你学51单片机】

注:本文章转载自《手把手教你学习51单片机》!因转载需要原文链接,故无法选择转载! 如若侵权,请联系我进行删除!上传至网络博客目的为了记录自己学习的过程的同时,同时能够帮助其他一同学习的小伙…