首页 > 其他分享 >《Pytorch - RNN模型》

《Pytorch - RNN模型》

时间:2022-12-14 16:34:56浏览次数:43  
标签:RNN 模型 Pytorch print input hidden data self size


前言:
之前的博文部分地讲解了RNN的标准结构,也用pytorch的RNNCell类和RNN类实现了前向传播的计算,这里我们再举一个例子,做一个特别简单特别简单特别简单特别简单的翻译器,目标如下:
将英文hello and thank you翻译成汉语拼音ni hao qie duo xie ni

篇幅有限,我们拿这五个数据练手吧。
如下两个例子也是为了让我们学习一下RNN相关维度的概念。

一:使用RNNCell类实现简单的字符串翻译
这里我们需要用到one-hot vector技术,也就是我们建立一个字符表,包含空格字符和26个小写英文字符,也就是一共有27个字符的字典表,空格符号标号是0,az编号是126,我们定义有22个序列的输入(也就是最多一次能接受22个字符的输入),每个输入的x 也是27维度的向量,输出层也是27维度的,也就是多个分类的问题,用RNN实现。代码如下:

import torch
import numpy as np
from torch.autograd import Variable

batch_size = 1 # 批量数据的大小,数据的批次,比如这里有5个需要测试的单词。
seq_len = 22 # 一共是多少个时间序列,是指时间的维度,在这里的意思就是一次性最大能接受20个字符的输入。
input_size = 27 # 某一时刻下,输入的X的维度向量,比如这里的4指的是维度是[4, 1]
hidden_size = 27 # 每一层的激活后 h 的维度,比如这里的2指的是维度是[2, 1]

# num_layers = 1

# a~z标号是1~26, 空格是1,这个字典表,每个字符有个对应的编号,也就是下标就是编号
idx2char = [' ', # 0
'a', 'b', 'c', 'd', 'e', 'f', 'g', # 1-7
'h', 'i', 'j', 'k', 'l', 'm', 'n', # 8-14
'o', 'p', 'q', 'r', 's', 't', # 15-20
'u', 'v', 'w', 'x', 'y', 'z'] # 21-26
idx2char = np.array(idx2char)
# 每个编号有个对应的向量,也就是下标对应的向量
one_hot_look = np.array(np.eye(idx2char.shape[0])).astype(int)
print('idx2char.shape[0]=', idx2char.shape[0])

x_data = np.zeros((batch_size, seq_len)).astype(int)
y_data = np.zeros((batch_size, seq_len)).astype(int)

# 待翻译的句子
x_data_char = ['hello and thank you']
y_data_char = ['ni hao qie duo xie you']

# 填充每个字符的下标
i=0
for item in x_data_char:
# fill each data
j=0
for letter in item:
x_data[i][j] = np.where(idx2char == letter)[0][0]
j = j + 1
i = i + 1

i=0
for item in y_data_char:
# fill each data
j=0
for letter in item:
y_data[i][j] = np.where(idx2char == letter)[0][0]
j = j + 1
i = i + 1

#print(x_data)
#print(y_data)




# Step 2:============================定义一个RNNCell的模型===================
class RNNCellModel(torch.nn.Module):
def __init__(self, input_size, hidden_size):
super(RNNCellModel, self).__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.rnncell = torch.nn.RNNCell(input_size=self.input_size, hidden_size=self.hidden_size)

def forward(self, input, hidden):
hidden = self.rnncell(input, hidden)
return hidden

model = RNNCellModel(input_size, hidden_size)



# Step 3:============================定义损失函数和优化器===================
# 定义 loss 函数,这里用的是交叉熵损失函数(Cross Entropy),这种损失函数之前博文也讲过的。
criterion = torch.nn.CrossEntropyLoss()
# 我们优先使用Adam下降,lr是学习率: 0.1
optimizer = torch.optim.Adam(model.parameters(), 1e-1)





# Step 4:============================开始训练===================
for e in range(200):
loss = 0
optimizer.zero_grad()
hidden = torch.zeros(batch_size, hidden_size) # 随机初始化的h0,且必须是Tensor类型的
i = 0
print('e============================')
print('predicted str: ', end='')
for cur_seq in zip(*x_data): # for each seq
cur_seq = np.array(cur_seq)
#input 必须是Tensor类型的
input = torch.Tensor([one_hot_look[x] for x in cur_seq])
# print(input.shape)
# y_label 必须是长整数型,且必须是Tensor类型的
y_label = torch.LongTensor(np.array(y_data[:, i]))
#print('real y_label: ', idx2char[y_label.item()], end='')

# 前向传播
hidden = model(input, hidden)
_, idx = hidden.max(dim=1)
print(idx2char[idx.item()], end='')
# print(hidden)
# 累加损失
loss += criterion(hidden, y_label)

i = i+1

loss.backward()
optimizer.step()
print(',epoch [%d/200] loss=%.4f' % (e+1, loss.item()), end='')

输出结果如下:训练的字符串是hello and thank you

《Pytorch - RNN模型》_深度学习

这个模型基本就差不多了训练出来是 ni hao qie duo xie ni

二:使用RNN类实现简单的字符串翻译
或者还可以用RNN模型来做,这样省去了自己写循环迭代序列的过程
,这里需要注意模型的建立需要传入层数,以及需要传递batch_size,因为hidden节点需要这个参数。

import torch
import numpy as np
from torch.autograd import Variable

batch_size = 1 # 批量数据的大小,数据的批次,比如这里有5个需要测试的单词。
seq_len = 22 # 一共是多少个时间序列,是指时间的维度,在这里的意思就是一次性最大能接受22个字符的输入。
input_size = 27 # 某一时刻下,输入的X的维度向量,比如这里的4指的是维度是[4, 1]
hidden_size = 27 # 每一层的激活后 h 的维度,比如这里的2指的是维度是[2, 1]
num_layers = 3 # 共有三层RNN

# a~z标号是1~26, 空格是1,这个字典表,每个字符有个对应的编号,也就是下标就是编号
idx2char = [' ', # 0
'a', 'b', 'c', 'd', 'e', 'f', 'g', # 1-7
'h', 'i', 'j', 'k', 'l', 'm', 'n', # 8-14
'o', 'p', 'q', 'r', 's', 't', # 15-20
'u', 'v', 'w', 'x', 'y', 'z'] # 21-26
idx2char = np.array(idx2char)
# 每个编号有个对应的向量,也就是下标对应的向量
one_hot_look = np.array(np.eye(idx2char.shape[0])).astype(int)
print('idx2char.shape[0]=', idx2char.shape[0])

x_data = np.zeros((batch_size, seq_len)).astype(int)
y_data = np.zeros((batch_size, seq_len)).astype(int)

# 待翻译的句子
x_data_char = ['hello and thank you']
y_data_char = ['ni hao qie duo xie you']

# 填充每个字符的下标
i=0
for item in x_data_char:
# fill each data
j=0
for letter in item:
x_data[i][j] = np.where(idx2char == letter)[0][0]
j = j + 1
i = i + 1

i=0
for item in y_data_char:
# fill each data
j=0
for letter in item:
y_data[i][j] = np.where(idx2char == letter)[0][0]
j = j + 1
i = i + 1

#print(x_data)
#print(y_data)
x_one_hot = [one_hot_look[x] for x in x_data]
inputs = torch.Tensor(x_one_hot).view(seq_len, batch_size, input_size)
lables = torch.LongTensor(y_data).view(-1)



# Step 2:============================定义一个RNNCell的模型===================
class RNNModel(torch.nn.Module):
def __init__(self, input_size, hidden_size, batch_size, num_layers):
super(RNNModel, self).__init__()
self.input_size = input_size
self.hidden_size = hidden_size
self.batch_size = batch_size
self.num_layers = num_layers
self.rnn = torch.nn.RNN(input_size=self.input_size, hidden_size=self.hidden_size,
num_layers=num_layers)

def forward(self, input):
# 由于不需要自己写序列的迭代,因此直接将随机初始化h0写道这里
hidden = torch.zeros(num_layers, batch_size, hidden_size) # 随机初始化的h0,且必须是Tensor类型的

# 我们只关心output: [seq_len, batch_size, hidden_size]
# input是: [seq_len, batch_size, input_size]
output, _ = self.rnn(input, hidden)

# 将out reshape到[seq_len * batch_size, hidden_size]
return output.view(-1, self.hidden_size)

model = RNNModel(input_size, hidden_size, batch_size, num_layers)



# Step 3:============================定义损失函数和优化器===================
# 定义 loss 函数,这里用的是交叉熵损失函数(Cross Entropy),这种损失函数之前博文也讲过的。
criterion = torch.nn.CrossEntropyLoss()
# 我们优先使用Adam下降,lr是学习率: 0.1
optimizer = torch.optim.Adam(model.parameters(), lr=0.05)





# Step 4:============================开始训练===================
for e in range(200):
loss = 0
optimizer.zero_grad()

# 前向传播
hidden = model(inputs)
# 计算损失
loss = criterion(hidden, lables)
# 反向传播,更新参数
loss.backward()
optimizer.step()

_, idx = hidden.max(dim=1)
idx = idx.data.numpy()
print('e============================')
print('predicted str: ', end='')
print(''.join([idx2char[x] for x in idx]), end='')
print(',epoch [%d/200] loss=%.4f' % (e+1, loss.item()), end='')

效果如下:很明显,损失好像更低了些。

《Pytorch - RNN模型》_深度学习_02


标签:RNN,模型,Pytorch,print,input,hidden,data,self,size
From: https://blog.51cto.com/u_12419595/5937527

相关文章