Pytorch实现的LSTM、RNN模型结构

news2024/11/25 13:13:58

一、LSTM模型

import torch
from torch import nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import matplotlib.pyplot as plt

torch.manual_seed(1)

# Hyper Parameters
EPOCH = 1           # 训练整批数据多少次, 为了节约时间, 我们只训练一次
BATCH_SIZE = 64
TIME_STEP = 28      # rnn 时间步数 / 图片高度
INPUT_SIZE = 28     # rnn 每步输入值 / 图片每行像素
LR = 0.01           # learning rate
DOWNLOAD_MNIST = True  # 如果你已经下载好了mnist数据就写上 Fasle

# Mnist 手写数字
train_data = dsets.MNIST(
    root='./mnist/',      # 保存或者提取位置
    train=True,  # this is training data
    transform=transforms.ToTensor(),    # 转换 PIL.Image or numpy.ndarray 成
                                                    # torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间
    download=DOWNLOAD_MNIST,          # 没下载就下载, 下载了就不用再下了
)

# plot one example
# print(train_data.train_data.size())     # (60000, 28, 28)
# print(train_data.train_labels.size())   # (60000)
# plt.imshow(train_data.train_data[0].numpy(), cmap='gray')
# plt.title('%i' % train_data.train_labels[0])
# plt.show()

# 批训练 50samples, 1 channel, 28x28 (50, 1, 28, 28)
train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)

# 为了节约时间, 我们测试时只测试前2000个
test_data = dsets.MNIST(root='./mnist/', train=False, transform=transforms.ToTensor())
test_x = test_data.test_data.type(torch.FloatTensor)[:2000]/255.   # shape (2000, 28, 28) value in range(0,1)
test_y = test_data.test_labels.numpy()[:2000]    # covert to numpy array

class RNN(nn.Module):
    def __init__(self):
        super(RNN, self).__init__()

        self.rnn = nn.LSTM(     # LSTM 效果要比 nn.RNN() 好多了
            input_size=28,      # 图片每行的数据像素点
            hidden_size=64,     # rnn hidden unit
            num_layers=1,       # 有几层 RNN layers
            batch_first=True,   # input & output 会是以 batch size 为第一维度的特征集 e.g. (batch, time_step, input_size)
        )

        self.out = nn.Linear(64, 10)    # 输出层

    def forward(self, x):
        # 输入的input为,(batch, time_step, input_size)
        # x shape (batch, time_step, input_size)
        # r_out shape (batch, time_step, output_size)
        # h_n shape (n_layers, batch, hidden_size)   LSTM 有两个 hidden states, h_n 是分线, h_c 是主线
        # h_c shape (n_layers, batch, hidden_size)
        r_out, (h_n, h_c) = self.rnn(x, None)   # None 表示 hidden state 会用全0的 state

        # 选取最后一个时间点的 r_out 输出
        # 这里 r_out[:, -1, :] 的值也是 h_n 的值
        out = self.out(r_out[:, -1, :])
        return out

rnn = RNN()
print(rnn)

optimizer = torch.optim.Adam(rnn.parameters(), lr=LR)   # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss()                       # the target label is not one-hotted

# training and testing
for epoch in range(EPOCH):
    for step, (b_x, b_y) in enumerate(train_loader):    # gives batch data
        b_x = b_x.view(-1, 28, 28)                      # reshape x to (batch, time_step, input_size)

        output = rnn(b_x)                               # rnn output
        loss = loss_func(output, b_y)                   # cross entropy loss
        optimizer.zero_grad()                           # clear gradients for this training step
        loss.backward()                                 # backpropagation, compute gradients
        optimizer.step()                                # apply gradients

        if step % 50 == 0:
            test_output = rnn(test_x)                   # (samples, time_step, input_size)
            pred_y = torch.max(test_output, 1)[1].data.numpy()
            accuracy = float((pred_y == test_y).astype(int).sum()) / float(test_y.size)
            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)

# print 10 predictions from test data
test_output = rnn(test_x[:10].view(-1, 28, 28))
pred_y = torch.max(test_output, 1)[1].data.numpy()
print(pred_y, 'prediction number')
print(test_y[:10], 'real number')

上述中,我们对于h_n, h_c全部以0为输入,此时我们也可以修改为随机参数:

import torch
from torch import nn

class RNN(nn.Module):
    def __init__(self):
        super(RNN, self).__init__()

        self.rnn = nn.LSTM(     # LSTM 效果要比 nn.RNN() 好多了
            input_size=28,      # 图片每行的数据像素点
            hidden_size=64,     # rnn hidden unit
            num_layers=1,       # 有几层 RNN layers
            batch_first=True,   # input & output 会是以 batch size 为第一维度的特征集 e.g. (batch, time_step, input_size)
        )

        self.out = nn.Linear(64, 10)    # 输出层

    def forward(self, x):
        # 输入的input为,(batch, time_step, input_size)
        # x shape (batch, time_step, input_size)
        # r_out shape (batch, time_step, output_size)
        # h_n shape (n_layers, batch, hidden_size)   LSTM 有两个 hidden states, h_n 是分线, h_c 是主线
        # h_c shape (n_layers, batch, hidden_size)

        # 初始化的隐藏元和记忆元,通常它们的维度是一样的
        # 1个LSTM层,batch_size=x.shape[0], 隐藏层的特征维度64
        h_0 = torch.randn(1, x.shape[0], 64)
        c_0 = torch.randn(1, x.shape[0], 64)
        r_out, (h_n, h_c) = self.rnn(x, (h_0, c_0))   # None 表示 hidden state 会用全0的 state

        # 选取最后一个时间点的 r_out 输出
        # 这里 r_out[:, -1, :] 的值也是 h_n 的值
        out = self.out(r_out[:, -1, :])
        return out

rnn = RNN()
print(rnn)

参数:

class torch.nn.LSTM(*args, **kwargs)
参数有:
    input_size:x的特征维度
    hidden_size:隐藏层的特征维度
    num_layers:lstm隐层的层数,默认为1
    bias:False则bihbih=0和bhhbhh=0. 默认为True
    batch_first:True则输入输出的数据格式为 (batch, seq, feature)
    dropout:除最后一层,每一层的输出都进行dropout,默认为: 0
    bidirectional:True则为双向lstm默认为False

LSTM的另外两个输入是 h0 和 c0,可以理解成网络的初始化参数,用随机数生成即可。

h0(num_layers * num_directions, batch, hidden_size)
c0(num_layers * num_directions, batch, hidden_size)
参数:
    num_layers:隐藏层数
    num_directions:如果是单向循环网络,则num_directions=1,双向则num_directions=2
    batch:输入数据的batch
    hidden_size:隐藏层神经元个数

注意,如果我们定义的input格式是:

input(batch, seq_len, input_size)
则H和C的格式也是要变的:
h0(batch, num_layers * num_directions,  hidden_size)
c0(batch, num_layers * num_directions,  hidden_size)

LSTM的输出是一个tuple,如下:

output,(ht, ct) = net(input)
    output: 最后一个状态的隐藏层的神经元输出
    ht:最后一个状态的隐含层的状态值
    ct:最后一个状态的隐含层的遗忘门值

output的默认维度是:

output(seq_len, batch, hidden_size * num_directions)
ht(num_layers * num_directions, batch, hidden_size)
ct(num_layers * num_directions, batch, hidden_size)

和input的情况类似,如果我们前面定义的input格式是:

input(batch, seq_len, input_size)
则ht和ct的格式也是要变的:
ht(batc,num_layers * num_directions, h, hidden_size)
ct(batc,num_layers * num_directions, h, hidden_size)

我们使用线性函数进行构建LSTM:

import torch
import torch.nn as nn


class LSTM_v1(nn.Module):
    def __init__(self, input_sz, hidden_sz):
        super().__init__()
        self.input_size = input_sz
        self.hidden_size = hidden_sz

        # 遗忘门
        self.f_gate = nn.Linear(self.input_size+self.hidden_size, self.hidden_size)

        # 输入门
        self.i_gate = nn.Linear(self.input_size+self.hidden_size, self.hidden_size)

        # 细胞cell
        self.c_cell = nn.Linear(self.input_size+self.hidden_size, self.hidden_size)

        # 输出门
        self.o_gate = nn.Linear(self.input_size+self.hidden_size, self.hidden_size)

        self.init_weights()

    def init_weights(self):
        pass

    def forward(self, x, init_states=None):
        bs, seq_sz, _ = x.size()
        hidden_seq = []

        if init_states is None:
            h_t, c_t = (
                torch.zeros(bs, self.hidden_size).to(x.device),
                torch.zeros(bs, self.hidden_size).to(x.device)
            )
        else:
            h_t, c_t = init_states

        for t in range(seq_sz):
            x_t = x[:, t, :]

            input_t = torch.concat([x_t, h_t], dim=-1)
            f_t = torch.sigmoid(self.f_gate(input_t))
            i_t = torch.sigmoid(self.i_gate(input_t))
            c_t_ = torch.tanh(self.c_cell(input_t))
            c_t = f_t * c_t + i_t * c_t_

            o_t = torch.sigmoid(self.o_gate(input_t))
            h_t = o_t * torch.tanh(c_t)

            hidden_seq.append(h_t.unsqueeze(0))
        hidden_seq = torch.cat(hidden_seq, dim=0)
        hidden_seq = hidden_seq.transpose(0, 1).contiguous()
        return hidden_seq, (h_t, c_t)

二、RNN

import torch
from torch import nn
import torchvision.datasets as dsets
import torchvision.transforms as transforms
import matplotlib.pyplot as plt

torch.manual_seed(1)

# Hyper Parameters
EPOCH = 1           # 训练整批数据多少次, 为了节约时间, 我们只训练一次
BATCH_SIZE = 64
TIME_STEP = 28      # rnn 时间步数 / 图片高度
INPUT_SIZE = 28     # rnn 每步输入值 / 图片每行像素
LR = 0.01           # learning rate
DOWNLOAD_MNIST = True  # 如果你已经下载好了mnist数据就写上 Fasle

# Mnist 手写数字
train_data = dsets.MNIST(
    root='./mnist/',      # 保存或者提取位置
    train=True,  # this is training data
    transform=transforms.ToTensor(),    # 转换 PIL.Image or numpy.ndarray 成
                                                    # torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间
    download=DOWNLOAD_MNIST,          # 没下载就下载, 下载了就不用再下了
)

# plot one example
# print(train_data.train_data.size())     # (60000, 28, 28)
# print(train_data.train_labels.size())   # (60000)
# plt.imshow(train_data.train_data[0].numpy(), cmap='gray')
# plt.title('%i' % train_data.train_labels[0])
# plt.show()

# 批训练 50samples, 1 channel, 28x28 (50, 1, 28, 28)
train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)

# 为了节约时间, 我们测试时只测试前2000个
test_data = dsets.MNIST(root='./mnist/', train=False, transform=transforms.ToTensor())
test_x = test_data.test_data.type(torch.FloatTensor)[:2000]/255.   # shape (2000, 28, 28) value in range(0,1)
test_y = test_data.test_labels.numpy()[:2000]    # covert to numpy array

class RNN(nn.Module):
    def __init__(self):
        super(RNN, self).__init__()

        self.rnn = nn.RNN(    
            input_size=28,      # 图片每行的数据像素点
            hidden_size=64,     # rnn hidden unit
            num_layers=1,       # 有几层 RNN layers
            batch_first=True,   # input & output 会是以 batch size 为第一维度的特征集 e.g. (batch, time_step, input_size)
        )

        self.out = nn.Linear(64, 10)    # 输出层

    def forward(self, x):
        # 输入的input为,(batch, time_step, input_size)
        # x shape (batch, time_step, input_size)
        # r_out shape (batch, time_step, output_size)
        # h_n shape (n_layers, batch, hidden_size)   LSTM 有两个 hidden states, h_n 是分线, h_c 是主线
        # h_c shape (n_layers, batch, hidden_size)

        r_out, h = self.rnn(x, None)   # None 表示 hidden state 会用全0的 state

        # 选取最后一个时间点的 r_out 输出
        out = self.out(r_out[:, -1, :])
        return out

rnn = RNN()
print(rnn)

optimizer = torch.optim.Adam(rnn.parameters(), lr=LR)   # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss()                       # the target label is not one-hotted

# training and testing
for epoch in range(EPOCH):
    for step, (b_x, b_y) in enumerate(train_loader):    # gives batch data
        b_x = b_x.view(-1, 28, 28)                      # reshape x to (batch, time_step, input_size)

        output = rnn(b_x)                               # rnn output
        loss = loss_func(output, b_y)                   # cross entropy loss
        optimizer.zero_grad()                           # clear gradients for this training step
        loss.backward()                                 # backpropagation, compute gradients
        optimizer.step()                                # apply gradients

        if step % 50 == 0:
            test_output = rnn(test_x)                   # (samples, time_step, input_size)
            pred_y = torch.max(test_output, 1)[1].data.numpy()
            accuracy = float((pred_y == test_y).astype(int).sum()) / float(test_y.size)
            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)

# print 10 predictions from test data
test_output = rnn(test_x[:10].view(-1, 28, 28))
pred_y = torch.max(test_output, 1)[1].data.numpy()
print(pred_y, 'prediction number')
print(test_y[:10], 'real number')

上述中,我们对于h全部以0为输入,此时我们也可以修改为随机参数:

import torch
from torch import nn

class RNN(nn.Module):
    def __init__(self):
        super(RNN, self).__init__()

        self.rnn = nn.RNN(
            input_size=28,      # 图片每行的数据像素点
            hidden_size=64,     # rnn hidden unit
            num_layers=1,       # 有几层 RNN layers
            batch_first=True,   # input & output 会是以 batch size 为第一维度的特征集 e.g. (batch, time_step, input_size)
        )

        self.out = nn.Linear(64, 10)    # 输出层

    def forward(self, x):
        # 输入的input为,(batch, time_step, input_size)
        # x shape (batch, time_step, input_size)
        # r_out shape (batch, time_step, output_size)
        # h_n shape (n_layers, batch, hidden_size)   LSTM 有两个 hidden states, h_n 是分线, h_c 是主线
        # h_c shape (n_layers, batch, hidden_size)

        # 初始化的隐藏元
        # 1个RNN层,batch_size=x.shape[0], 隐藏层的特征维度64
        h_0 = torch.randn(1,x.shape[0], 64)
        r_out, h = self.rnn(x, h_0)   # None 表示 hidden state 会用全0的 state

        # 选取最后一个时间点的 r_out 输出
        out = self.out(r_out[:, -1, :])
        return out

rnn = RNN()
print(rnn)

参数:

nn.RNN是PyTorch中的一个循环神经网络模型。它有几个重要的参数:

input_size:输入的特征维度大小。
hidden_size:隐藏状态的维度大小。
num_layers:RNN层数。
nonlinearity:非线性激活函数,默认为’tanh’。
bias:是否使用偏置,默认为True。
batch_first:如果为True,则输入的维度为(batch_size, seq_length, input_size),否则为(seq_length, batch_size, input_size)。默认为False。
dropout:如果非零,则在输出之间应用丢弃以进行稀疏连接。
bidirectional:如果为True,则使用双向RNN,默认为False。

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

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

相关文章

PCA9306——I2C电平转换模块

PCA930——I2C电平转换 PCA9306是双向I2C总线和SMBus电压电平转换器,具有启用(EN)输入,可从1.0 V到3.6 V和1.8 V到5.5V的电平转换。 PCA9306允许在1.0 V和5V之间的双向电压转换,而不使用方向引脚。开关的低接通状态电…

自监督学习模型发展综述:Inst Disc、Inva Sread、MOCO、SimCLR、BYOL

文章目录 一、Inst Disc研究意义价值个体判别(instance discrimination)特点实现方法如何训练CNN大量负样本如何存储前向传播过程Proximal Regularization超参数设置 二、Inva Sread特点原理如何选取正负样本前向传播过程目标函数模型效果不够好的原因 M…

JDK jps命令复习

之前写过jdk命令工具的博文,下面复习jps命令; jps 是 Java Process Status Tool 的简称,它的作用是为了列出所有正在运行中的 Java 虚拟机进程和相关信息; jps 命令参数 -q 只输出进程 ID,省略主类的名称 -m 输出虚拟机进程启动时传递…

【PyTorch攻略(2/7)】 加载数据集

一、说明 PyTorch提供了两个数据原语:torch.utils.data.DataLoader和torch.utils.data.Dataset,允许您使用预加载的数据集以及您自己的数据。数据集存储样本及其相应的标签,DataLoader 围绕数据集包装一个可迭代对象,以便轻松访问…

大模型助力企业数据驱动,火山引擎数智平台发布AI助手

9月19日,火山引擎在其举办的“V-Tech数据驱动科技峰会”上宣布,火山引擎数智平台VeDI推出“AI助手”,通过接入人工智能大模型,帮助企业提升数据处理和查询分析的效率。即使是不会写代码的运营人员,和大模型对话也能做好…

Vue3封装知识点(三)依赖注入:project和inject详细介绍

Vue3封装知识点(三)依赖注入:project和inject详细介绍 文章目录 Vue3封装知识点(三)依赖注入:project和inject详细介绍一、project和inject是什么二、为了解决什么问题三、project和inject如何使用1.provid…

四川百幕晟科技:抖店精选联盟怎么使用?

近年来,电商平台的兴起让很多人纷纷加入进来,希望通过在网上销售产品来赚取更多的利润。在这个竞争激烈的市场中,如何找到稳定的渠道来推广自己的产品成为了每个卖家的追求。抖店精选联盟是一个不错的选择,可以帮助卖家快速提升销…

数字调度与智能填报:提升效率的新时代

数字化和智能化正深刻改变着各行各业,包括调度和填报领域。传统的手工操作正在被数字调度和智能填报技术所取代,它们正在改变各行各业的工作方式,带来巨大的效率提升和智能化管理。 了解数字调度与智能填报 数字调度:优化资源利用…

C/C++大写字母的判断 2023年5月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C大写字母的判断 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 C/C大写字母的判断 2023年5月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 输入一个字符,判…

原生小程序生命周期,路由跳转,本地存储等详解

原生小程序生命周期,路由跳转,本地存储等详解 生命周期,路由跳转,本地存储等API详解 原生小程序(Native Mini Program)是一种在微信小程序平台上开发的小程序类型,与传统的小程序开发方式&#…

合并两个升序链表,合并后也是升序的

开始时也要判断是否有一个链表本来就是空,如果是,直接返回另外一个链表 代码: struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){if(list1NULL){return list2;}if(list2NULL){return list1;} struct ListN…

VB Function过程求最大公约数和最小公倍数

VB Function过程求最大公约数和最小公倍数 Function过程求最大公约数和最小公倍数 Private Function gys(ByVal m%, ByVal n%) As IntegerDim r As IntegerDo 辗转相除法r m Mod nIf r 0 Then Exit Dom nn rLoopgys n End Function Private Sub Command1_Click()Dim a%, …

【EI会议信息】第五届土木建筑与城市工程国际学术会议(ICCAUE 2023)

第五届土木建筑与城市工程国际学术会议(ICCAUE 2023) 2023 5th International Conference on Civil Architecture and Urban Engineering (ICCAUE 2023) 第五届土木建筑与城市工程国际学术会议(ICCAUE 2023)由天津大学主办&…

听GPT 讲Istio源代码--pilot(5)

File: istio/pilot/pkg/serviceregistry/kube/controller/ambientindex.go ambientindex.go文件位于istio/pilot/pkg/serviceregistry/kube/controller目录中。它是Istio中Kubernetes服务注册表控制器的一部分,负责维护工作负载和服务之间的索引,以便快速…

「聊设计模式」之外观模式(Facade)

🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅! 前言 设计模式是一种通用的解决问题的方式,它不仅仅…

MySQL常见面试题(二)

😀前言 在数据库管理和操作中,我们常常需要深入理解其各种数据类型、特性和索引类型来优化我们的数据库设计和查询效率。其中,字符串类型和它们如何在MySQL中实现和使用成为了一个必不可少的知识点。同时,我们也需要理解新的特性&…

基于Java的高校实习管理系统设计与实现(亮点:实习记录、实习打分、实习作业,功能新颖、老师没见过、当场唬住!)

高校实习管理系统 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序(小蔡coding)2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统主要功能5.1…

若依cloud -【 100 ~ 】

100 分布式日志介绍 | RuoYi 分布式日志就相当于把日志存储在不同的设备上面。比如若依项目中有ruoyi-modules-file、ruoyi-modules-gen、ruoyi-modules-job、ruoyi-modules-system四个应用,每个应用都部署在单独的一台机器里边,应用对应的日志的也单独存…

Vue 3 + TypeScript + jsplumb

网上搜了很久,没有找到基于vue3写的jsplumb,如是写了一个简单版,已开源 Vue 3 TypeScript jsplumb 支持回显,拖拽,连线的基础功能

十分钟理解OSPF路由协议

十分钟理解OSPF路由协议 1.RIP的缺陷以跳数为度量值最大跳数为15更新路由表采用全更新收敛速度慢 2.RIP与OSPF比较OSPF概述运行OSPF协议之前运行OSPF协议之后 3.OSPF协议工作过程1.发现邻居2.建立邻接关系3.传递链路状态信息4.计算路由 4.OSPF分区域管理 有RIP协议,…