循环神经网络RNN与LSTM学习(一)

1 word2vec

1.1 理解torch.nn.Embedding

  • 全部参数如下:
torch.nn.Embedding(num_embeddings: int, embedding_dim: int, padding_idx: Optional[int] = None,
                 max_norm: Optional[float] = None, norm_type: float = 2., scale_grad_by_freq: bool = False,
                 sparse: bool = False, _weight: Optional[Tensor] = None)
  • num_embedding:词典的大小尺寸,比如说下面代码中只有两个词,“hello"和"world”,所以说这里的词典尺寸设置为2
  • embedding_dim:嵌入向量的维度,即用多少维来表示一个符号。这里是用5维,可以看到最后的输出结果就是将"hello"映射成了一个5维的向量
import torch

word_to_ix = {"hello": 0, "world": 1}

lookup_tensor = torch.tensor([word_to_ix["hello"]], dtype=torch.long)

embeds = torch.nn.Embedding(2, 5)
hello_embed = embeds(lookup_tensor)
print(hello_embed)

  • 输出结果:
    在这里插入图片描述
  • 可以作为知识储备,可以用这个做自然语言处理

2 RNN 的梯度计算

在这里插入图片描述

  • 求梯度
    在这里插入图片描述

  • 所以说,RNN 在步数epoch一多的情况下,必然会出现梯度消失或者是梯度爆炸的问题。

  • 我们只能使用有限的步数来解决这个问题!

2.1 什么是梯度爆炸

  • 梯度值不断发散,慢慢到了NAN
  • 可以用梯度剪裁的方式,解决一些梯度爆炸的问题,

2.2 什么是梯度消失

  • 并不是梯度变成0
  • 而是历史梯度不断衰减,当步长越差,其反馈梯度信号越不显著,最后可能完全没有作用了,这就是说RNN对长距离语义的捕捉能力失效了,就是梯度消失的真正含义!

3 LSTM

在这里插入图片描述

4 常见的面试题——LSTM是如何解决RNN梯度消失和梯度爆炸问题?

  • 上面我们已经讨论知道,RNN中总的梯度是不会消失的。但是历史梯度会越传越弱,梯度被近距离梯度主导,导致模型难以学习到远距离的依赖关系。

  • LSTM中的forget门,input门,output门,而其中关键的是forget门部件。如果forget门接近1,远距离的梯度不会消失;如果forget门接近0,则是表示模型学习到了某种新特征,选择对前面的数据进行遗忘。

  • LSTM仍然有可能发生梯度消失,但是概率会远远小于RNN。

5 利用PyTorch RNN实现MNIST手写字体识别

  • 之前已经用CNN实现过了,现在用RNN实现一下。(这里不掺杂模型优劣的概念,强调实现)

5.0 流程介绍

1. 加载数据集
2. 创建模型类
3. 初始化模型类
4. 初始化损失类、优化器
5. 训练模型

5.1 加载数据集

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import numpy as np
import pandas as pd

trainsets = datasets.MNIST(root='./data', train=True, download=True, transform=transforms.ToTensor())
testsets = datasets.MNIST(root='./data', train=False, download=False, transform=transforms.ToTensor())

class_names = trainsets.classes
print(class_names)  # 查看训练集的类别/标签

print(trainsets.data.shape)  # 查看训练集的大小
print(testsets.data.shape)  # 查看测试集的大小

print(trainsets.targets.shape)  # 查看训练集标签的大小
print(testsets.targets.shape)  # 查看测试集标签的大小
  • 输出情况:
['0 - zero', '1 - one', '2 - two', '3 - three', '4 - four', '5 - five', '6 - six', '7 - seven', '8 - eight', '9 - nine']
torch.Size([60000, 28, 28])
torch.Size([10000, 28, 28])
torch.Size([60000])
torch.Size([10000])

5.2 定义超参数

BATCH_SIZE = 32  # 每批读取数据的大小
EPOCHS = 10  # 训练10轮

5.3 创建数据集的可迭代对象

train_loader = torch.utils.data.DataLoader(datasets=trainsets, batch_size=BATCH_SIZE, shuffle=True)
test_loader = torch.utils.data.DataLoader(datasets=testsets, batch_size=BATCH_SIZE, shuffle=True)

5.4 查看一批batch的数据

# 查看一批batch的数据
images, labels = next(iter(test_loader))
print(images.shape)
print(labels.shape)
  • 输出结果:
torch.Size([32, 1, 28, 28])
torch.Size([32])
  • 显示图片的代码:
import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import torchvision.datasets as datasets
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


trainsets = datasets.MNIST(root='./data', train=True, download=True, transform=transforms.ToTensor())
testsets = datasets.MNIST(root='./data', train=False, download=False, transform=transforms.ToTensor())

class_names = trainsets.classes
print(class_names)  # 查看训练集的类别/标签

print(trainsets.data.shape)  # 查看训练集的大小
print(testsets.data.shape)  # 查看测试集的大小

print(trainsets.targets.shape)  # 查看训练集标签的大小
print(testsets.targets.shape)  # 查看测试集标签的大小

BATCH_SIZE = 32  # 每批读取数据的大小
EPOCHS = 10  # 训练10轮

train_loader = torch.utils.data.DataLoader(dataset=trainsets, batch_size=BATCH_SIZE, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=testsets, batch_size=BATCH_SIZE, shuffle=True)

# 查看一批batch的数据
images, labels = next(iter(test_loader))
print(images.shape)
print(labels.shape)


# 定义函数,显示一批数据
def imshow(inp, title=None):
    inp = inp.numpy().transpose(1, 2, 0)
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    inp = std * inp + mean
    inp = np.clip(inp, 0, 1)  # 将像素值压缩在(0,1)之间
    plt.imshow(inp)
    if title is not None:
        plt.title(title)
    plt.show()


# 网格显示
out = torchvision.utils.make_grid(images)
imshow(out)

在这里插入图片描述

5.3 模型定义

class RNN_Model(nn.Model):
    def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
        super(RNN_Model, self).__init__()
        self.hidden_dim = hidden_dim
        self.layer_dim = layer_dim
        # RNN层
        self.rnn = nn.RNN(input_dim, hidden_dim, layer_dim, batch_first=True, nonlinearity='relu')
        # 全连接层
        self.fc = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        # (layer_dim, batch_size, hidden_dim)
        h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_().to(device)
        # 分离隐藏状态,防止梯度爆炸
        out, hn = self.rnn(x, h0.detach())
        out = self.fc(out[:, -1, :])
        return out

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值