当前位置:   article > 正文

【PyTorch】深度学习实践之 RNN基础篇——实现RNN_pytorch rnn

pytorch rnn

1. DNN

[图片]

深度神经网络是稠密网络,Dense连接就是指全连接,有很多线性层对输入数据进行空间上的变换,又叫DNN。比如预测天气,假设输入前3天的特征(温度、气压、雨天),预测第4天是否下雨?

第一种方法:把x1,x2,x3拼成有9个维度的长向量,然后去训练最后一天是否有雨。用全连接稠密网络进行预测,如果输入序列很长,而且每一个序列维度很高的话,对网络训练有很大挑战,因为稠密网络(全连接网络)实际上权重是最多的。
[图片]

对比CNN网络和DNN网络的权重数量:全连接网络的权重是最多的。

[图片]

对于卷积层:比如输入通道是128个,输出通道是64个,如果用5x5的卷积,权重数就是 2564188=204800,卷积层的输入输出只与通道数和卷积核的大小有关,全连接层和变换之后的数据大小有关,比如3阶张量经过一系列的卷积变换还剩下4096个元素,4096我们很少直接降成1维或者10维,而是先降成1024维,全连接层的权重为4096*1024=4194304,所以相比起来,卷积层的权重并不多,而全连接层的权重较多。全连接层是在网络的全部参数中占大头的。

CNN在做卷积的时候,它的卷积核是共享的。所以它的权重数量比较少,它并不是图像上的每一个像素要和下一层的featureMap建立连接,权重数量就少。处理视频的时候,每一帧就少一张图像,我们需要把一组图像做成一个集合,如果用全连接网络的话,使用到的权重的数量就是一个天文数字,极大可能难以处理。

RNN是用来专门处理带有序列的数据,也会使用权重共享来减少权重的数量。它把x1,x2,x3看成是一个序列,不仅考虑x1,x2之间的连接关系,还考虑x1,x2的时间上的先后顺序(x2依赖于x1,x3依赖于x2),下一天的天气状况部分依赖于前一天的天气状况,RNN主要处理这种具有序列连接的数据。

[图片]

数据是有先后顺序进行连接的,也就是当天数据会依赖之前数据。比如股市、金融数据、自然语言(我爱北京天安门)


2. RNN

[图片]

RNN是循环神经网络,RNN其实是对线性层的复用。RNN Cell本质是一个线性层(linear),把一个维度映射到另一个维度(比如把输入的3维向量xt 变成输出5维向量 ht )。 这个线性层与普通的线性层的区别是这个线性层是共享的。

如上图右侧的结构是对左侧结构的展开。h0是一种先验知识,如果知道输出的维度,可以选择将其每一个维度都设置为0。也可以使用CNN+fc的网络去生成先验知识,实现图像到文本的转换。

RNN相当于一个形成层,所以可以简单的用代码进行描述:

linear = Linear()
h = 0
for x in X:
    h = linear(x,h)
  • 1
  • 2
  • 3
  • 4

相当于

h1 = linear(x1,h0)
h2 = linear(x2,h1)
h3 = linear(x3,h2)
  • 1
  • 2
  • 3

3. RNN Cell 具体计算过程

  • 输入xt ,h_t-1做线性变换。 x_t的维度是input_size,h_t-1的维度是hidden_size,输出ht的维度是hidden_size。需要先把xt的维度变成hidden_size,所以W_ih应该是一个 hidden_sizeinput_size的矩阵,W_ihx_t得到一个 hidden_size的矩阵(就是维度为hidden_size的向量),bih是偏置。输入权重矩阵Whh是一个hidden_size*hidden_size的矩阵。
  • W_hhh_t-1+b_hh和W_ihx_t+b_ih相加 ,把信息融合起来。
  • 再用tanh做激活,得到这一层的隐藏层输出h_t。

完整的定义RNN:将RNN cell以循环的形式一个一个送进去,然后依次算出隐藏层的过程,称之为循环神经网络。
[图片]

循环神经网络的激活函数用的是tanh(为什么呢?因为tanh的取值在-1到+1之间)

补充:Tanh的诞生比Sigmoid晚一些,sigmoid函数我们提到过有一个缺点就是输出不以0为中心,使得收敛变慢的问题。而Tanh则就是解决了这个问题。

4. Pytorch实现RNN

4.1 创建RNNcell再写循环

主要是确定输入的维度和隐藏层的维度

  • RNN_cell实现
    [图片]

如上图,RNN本质上还是一个线性层,要弄清楚维度。代码如下:

# pytorch实现
cell = torch.nn.RNNcell(input_size=input_size,hidden_size=hidden_size)
hidden = cell(input,hidden) # h1 = cell(x1,h0)
  • 1
  • 2
  • 3

举个例子:
输入有4个特征,每个特征是4维的,隐藏层是2维向量

[图片]

  • BatchSize—批量大小
  • SeqLen—样本数量
  • InputSize—输入维度
  • HiddenSize—隐藏层(输出)维度
import torch

# 参数设置
batch_size = 1
seq_len = 3
input_size = 4
hidden_size = 2

# 构造RNN cell
cell = torch.nn.RNNCell(input_size=input_size,hidden_size=hidden_size)

# 维度 (seq,batch,features)
dataset = torch.randn(seq_len,batch_size,input_size)
hidden = torch.zeros(batch_size,hidden_size) # 初始化零向量

for idx,input in enumerate(dataset):
    print("="*20,idx,"="*20)
    print("Input size:",input.shape)

    hidden = cell(input,hidden)
    print("Output size:",hidden.shape)
    print(hidden)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

[图片]

4.2 直接调用RNN

直接使用torch.nn.RNN()需要知道input_size、hidden_size和num_layers(RNN有多少层,默认为1)

[图片]

cell(inputs,hidden)中 inputs指包含整个输入序列(x1,x2,x3,…xN),hidden指h0。
用RNN自动循环,所以输入的时候要把所有的序列都送进去,然后给定h0,然后我们就会得到所有的隐层输出以及最后一层的输出。
[图片]

import torch
 
batch_size = 1
seq_len = 5
input_size = 4
hidden_size = 2
num_layers = 3
 
#其他参数
#batch_first=True 维度从(SeqLen*Batch*input_size)变为(Batch*SeqLen*input_size)
cell = torch.nn.RNN(input_size = input_size, hidden_size = hidden_size, num_layers = num_layers)
 
inputs = torch.randn(seq_len, batch_size, input_size)
hidden = torch.zeros(num_layers, batch_size, hidden_size)
 
out, hidden = cell(inputs, hidden)
 
print("Output size: ", out.shape)
print("Output: ", out)
print("Hidden size: ", hidden.shape)
print("Hidden: ", hidden)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

[图片]

注:batch_first=True 维度从(SeqLenBatchinput_size)变为(BatchSeqLeninput_size)
[图片]

5. 多层RNN

当RNN有多层,下图中同样颜色的RNNCell是同一个即有3个线性层(一个RNNCell是一个线性层)。因为每一层都需要隐藏层h的参数,因此隐藏层维度需要numLayers参数。
[图片]

6. 案例

一个序列到一个序列(seq->seq)的问题
在这里插入图片描述

  • 先将"Hello“转化成数值型向量
    用one-hot编码
    [图片]

多分类问题(输出维度为4)经过Softmax求得映射之后的概率分别是多少,再利用输出对应的独热向量,计算NLLLoss

[图片]

6.1 使用RNN_cell

import torch
 
input_size = 4
hidden_size = 4
batch_size = 1
 
#构建输入输出字典
idx2char = ['e', 'h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [3, 1, 2, 3, 2]

one_hot_lookup = [[1, 0, 0, 0],
                  [0, 1, 0, 0],
                  [0, 0, 1, 0],
                  [0, 0, 0, 1]]

#构造独热向量,此时向量维度为(SeqLen*InputSize)
x_one_hot = [one_hot_lookup[x] for x in x_data]
#view(-1……)保留原始SeqLen,并添加batch_size,input_size两个维度
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
#将labels转换为(SeqLen*1)的维度
labels = torch.LongTensor(y_data).view(-1, 1)
 
class Model(torch.nn.Module):
    def __init__(self, input_size, hidden_size, batch_size):
        super(Model, self).__init__()
        self.batch_size = batch_size
        self.input_size = input_size
        self.hidden_size = hidden_size
 
        self.rnncell = torch.nn.RNNCell(input_size = input_size,
                                        hidden_size = hidden_size)
 
    def forward(self, input, hidden):
        # RNNCell input = (batchsize*inputsize)
        # RNNCell hidden = (batchsize*hiddensize)
        # h_i = cell(x_i , h_i-1)
        hidden = self.rnncell(input, hidden)
        return hidden
 
    #初始化零向量作为h0,只有此处用到batch_size
    def init_hidden(self):
        return torch.zeros(self.batch_size, self.hidden_size)
 
model = Model(input_size, hidden_size, batch_size)
 
criterion = torch.nn.CrossEntropyLoss(reduction="mean")
optimizer = torch.optim.Adam(model.parameters(), lr=0.1)
 
for epoch in range(15):
    #损失及梯度置0,创建前置条件h0
    loss = 0
    optimizer.zero_grad()
    hidden = model.init_hidden()
 
    print("Predicted string: ",end="")
    #inputs=(seqLen*batchsize*input_size) labels = (seqLen*1)
    #input是按序列取的inputs元素(batchsize*inputsize)
    #label是按序列去的labels元素(1)
    for input, label in zip(inputs, labels):
        hidden = model(input, hidden)
        #序列的每一项损失都需要累加
        loss += criterion(hidden, label)
        #多分类取最大,找到四个类中概率最大的下标
        _, idx = hidden.max(dim=1)
        print(idx2char[idx.item()], end='')
 
    loss.backward()
    optimizer.step()
 
    print(", Epoch [%d/15] loss = %.4f" % (epoch+1, loss.item()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

[图片]

6.2 使用RNN

import torch

input_size = 4
hidden_size = 4
batch_size = 1
num_layers = 1
seq_len = 5

# 准备数据
idx2char = ['e','h','l','o'] # 字典
x_data = [1,0,2,2,3] # hello
y_data = [3,1,2,3,2] # ohlol

one_hot_lookup = [[1,0,0,0],
                  [0,1,0,0],
                  [0,0,1,0],
                  [0,0,0,1]]  # ont_hot查询

x_one_hot = [one_hot_lookup[x] for x in x_data] # seq * input_Size

# (seqlen,batchsize,inputsize)
inputs = torch.Tensor(x_one_hot).view(seq_len,batch_size,input_size)
# label (seqlen,1)
labels = torch.LongTensor(y_data)

# 构造模型
class Model(torch.nn.Module):
    def __init__(self,batch_size,input_size,hidden_size,num_layers = 1):
        super(Model, self).__init__()
        self.batch_size = batch_size
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        # input维度(batchsize,inputsize)
        # hidden维度(batchsize,hiddensize)
        self.rnn = torch.nn.RNN(input_size=self.input_size,hidden_size=self.hidden_size,num_layers=self.num_layers)

    def forward(self,input):
        hidden = torch.zeros(self.num_layers,self.batch_size,self.hidden_size)

        out,_ = self.rnn(input,hidden)
        return out.view(-1,self.hidden_size) # 转变维2维矩阵,seq*batchsize*1 -》((seq*batchsize),1)

model = Model(input_size=input_size,hidden_size=hidden_size,batch_size=batch_size,num_layers=1)

# 损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr=0.05)  # lr = 0.01学习的太慢

# 训练
for epoch in range(15):

    optimizer.zero_grad()
    outputs = model(inputs) # inputs是(seq,Batchsize,Inputsize) outputs是(seq,Batchsize,Hiddensize)
    loss = criterion(outputs,labels) # labels是(seq,batchsize,1)
    loss.backward()
    optimizer.step()

    _,idx = outputs.max(dim=1)
    idx = idx.data.numpy()
    print("Predicted:",''.join([idx2char[x] for x in idx]),end='')
    print(",Epoch {}/15 loss={:.3f}".format(epoch+1,loss.item()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

在这里插入图片描述

7. 独热向量

one-hot缺点

  • 维度太高
  • 向量稀疏
  • 硬编码,不是学习出来的

综上所述,需要一种低维度的、稠密的、可学习数据的编码方式

改进目标

  • 词嵌入
    (数据降维)将高维、稀疏的样本 映射到 低维、稠密的空间 
    [图片]

[图片]

[图片]

输入是2,就去表里查找2的位置,输出向量。

取第2行的向量,我们可以通过矩阵乘法来获得:将上述4x5行的矩阵进行转置变成5x4,然后乘以一个[0 0 1 0]^T就可以取出第2行的向量。
求反向传播导数的话,我们就可以通过矩阵乘法的导数来进行计算。

网络结构

[图片]

之前的RNN cell输出的隐藏层是和分类的数量是一致的, 如果不一致的话,可以再接一个线性层。

  • 添加嵌入层
  • 线性层,将hiddensize变成numclass
  • Return 二维矩阵的形式,方便loss的计算
    [图片]

完整代码

import torch

# 使用RNN 有嵌入层和线性层
num_class = 4     # 4个类别
input_size = 4    # 输入维度是4
hidden_size = 8   # 隐层是8个维度
embedding_size = 10 # 嵌入到10维空间
batch_size = 1
num_layers = 2    # 两层的RNN
seq_len = 5       # 序列长度是5

# 准备数据
idx2char = ['e','h','l','o'] # 字典
x_data = [[1,0,2,2,3]] # hello  维度(batch,seqlen)
y_data = [3,1,2,3,2] # ohlol    维度 (batch*seqlen)

# (batchsize,seqlen)
inputs = torch.LongTensor(x_data)
# label (batchsize*seqlen)
labels = torch.LongTensor(y_data)
# print(labels.shape)
# print(labels)

# 构造模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.emb = torch.nn.Embedding(input_size,embedding_size)
        self.rnn = torch.nn.RNN(input_size=embedding_size,hidden_size=hidden_size,num_layers=num_layers,batch_first=True)
        self.fc = torch.nn.Linear(hidden_size,num_class)

    def forward(self,x):
        hidden = torch.zeros(num_layers,x.size(0),hidden_size)
        x = self.emb(x) # (batch,seqlen,embeddingsize)
        x,_ = self.rnn(x,hidden)
        x = self.fc(x)
        return x.view(-1,num_class) # 转变维2维矩阵,seq*batchsize*numclass -》((seq*batchsize),numclass)

model = Model()

# 损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr=0.05)  # lr = 0.01学习的太慢

# 训练
for epoch in range(15):

    optimizer.zero_grad()
    outputs = model(inputs) # inputs是(seq,Batchsize,Inputsize) outputs是(seq,Batchsize,Hiddensize)
    loss = criterion(outputs,labels) # labels是(seq,batchsize,1)
    loss.backward()
    optimizer.step()

    _,idx = outputs.max(dim=1)
    idx = idx.data.numpy()
    print("Predicted:",''.join([idx2char[x] for x in idx]),end='')
    print(",Epoch {}/15 loss={:.3f}".format(epoch+1,loss.item()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

[图片]


课后练习1:LSTM实现之前的模型

LSTM效果比RNN好得多,但由于计算复杂度上升,运算效率低,训练时间长。

[图片]

增加c_t+1的这条路径,在反向传播时,提供更快梯度下降的路径,减少梯度消失。

[图片]

torch.nn.LSTM():

[图片]

输入和输出:
[图片]

代码:

import torch

num_class = 4     
input_size = 4  
hidden_size = 8
embedding_size = 10
batch_size = 1
num_layers = 1    
seq_len = 5       

# 准备数据
idx2char = ['e','h','l','o'] # 字典
x_data = [[1,0,2,2,3]]  #维度(batch,seqlen)
y_data = [3,1,2,3,2] #ohlol

inputs = torch.LongTensor(x_data) 
labels = torch.LongTensor(y_data)

# 构造模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.emb = torch.nn.Embedding(input_size,embedding_size) #返回(batch,seqlen,embeddingsize) 
        self.lstm = torch.nn.LSTM(input_size=embedding_size,
                                 hidden_size=hidden_size,
                                 num_layers=num_layers)
        self.fc = torch.nn.Linear(hidden_size,num_class)

    def forward(self,x):
        hidden = torch.zeros(num_layers,x.size(0),hidden_size)
        x = self.emb(x) # (batch,seqlen,embeddingsize) 
        x,_ = self.lstm(x)
        x = self.fc(x)
        return x.view(-1,num_class) # 转变2维矩阵,seq*batchsize*numclass -》((seq*batchsize),numclass)

model = Model()

# 损失函数和优化器
criterion = torch.nn.CrossEntropyLoss(reduction='mean')
optimizer = torch.optim.Adam(model.parameters(),lr=0.01)  # lr = 0.01学习的太慢

# 训练
for epoch in range(15):

    optimizer.zero_grad()
    outputs = model(inputs) # inputs是(seq,Batchsize,Inputsize) outputs是(seq,Batchsize,Hiddensize)
    loss = criterion(outputs,labels) # labels是(seq,batchsize,1)
    loss.backward()
    optimizer.step()

    _,idx = outputs.max(dim=1) # 找到矩阵每行的最大值
    idx = idx.data.numpy() # 将tensor转成n数组
    print("Predicted:",''.join([idx2char[x] for x in idx]),end='')
    print(",Epoch {}/15 loss={:.3f}".format(epoch+1,loss.item()))
import torch

num_class = 4     
input_size = 4    
hidden_size = 8   
embedding_size = 10 
batch_size = 1
num_layers = 1    
seq_len = 5       

# 准备数据
idx2char = ['e','h','l','o'] # 字典
x_data = [[1,0,2,2,3]] 
y_data = [3,1,2,3,2] #ohlol

inputs = torch.LongTensor(x_data)
labels = torch.LongTensor(y_data)

# 构造模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.emb = torch.nn.Embedding(input_size,embedding_size) #返回inputs_len*embedding_size
        self.lstm = torch.nn.LSTM(input_size=embedding_size,
                                 hidden_size=hidden_size,
                                 num_layers=num_layers)
        self.fc = torch.nn.Linear(hidden_size,num_class)

    def forward(self,x):
        hidden = torch.zeros(num_layers,x.size(0),hidden_size)
        x = self.emb(x) # (batch,seqlen,embeddingsize) 
        # print("emb_x",x)
        x,_ = self.lstm(x)
        x = self.fc(x)
        return x.view(-1,num_class) # 转变2维矩阵,seq*batchsize*numclass -》((seq*batchsize),numclass)

model = Model()

# 损失函数和优化器
criterion = torch.nn.CrossEntropyLoss(reduction='mean')
optimizer = torch.optim.Adam(model.parameters(),lr=0.01)  # lr = 0.01学习的太慢

# 训练
for epoch in range(15):

    optimizer.zero_grad()
    outputs = model(inputs) # inputs是(seq,Batchsize,Inputsize) outputs是(seq,Batchsize,Hiddensize)
    loss = criterion(outputs,labels) # labels是(seq,batchsize,1)
    loss.backward()
    optimizer.step()

    _,idx = outputs.max(dim=1) # 找到矩阵每行的最大值
    idx = idx.data.numpy() # 将tensor转成n数组
    print("Predicted:",''.join([idx2char[x] for x in idx]),end='')
    print(",Epoch {}/15 loss={:.3f}".format(epoch+1,loss.item()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

结果:

[图片]

效果很差,根本没预测出来。

  • https://blog.csdn.net/m0_58327216/article/details/122854569?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-122854569-blog-119042008.pc_relevant_multi_platform_featuressortv2removedup&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-122854569-blog-119042008.pc_relevant_multi_platform_featuressortv2removedup&utm_relevant_index=1
    这个代码运行出来预测是正确的,暂时不知道我直接调取LSTM的问题。

课后练习2:GRU实现之前的模型

RNN和LSTM折中方案

[图片]

torch.nn.GRU():

[图片]

输入和输出:

[图片]

代码:

import torch

num_class = 4     
input_size = 4  
hidden_size = 8
embedding_size = 10
batch_size = 1
num_layers = 1    
seq_len = 5       

# 准备数据
idx2char = ['e','h','l','o'] # 字典
x_data = [[1,0,2,2,3]]  #维度(batch,seqlen)
y_data = [3,1,2,3,2] #ohlol

inputs = torch.LongTensor(x_data) 
labels = torch.LongTensor(y_data)

# 构造模型
class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.emb = torch.nn.Embedding(input_size,embedding_size) #返回(batch,seqlen,embeddingsize) 
        self.lstm = torch.nn.GRU(input_size=embedding_size,
                                 hidden_size=hidden_size,
                                 num_layers=num_layers)
        self.fc = torch.nn.Linear(hidden_size,num_class)

    def forward(self,x):
        hidden = torch.zeros(num_layers,x.size(0),hidden_size)
        x = self.emb(x) # (batch,seqlen,embeddingsize) 
        x,_ = self.lstm(x)
        x = self.fc(x)
        return x.view(-1,num_class) # 转变2维矩阵,seq*batchsize*numclass -》((seq*batchsize),numclass)

model = Model()

# 损失函数和优化器
criterion = torch.nn.CrossEntropyLoss(reduction='mean')
optimizer = torch.optim.Adam(model.parameters(),lr=0.01)  # lr = 0.01学习的太慢

# 训练
for epoch in range(15):

    optimizer.zero_grad()
    outputs = model(inputs) # inputs是(seq,Batchsize,Inputsize) outputs是(seq,Batchsize,Hiddensize)
    loss = criterion(outputs,labels) # labels是(seq,batchsize,1)
    loss.backward()
    optimizer.step()

    _,idx = outputs.max(dim=1) # 找到矩阵每行的最大值
    idx = idx.data.numpy() # 将tensor转成n数组
    print("Predicted:",''.join([idx2char[x] for x in idx]),end='')
    print(",Epoch {}/15 loss={:.3f}".format(epoch+1,loss.item()))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

结果:

[图片]

同样没有预测出来,问题待解决。


学习资料

  • https://blog.csdn.net/lizhuangabby/article/details/125854784
  • https://www.cnblogs.com/motoharu/p/15175371.html

系列文章索引

教程指路:【《PyTorch深度学习实践》完结合集】 https://www.bilibili.com/video/BV1Y7411d7Ys?share_source=copy_web&vd_source=3d4224b4fa4af57813fe954f52f8fbe7

  1. 线性模型 Linear Model
  2. 梯度下降 Gradient Descent
  3. 反向传播 Back Propagation
  4. 用PyTorch实现线性回归 Linear Regression with Pytorch
  5. 逻辑斯蒂回归 Logistic Regression
  6. 多维度输入 Multiple Dimension Input
  7. 加载数据集Dataset and Dataloader
  8. 用Softmax和CrossEntroyLoss解决多分类问题(Minst数据集)
  9. CNN基础篇——卷积神经网络跑Minst数据集
  10. CNN高级篇——实现复杂网络
  11. RNN基础篇——实现RNN
  12. RNN高级篇—实现分类
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/897190
推荐阅读
相关标签
  

闽ICP备14008679号