【Deep Learning 4】循环神经网络
🌞欢迎来到PyTorch的世界
🌈博客主页:卿云阁💌欢迎关注🎉点赞👍收藏⭐️留言📝
🌟本文由卿云阁原创!
📆首发时间:🌹2024年2月18日🌹
✉️希望可以和大家一起完成进阶之路!
🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!
目录
RNN
RNN的用途
这就说明, 对于预测, 顺序排列是多么重要. 我们可以预测下一个按照一定顺序排列的字, 但是打乱顺序, 我们就没办法分析自己到底在说什么了。
序列数据
我们想象现在有一组序列数据 data 0,1,2,3. 在当预测 result0 的时候,我们基于的是 data0, 同样在预测其他数据的时候, 我们也都只单单基于单个的数据. 每次使用的神经网络都是同一个 NN. 不过这些数据是有关联 顺序的 , 就像在厨房做菜, 酱料 A要比酱料 B 早放, 不然就串味了. 所以普通的神经网络结构并不能让 NN 了解这些数据之间的关联。
处理序列数据的神经网络
我们人类是怎么分析各种事物的关联吧, 最基本的方式,就是记住之前发生的事情. 那我们让神经网络也具备这种记住之前发生的事的能力. 再分析 Data0 的时候, 我们把分析结果存入记忆. 然后当分析 data1的时候, NN会产生新的记忆, 但是新记忆和老记忆是没有联系的. 我们就简单的把老记忆调用过来, 一起分析. 如果继续分析更多的有序数据 , RNN就会把之前的记忆都累积起来, 一起分析.每次 RNN 运算完之后都会产生一个对于当前状态的描述 , state. 我们用简写 S( t) 代替, 然后这个 RNN开始分析 x(t+1) , 他会根据 x(t+1)产生s(t+1), 不过此时 y(t+1) 是由 s(t) 和 s(t+1) 共同创造的. 所以我们通常看到的 RNN 也可以表达成这种样子.
RNN 的应用
RNN 的形式不单单这有这样一种, 他的结构形式很自由. 如果用于分类问题, 比如说一个人说了一句话, 这句话带的感情色彩是积极的还是消极的. 那我们就可以用只有最后一个时间点输出判断结果的RNN.
又或者这是图片描述 RNN, 我们只需要一个 X 来代替输入的图片, 然后生成对图片描述的一段话.
或者是语言翻译的 RNN, 给出一段英文, 然后再翻译成中文.
有了这些不同形式的 RNN, RNN 就变得强大了.
LSTM 循环神经网络
LSTM 是 long-short term memory 的简称, 中文叫做 长短期记忆. 是当下最流行的 RNN 形式之一。之前我们说过, RNN 是在有顺序的数据上进行学习的. 为了记住这些数据, RNN 会像人一样产生对先前发生事件的记忆. 不过一般形式的 RNN 就像一个老爷爷, 有时候比较健忘. 为什么会这样呢?想像现在有这样一个 RNN, 他的输入值是一句话: ‘我今天要做红烧排骨, 首先要准备排骨, 然后…., 最后美味的一道菜就出锅了’, shua ~ 说着说着就流口水了. 现在请 RNN 来分析, 我今天做的到底是什么菜呢. RNN可能会给出“辣子鸡”这个答案. 由于判断失误, RNN就要开始学习 这个长序列 X 和 ‘红烧排骨’ 的关系 , 而RNN需要的关键信息 ”红烧排骨”却出现在句子开头。
与RNN相比,除了输入和前一时刻还要包括当前时刻(日记的信息)
现在我们把St和Ct之间的线看清楚,一条线拆分成三条线,其中包含了,两个更细致的操作,删除旧日记,增添新日记,f1函数就像是一个橡皮擦,根据昨天的记忆St-1和今天的输入Xt,决定要修改日记中的那些记录。 f2函数就像是一个铅笔,根据昨天的记忆St-1和今天的输入Xt,增加日记中的那些记录。f1和 f2进行运算得到新的日记啦。LSTM 就像延缓记忆衰退的良药, 可以带来更好的结果。
循环神经网络实战 (分类)
RNN模型
和以前一样, 我们用一个 class 来建立 RNN 模型. 这个 RNN 整体流程是
(input0, state0)
->LSTM
->(output0, state1)
;(input1, state1)
->LSTM
->(output1, state2)
;- ...
(inputN, stateN)
->LSTM
->(outputN, stateN+1)
;outputN
->Linear
->prediction
. 通过LSTM
分析每一时刻的值, 并且将这一时刻和前面时刻的理解合并在一起, 生成当前时刻对前面数据的理解或记忆. 传递这种理解给下一时刻分析.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): # 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) """ RNN ( (rnn): LSTM(28, 64, batch_first=True) (out): Linear (64 -> 10) ) """
MNIST手写数据
import torch from torch import nn import torchvision.datasets as dsets import torchvision.transforms as transforms import matplotlib.pyplot as plt import torchvision import torch.utils.data as Data torch.manual_seed(1) # reproducible # 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 = torchvision.datasets.MNIST( root='./mnist/', # 保存或者提取位置 train=True, # this is training data transform=torchvision.transforms.ToTensor(), # 转换 PIL.Image or numpy.ndarray 成 # torch.FloatTensor (C x H x W), 训练的时候 normalize 成 [0.0, 1.0] 区间 download=DOWNLOAD_MNIST, # 没下载就下载, 下载了就不用再下了 )
我们除了训练数据, 还给一些测试数据, 测试看看它有没有训练好.
test_data = torchvision.datasets.MNIST(root='./mnist/', train=False) # 批训练 50samples, 1 channel, 28x28 (50, 1, 28, 28) train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True) # 为了节约时间, 我们测试时只测试前2000个 test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)[:2000]/255. # shape from (2000, 28, 28) to (2000, 1, 28, 28), value in range(0,1) test_y = test_data.test_labels[:2000]
训练
我们将图片数据看成一个时间上的连续数据, 每一行的像素点都是这个时刻的输入, 读完整张图片就是从上而下的读完了每行的像素点. 然后我们就可以拿出 RNN 在最后一步的分析值判断图片是哪一类了.
optimizer = torch.optim.Adam(rnn.parameters(), lr=LR) # optimize all parameters loss_func = nn.CrossEntropyLoss() # the target label is not one-hotted # training and testing for epoch in range(EPOCH): for step, (x, b_y) in enumerate(train_loader): # gives batch data b_x = 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 test_output = rnn(test_x[:10].view(-1, 28, 28)) pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze() print(pred_y, 'prediction number') print(test_y[:10], 'real number')
循环神经网络实战 (回归)
下面是一个简单的用于回归问题的循环神经网络 (RNN) 案例,使用 PyTorch。我们将使用一个简单的正弦波作为输入序列,目标是预测下一个时间步的值。我们将使用均方误差损失来度量预测值与实际值之间的差异。
import torch import torch.nn as nn import numpy as np import matplotlib.pyplot as plt # 定义 RNN 模型 class SimpleRNN(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(SimpleRNN, self).__init__() self.rnn = nn.RNN(input_size, hidden_size, batch_first=True) self.fc = nn.Linear(hidden_size, output_size) def forward(self, x): out, _ = self.rnn(x) out = self.fc(out[:, -1, :]) # 取最后一个时间步的输出 return out # 创建模型实例 input_size = 1 hidden_size = 32 output_size = 1 rnn = SimpleRNN(input_size, hidden_size, output_size) # 定义损失函数和优化器 criterion = nn.MSELoss() optimizer = torch.optim.Adam(rnn.parameters(), lr=0.01) # 生成正弦波数据 seq_length = 100 time_steps = np.linspace(0, 10, seq_length) data = np.sin(time_steps) # 转换数据为 PyTorch 张量 data = torch.FloatTensor(data).view(-1, 1, 1) # 划分训练集和测试集 train_size = int(len(data) * 0.67) train_data, test_data = data[:train_size], data[train_size:] # 准备数据,构造输入序列和对应的目标值 def create_inout_sequences(input_data, tw): inout_seq = [] L = len(input_data) for i in range(L-tw): train_seq = input_data[i:i+tw] train_label = input_data[i+tw:i+tw+1] inout_seq.append((train_seq ,train_label)) return inout_seq train_inout_seq = create_inout_sequences(train_data, 10) test_inout_seq = create_inout_sequences(test_data, 10) # 训练模型 num_epochs = 150 for epoch in range(num_epochs): for seq, labels in train_inout_seq: optimizer.zero_grad() rnn.train() y_pred = rnn(seq) single_loss = criterion(y_pred, labels) single_loss.backward() optimizer.step() if (epoch+1) % 10 == 0: print(f'Epoch {epoch+1}/{num_epochs}, Loss: {single_loss.item()}') # 在测试集上评估模型 rnn.eval() test_losses = [] with torch.no_grad(): for seq, labels in test_inout_seq: y_pred = rnn(seq) test_loss = criterion(y_pred, labels) test_losses.append(test_loss.item()) # 可视化结果 plt.plot(test_losses, label='Test Loss') plt.xlabel('Test Sequence') plt.ylabel('MSE Loss') plt.legend() plt.show()
原文地址:https://blog.csdn.net/zzqingyun/article/details/136145135
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!