• 【Pytorch深度学习实战】(6)递归神经网络(RNN)


     🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎

    📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃

    🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​

    📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

     🖍foreword

    ✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

    如果你对这个系列感兴趣的话,可以关注订阅哟👋

    循环神经网(Recurrent Neural Network,RNN)

    RNN,循环神经网络,也有人将它翻译为递归神经网络。从这个名字就可以想到,它的结构中存在着“环”。

    确实,RNN 和 NN/DNN 的数据单一方向传递不同。RNN 的神经元接受的输入除了“前辈”的输出,还有自身的状态信息,其状态信息在网络中循环传递。

    RNN 的结构用图形勾画出来,是下图这样的:

    图 1

    注意:图中的 AA 并不是一个神经元,而是一个神经网络块,可以简单理解为神经网络的一个隐层。

    RNN 的这种结构,使得它很适合应用于序列数据的处理,比如文本、语音、视频等。这类数据的样本间存在顺序关系(往往是时序关系),每个样本和它之前的样本存在关联。

    RNN 把所处理的数据序列视作时间序列,在每一个时刻 tt,每个 RNN 的神经元接受两个输入:当前时刻的输入样本 xtxt,和上一时刻自身的输出 ht-1 。

    t 时刻的输出:

    图1经过进一步简化,将隐层的自连接重叠,就成了下图:

    图2

    上图展示的是最简单的 RNN 结构,此外 RNN 还存在着很多变种,比如双向 RNN(Bidirectional RNN),深度双向 RNN(Deep Bidirectional RNN)等。

    RNN 的作用最早体现在手写识别上,后来在语音和文本处理中也做出了巨大的贡献,近年来也不乏将其应用于图像处理的尝试。

    长短时记忆(Long Short Term Memory,LSTM)

    LSTM 可以被简单理解为是一种神经元更加复杂的 RNN,处理时间序列中当间隔和延迟较长时,LSTM 通常比 RNN 效果好。

    相较于构造简单的 RNN 神经元,LSTM 的神经元要复杂得多,每个神经元接受的输入除了当前时刻样本输入,上一个时刻的输出,还有一个元胞状态(Cell State),LSTM 神经元结构请参见下图:

    LSTM 神经元中有三个门。

    遗忘门(Forget Gate):接受xt 和 0ht-1 为输入,输出一个0到11之间的值,用于决定在多大程度上保留上一个时刻的元胞状态ct-1。1表示全保留,0表示全放弃。

    输入门(Input Gate): 用于决定将哪些信息存储在这个时刻的元胞状态 ct ct 中。

    输出门(Output Gate):用于决定输出哪些信息。

     递归神经网络Pytorch的实现

    1. import torch
    2. import torch.nn as nn
    3. import torchvision
    4. import torchvision.transforms as transforms
    5. # 设备配置
    6. device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    7. # 超参数
    8. sequence_length = 28
    9. input_size = 28
    10. hidden_size = 128
    11. num_layers = 2
    12. num_classes = 10
    13. batch_size = 100
    14. num_epochs = 2
    15. learning_rate = 0.01
    16. # MNIST 数据集
    17. train_dataset = torchvision.datasets.MNIST(root='../../data/',
    18. train=True,
    19. transform=transforms.ToTensor(),
    20. download=True)
    21. test_dataset = torchvision.datasets.MNIST(root='../../data/',
    22. train=False,
    23. transform=transforms.ToTensor())
    24. # 数据加载器
    25. train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
    26. batch_size=batch_size,
    27. shuffle=True)
    28. test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
    29. batch_size=batch_size,
    30. shuffle=False)
    31. # 循环神经网络(多对一)
    32. class RNN(nn.Module):
    33. def __init__(self, input_size, hidden_size, num_layers, num_classes):
    34. super(RNN, self).__init__()
    35. self.hidden_size = hidden_size
    36. self.num_layers = num_layers
    37. self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
    38. self.fc = nn.Linear(hidden_size, num_classes)
    39. def forward(self, x):
    40. # 设置初始隐藏和单元格状态
    41. h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)
    42. c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)
    43. # 前向传播 LSTM
    44. out, _ = self.lstm(x, (h0, c0)) # out: tensor of shape (batch_size, seq_length, hidden_size)
    45. # 解码上一个时间步的隐藏状态
    46. out = self.fc(out[:, -1, :])
    47. return out
    48. model = RNN(input_size, hidden_size, num_layers, num_classes).to(device)
    49. # 损失和优化器
    50. criterion = nn.CrossEntropyLoss()
    51. optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
    52. # 训练模型
    53. total_step = len(train_loader)
    54. for epoch in range(num_epochs):
    55. for i, (images, labels) in enumerate(train_loader):
    56. images = images.reshape(-1, sequence_length, input_size).to(device)
    57. labels = labels.to(device)
    58. # 前向传播
    59. outputs = model(images)
    60. loss = criterion(outputs, labels)
    61. # 向后和优化
    62. optimizer.zero_grad()
    63. loss.backward()
    64. optimizer.step()
    65. if (i+1) % 100 == 0:
    66. print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'
    67. .format(epoch+1, num_epochs, i+1, total_step, loss.item()))
    68. # 测试模型
    69. model.eval()
    70. with torch.no_grad():
    71. correct = 0
    72. total = 0
    73. for images, labels in test_loader:
    74. images = images.reshape(-1, sequence_length, input_size).to(device)
    75. labels = labels.to(device)
    76. outputs = model(images)
    77. _, predicted = torch.max(outputs.data, 1)
    78. total += labels.size(0)
    79. correct += (predicted == labels).sum().item()
    80. print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))
    81. # 模型保存
    82. torch.save(model.state_dict(), 'model.ckpt')

  • 相关阅读:
    23种设计模式
    重磅!flink-table-store 将作为独立数据湖项目重新加入 Apache
    恢复出厂设置,手机数据还能“复活”?
    马斯克雷军竞速「机器人」背后,一场机器革命正在发生 | 幂集创新
    dubbogo-02 将服务注册到nacos
    Vue学习笔记(一)
    leaflet教程039: 只显示一屏地图,设定范围不让循环延展
    Git工作流
    运营-20.产品社区化和内容化
    (仿牛客社区项目)Java开发笔记0:项目目录
  • 原文地址:https://blog.csdn.net/sikh_0529/article/details/126922788