日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新)
在线聊天的总体架构与工具介绍:Flask web、Redis、Gunicorn服务组件、Supervisor服务监控器、Neo4j图数据库
linux 安装 neo4j、linux 安装 Redis、supervisor 安装
在线部分:werobot服务、主要逻辑服务、句子相关模型服务、BERT中文预训练模型+微调模型(目的:比较两句话text1和text2之间是否有关联)、模型在Flask部署
离线部分+在线部分:命名实体审核任务RNN模型、命名实体识别任务BiLSTM+CRF模型、BERT中文预训练+微调模型、werobot服务+flask
5.4 构建RNN模型
- 学习目标:
- 学习RNN模型的内部结构及计算公式.
- 掌握RNN模型的实现过程.
- 传统RNN的内部结构图:
- 内部结构分析: * 我们把目光集中在中间的方块部分, 它的输入有两部分, 分别是h(t-1)以及x(t), 代表上一时间步的隐层输出, 以及此时间步的输入, 它们进入RNN结构体后, 会"融合"到一起, 这种融合我们根据结构解释可知, 是将二者进行拼接, 形成新的张量[x(t), h(t-1)], 之后这个新的张量将通过一个全连接层(线性层), 该层>使用tanh作为激活函数, 最终得到该时间步的输出h(t), 它将作为下一个时间步的>输入和x(t+1)一起进入结构体. 以此类推.
- 内部结构过程演示:
- 根据结构分析得出内部计算公式:
- 激活函数tanh的作用: * 用于帮助调节流经网络的值, tanh函数将值压缩在-1和1之间.
- 构建RNN模型的代码分析:
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
"""初始化函数中有三个参数,分别是输入张量最后一维的尺寸大小,
隐层张量最后一维的尺寸大小, 输出张量最后一维的尺寸大小"""
super(RNN, self).__init__()
# 传入隐含层尺寸大小
self.hidden_size = hidden_size
# 构建从输入到隐含层的线性变化, 这个线性层的输入尺寸是input_size + hidden_size
# 这是因为在循环网络中, 每次输入都有两部分组成,分别是此时刻的输入和上一时刻产生的输出.
# 这个线性层的输出尺寸是hidden_size
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
# 构建从输入到输出层的线性变化, 这个线性层的输入尺寸还是input_size + hidden_size
# 这个线性层的输出尺寸是output_size.
self.i2o = nn.Linear(input_size + hidden_size, output_size)
# 最后需要对输出做softmax处理, 获得结果.
self.softmax = nn.LogSoftmax(dim=-1)
def forward(self, input, hidden):
"""在forward函数中, 参数分别是规定尺寸的输入张量, 以及规定尺寸的初始化隐层张量"""
# 首先使用torch.cat将input与hidden进行张量拼接
combined = torch.cat((input, hidden), 1)
# 通过输入层到隐层变换获得hidden张量
hidden = self.i2h(combined)
# 通过输入到输出层变换获得output张量
output = self.i2o(combined)
# 对输出进行softmax处理
output = self.softmax(output)
# 返回输出张量和最后的隐层结果
return output, hidden
def initHidden(self):
"""隐层初始化函数"""
# 将隐层初始化成为一个1xhidden_size的全0张量
return torch.zeros(1, self.hidden_size)
- torch.cat演示:
>>> x = torch.randn(2, 3)
>>> x
tensor([[ 0.6580, -1.0969, -0.4614],
[-0.1034, -0.5790, 0.1497]])
>>> torch.cat((x, x, x), 0)
tensor([[ 0.6580, -1.0969, -0.4614],
[-0.1034, -0.5790, 0.1497],
[ 0.6580, -1.0969, -0.4614],
[-0.1034, -0.5790, 0.1497],
[ 0.6580, -1.0969, -0.4614],
[-0.1034, -0.5790, 0.1497]])
>>> torch.cat((x, x, x), 1)
ensor([[ 0.6580, -1.0969, -0.4614, 0.6580, -1.0969, -0.4614, 0.6580,-1.0969, -0.4614],
[-0.1034, -0.5790, 0.1497, -0.1034, -0.5790, 0.1497, -0.1034,-0.5790, 0.1497]])
- 实例化参数:
input_size = 768
hidden_size = 128
n_categories = 2
- 输入参数:
input = torch.rand(1, input_size)
hidden = torch.rand(1, hidden_size)
- 调用:
from RNN_MODEL import RNN
rnn = RNN(input_size, hidden_size, n_categories)
outputs, hidden = rnn(input, hidden)
print("outputs:", outputs)
print("hidden:", hidden)
- 输出效果:
outputs: tensor([[-0.7858, -0.6084]], grad_fn=<LogSoftmaxBackward>)
hidden: tensor([[-4.8444e-01, -5.9609e-02, 1.7870e-01,
-1.6553e-01, ... , 5.6711e-01]], grad_fn=<AddmmBackward>))
- 小节总结:
- 学习了RNN模型的内部结构及计算公式.
- 学习并实现了RNN模型的类: class RNN(nn.Module).
import torch
import torch.nn as nn
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
"""初始化函数中有三个参数,分别是输入张量最后一维的尺寸大小,
隐层张量最后一维的尺寸大小, 输出张量最后一维的尺寸大小
"""
super(RNN, self).__init__()
# 传入隐含层尺寸大小
self.hidden_size = hidden_size
# 构建从输入到隐含层的线性变化, 这个线性层的输入尺寸是input_size + hidden_size
# 这是因为在循环网络中, 每次输入都有两部分组成,分别是此时刻的输入和上一时刻产生的输出.
# 这个线性层的输出尺寸是hidden_size
self.i2h = nn.Linear(input_size + hidden_size, hidden_size)
# 构建从输入到输出层的线性变化, 这个线性层的输入尺寸还是input_size + hidden_size
# 这个线性层的输出尺寸是output_size.
self.i2o = nn.Linear(input_size + hidden_size, output_size)
# 最后需要对输出做softmax处理, 获得结果.
self.softmax = nn.LogSoftmax(dim=-1)
def forward(self, input, hidden):
"""在forward函数中, 参数分别是规定尺寸的输入张量, 以及规定尺寸的初始化隐层张量"""
# 首先使用torch.cat将input与hidden进行张量拼接
combined = torch.cat((input, hidden), 1)
# 通过输入层到隐层变换获得hidden张量
hidden = self.i2h(combined)
# 通过输入到输出层变换获得output张量
output = self.i2o(combined)
# 对输出进行softmax处理
output = self.softmax(output)
# 返回输出张量和最后的隐层结果
return output, hidden
def initHidden(self):
"""隐层初始化函数"""
# 将隐层初始化成为一个1xhidden_size的全0张量
return torch.zeros(1, self.hidden_size)
input_size = 768
hidden_size = 128
n_categories = 2
input = torch.rand(1, input_size)
hidden = torch.rand(1, hidden_size)
rnn = RNN(input_size, hidden_size, n_categories)
outputs, hidden = rnn(input, hidden)
print("outputs:", outputs)
print("hidden:", hidden)