LSTM基本理论及手写数字识别实战应用(pytorch)

您所在的位置:网站首页 电压字母代号手写 LSTM基本理论及手写数字识别实战应用(pytorch)

LSTM基本理论及手写数字识别实战应用(pytorch)

2024-07-17 10:30:49| 来源: 网络整理| 查看: 265

目录 LSTM介绍LSTM的特点(与RNN的区别)具体实现流程公式汇总及总结 LSTM实现手写数字识别(pytorch代码)导入环境定义超参数训练和测试数据定义定义LSTM模型LSTM模型训练和预测

LSTM介绍 LSTM的特点(与RNN的区别)

特点:加入一个门控机制,该被记住的信息会一直传递,不该记的会被“门”阶段。由三个具有sigmoid激活函数的全连接层处理, 以计算输入门、遗忘门和输出门的值。 因此,这三个门的值都在(0,1)的范围内。

LSTM的关键就是细胞状态,水平线在图上方贯穿运行,细胞状态类似于传送带。直接在整个链上运行,只有少量的线性交互,信息在上面流传保持不变会很容易。

在这里插入图片描述

LSTM通过门结构来去除或增加信息到细胞状态的能力。是一种让信息选择通过的方法。包含一个sigmoid神经网络和一个点乘操作,其中,sigmoid输出0-1的数值,描述每个部分有多少量可以通过,0表示不允许任何量通过,1表示允许任意量通过。(LSTM通过三个门来保护和控制细胞状态)

具体实现流程

第一步:

cell state是否传递到下一个cell state 是通过sigmoid layer (遗忘门) 决定的。sigmoid后结果为0/1,1表示保留cell state, 0表示遗忘以前记忆的数据 在这里插入图片描述

第二步:

也是一个sigmoid layer被成为输入门(it),决定了我们需要更新哪些值,还有有一个tanh layer用来制造新的候选值向量(Ct),最后将it和Ct进行点乘。 在这里插入图片描述

第三步:

ft,抛弃需要忘记的之前的信息,然后加上我们需要记录的信息。如下式所示,ft*Ct-1表示的含义为,忘记上一层的部分单元状态。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RwFWJ2Bi-1649292695221)(C:\Users\pc\AppData\Roaming\Typora\typora-user-images\image-20220402120114657.png)]

第四步:

最后决定,哪些需要被输出,这些输出是基于cell state的。用sigmoid layer决定应该输出哪一部分cell state.将单元状态放入tanh函数中使得结果处于(-1,1)区间中。并将tanh(Ct)与输出部分Ot相乘,以此控制我们想要输出的部分。

公式汇总及总结

在这里插入图片描述

ht是t时刻隐藏层状态,Ct是t时刻的单元状态,xt是输入值

it,ft,ot是输入、遗忘、输出门

关于LSTM的认识:LSTM神经元在时间维度上向后传递了两份信息:cell state和hidden state。

hidden state是cell state经过一个神经元和一道输出门后得到的,因此hidden state里包含的记忆,实际上是cell state衰减之后的内容。另外,cell state在一个衰减较少的通道里沿时间轴传递,对时间跨度较大的信息的保持能力比hidden state要强很多。

因此,实际上hidden state里存储的,主要是近期记忆;cell state里存储的,主要是远期记忆。cell state的存在,使得LSTM得以对长依赖进行很好地刻画。(过去的信息直接在Cell运行,当下的决策或者说特征选择在Hidden State里面运行)

LSTM实现手写数字识别(pytorch代码)

这里仅仅是将LSTM应用于手写数字识别(图像的处理)这一经典问题,体现网络结构和训练过程方便大家学习,实际上RNN、LSTM等网络一般用于处理序列问题,而CNN等网络被用来处理图像问题(可以保存空间特征)

导入环境 import torch from torch import nn import torchvision.datasets import torchvision.transforms as transforms import matplotlib.pyplot as plt import warnings import numpy as np warnings.filterwarnings('ignore') torch.manual_seed(1) 定义超参数 epoch = 2 batch_size = 64 time_step = 28 #时间步数(图片高度)(因为每张图像为28*28,而每一个序列长度为1*28,所以总共是28个1*28) input_size = 28 #每步输入的长度(每行像素的个数) lr = 0.01 download_mnist = True num_classes = 10 #总共有10类 hidden_size = 128 #隐层大小 num_layers = 1 训练和测试数据定义 #MINIST train_data = torchvision.datasets.MNIST( root='./mnist', train=True, transform=torchvision.transforms.ToTensor(), download=download_mnist, ) test_data = torchvision.datasets.MNIST( root='./mnist', train=False, transform=torchvision.transforms.ToTensor(), download=download_mnist, ) print(train_data.train_data.size()) print(train_data.train_labels.size()) plt.imshow(train_data.train_data[0].numpy(), cmap='gray') plt.title("MNIST:%i" % train_data.train_labels[0]) plt.show() torch.Size([60000, 28, 28]) torch.Size([60000])

加载器数据处理:

train_loader = torch.utils.data.DataLoader(dataset=train_data, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(dataset=test_data, batch_size=batch_size, shuffle=False) data = next(iter(train_loader)) #train_loader是迭代器 print(data[0].shape) #data的第一个元素为64个(1*28*28的图像) print(data[1].shape) #data的第二个元素为64个标签 # print("data[0]", data[0]) # print("data[1]", data[1]) print(np.array(data).shape) #每次迭代为64张图片由batch_size决定, 1为通道数(灰白图片) torch.Size([64, 1, 28, 28]) torch.Size([64]) (2,) for step, (b_x, b_y) in enumerate(train_loader): #遍历数据和标签 print(b_x.shape) b_x = b_x.view(-1, 28, 28) #将tensor拉成(64*28*28) print(b_x.shape) print(b_y.shape) print(b_x[0].shape) print(b_y[0]) break torch.Size([64, 1, 28, 28]) torch.Size([64, 28, 28]) torch.Size([64]) torch.Size([28, 28]) tensor(9) test_data = torchvision.datasets.MNIST(root='./mnist/', train=False, transform=transforms.ToTensor()) test_x = test_data.test_data.type(torch.FloatTensor)[:2000]/255 test_y = test_data.test_labels.numpy()[:2000] print(test_x.shape) print(test_y.shape) torch.Size([2000, 28, 28]) (2000,) 定义LSTM模型

(input0, output0) -> LSTM -> (output0, state1) (input1, output1) -> LSTM -> (output1, state2) … (inputN, outputN) -> LSTM -> (outputN, stateN+1) outputN -> Lineaer -> prediction 通过LSTM分析每一刻的值,并且将这一时刻和前面时刻的理解合并在一起,生成当前时刻对前面数据的理解或记忆

class RNN(nn.Module): def __init__(self, input_size, hidden_size, num_layers, num_classes): super(RNN, self).__init__() #LSTM层 self.rnn_layer = nn.LSTM( input_size=input_size, #每行的像素点个数 hidden_size=hidden_size, num_layers=num_layers, #层数 batch_first=True, #input和output会以batch_size为第一维度 ) #输出层 self.linear_layer = nn.Linear(hidden_size, num_classes) def forward(self, x): #x.shape (batch, time_step, input_size) #rnn_out.shape (batch, time_step, output_size) #h_n (n_layers, batch, hidden_size) LSTM有两个hidden states, h_c是分线, h_c是主线 #c_n (n_layers, batch, hidden_size) rnn_output, (h_n, c_n) = self.rnn_layer(x, None) #None表示hidden state 会用全0的state #选择lstm_output[-1] 也就是最后一个输出,因为每个cell都会有输出,但我们只关心最后一个(分类问题) #选取最后一个时间节点的rnn_output输出 #这里的 rnn_output[:, -1, :]的值也是h_n的值 output = self.linear_layer(rnn_output[:, -1, :]) return output rnn = RNN(input_size, hidden_size, num_layers, num_classes) print(rnn) RNN( (rnn_layer): LSTM(28, 128, batch_first=True) (linear_layer): Linear(in_features=128, out_features=10, bias=True) ) LSTM模型训练和预测 #定义优化器和损失函数 optimizer = torch.optim.Adam(rnn.parameters(), lr=lr) loss_func = nn.CrossEntropyLoss() # device = 'cuda' if torch.cuda.is_available() else 'cpu' # rnn.to(device) #将模型送入cuda # print('devices = ', device)

在分类问题中,通常需要使用max()函数对softmax函数的输出值进行操作,求出预测值索引,然后与标签进行比对,计算准确率。 函数: output = torch.max(input, dim) 输入: input是softmax函数输出的一个tensor dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值 输出: 函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。

# print(len(train_loader)) #训练流程 for i in range(epoch): rnn.train() total_batch = len(train_loader) run_loss = 0.0 for step, (images, labels) in enumerate(train_loader): # images, labels = images.to(device), labels.to(device) images = images.view(-1, 28, 28) #运行模型 outputs = rnn(images) #损失函数 loss = loss_func(outputs, labels) #清除梯度 optimizer.zero_grad() #反向传播 loss.backward() #更新 optimizer.step() run_loss = loss.item() if(step + 1) % 100 == 0: print('Epoch[{}/{}], step[{}/{}], train_loss:{}'.format(i+1, epoch, step+1, total_batch, '%.4f' % run_loss)) #训练结束 #对模型进行测试 with torch.no_grad(): rnn.eval() correct = 0 total = 0 for i, (images, labels) in enumerate(test_loader): # images, labels = images.to(device), labels.to(device) images = images.view(-1, 28, 28) outputs = rnn(images) #output(64, 10) 输出为(batch_size, output_size) 因为我们只关心最后一维输出 #输出是每一批64个样本,每个样本有10个概率值(对应十个分类) 将概率值最大数值的所在类作为当前的预测结果 if i == 0: print("输出的结果", ) print("输出的维度", outputs.shape) _, prediction = torch.max(outputs.data, 1) #prediction保存最大值的索引,也就相当于标签数0-9 if i == 0: print("最大值和索引", (_, prediction)) total += labels.size(0) correct += (prediction == labels).sum().item() #输出结果 print(total, correct) print("Test accuracy of model in test images:{}".format(correct/total)) torch.save(rnn.state_dict(), 'rnn.pkl')

训练结果:

Epoch[1/2], step[100/938], train_loss:0.8388 Epoch[1/2], step[200/938], train_loss:0.5867 Epoch[1/2], step[300/938], train_loss:0.2973 Epoch[1/2], step[400/938], train_loss:0.2541 Epoch[1/2], step[500/938], train_loss:0.0706 Epoch[1/2], step[600/938], train_loss:0.1402 Epoch[1/2], step[700/938], train_loss:0.2660 Epoch[1/2], step[800/938], train_loss:0.1185 Epoch[1/2], step[900/938], train_loss:0.1742 输出的结果 输出的维度 torch.Size([64, 10]) 最大值和索引 (tensor([ 8.9605, 7.0959, 10.5307, 6.7607, 6.3854, 9.9979, 5.8245, 4.1132, 5.9978, 4.8795, 9.1994, 9.8002, 7.5107, 6.8908, 9.3948, 6.6050, 6.8807, 9.0425, 3.7695, 6.1420, 2.9081, 9.6258, 9.2399, 7.6210, 5.8143, 7.2229, 7.2480, 6.2991, 8.4457, 9.9901, 7.3378, 10.5309, 6.9480, 3.4193, 7.5618, 6.5634, 7.3954, 9.9699, 4.1137, 9.4361, 9.4986, 7.1948, 5.9212, 3.2806, 6.1133, 6.3882, 7.0285, 7.2906, 5.1487, 6.1292, 10.3341, 5.6718, 7.6015, 5.9462, 10.0196, 6.7889, 6.5652, 10.1855, 6.0312, 4.4976, 7.1902, 3.6839, 3.4036, 4.0903]), tensor([7, 2, 1, 6, 4, 1, 4, 9, 6, 9, 0, 6, 9, 0, 1, 5, 9, 7, 3, 4, 5, 6, 6, 5, 4, 0, 7, 4, 0, 1, 3, 1, 3, 4, 7, 2, 7, 1, 2, 1, 1, 7, 4, 2, 3, 5, 1, 2, 4, 4, 6, 3, 5, 5, 6, 0, 4, 1, 9, 5, 7, 8, 5, 2])) 10000 9490 Test accuracy of model in test images:0.949 Epoch[2/2], step[100/938], train_loss:0.1428 Epoch[2/2], step[200/938], train_loss:0.0757 Epoch[2/2], step[300/938], train_loss:0.0949 Epoch[2/2], step[400/938], train_loss:0.1465 Epoch[2/2], step[500/938], train_loss:0.0187 Epoch[2/2], step[600/938], train_loss:0.0690 Epoch[2/2], step[700/938], train_loss:0.1198 Epoch[2/2], step[800/938], train_loss:0.1921 Epoch[2/2], step[900/938], train_loss:0.0716 输出的结果 输出的维度 torch.Size([64, 10]) 最大值和索引 (tensor([ 7.3178, 10.6847, 9.3740, 9.1583, 8.6876, 9.2710, 8.7351, 7.1284, 3.9576, 8.4149, 10.2904, 6.8698, 8.2608, 8.7133, 9.3011, 10.0828, 7.2414, 7.4259, 3.6580, 9.1079, 8.4237, 8.2516, 7.3270, 9.8116, 8.6081, 10.0169, 6.0650, 8.7936, 9.6732, 5.8133, 10.1085, 5.3593, 10.7706, 4.9747, 6.7490, 10.1497, 7.4211, 5.8098, 7.0112, 10.3313, 6.5496, 7.1471, 7.7012, 6.9186, 9.2815, 8.7697, 7.8598, 9.9610, 6.2150, 8.2662, 7.9309, 8.6589, 9.6622, 8.4956, 5.3241, 8.6748, 8.7984, 8.1394, 6.9538, 5.7582, 9.1990, 7.1813, 4.1776, 7.4175]), tensor([7, 2, 1, 0, 4, 1, 4, 9, 5, 9, 0, 6, 9, 0, 1, 5, 9, 7, 3, 4, 9, 6, 6, 5, 4, 0, 7, 4, 0, 1, 3, 1, 3, 4, 7, 2, 7, 1, 2, 1, 1, 7, 4, 2, 3, 5, 1, 2, 4, 4, 6, 3, 5, 5, 6, 0, 4, 1, 9, 5, 7, 8, 9, 3])) 10000 9794 Test accuracy of model in test images:0.9794


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


    图片新闻

    实验室药品柜的特性有哪些
    实验室药品柜是实验室家具的重要组成部分之一,主要
    小学科学实验中有哪些教学
    计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
    实验室各种仪器原理动图讲
    1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
    高中化学常见仪器及实验装
    1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
    微生物操作主要设备和器具
    今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
    浅谈通风柜使用基本常识
     众所周知,通风柜功能中最主要的就是排气功能。在

    专题文章

      CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭