【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU)
【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU)
文章目录
- 【深度学习基础模型】门控循环单元 (Gated Recurrent Units, GRU)
- 1.门控循环单元 (Gated Recurrent Units, GRU) 原理详解
- 1.1 GRU 概述
- 1.2 GRU 的门控机制
- 1.3 GRU 的优缺点
- 1.4 GRU 的应用
- 2.Python 实现 GRU 的实例
- 2.1GRU 实现及应用实例
- 2.2 代码解释
- 3.总结
参考地址:https://www.asimovinstitute.org/neural-network-zoo/
论文地址:https://arxiv.org/pdf/1412.3555v1
欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指正!
1.门控循环单元 (Gated Recurrent Units, GRU) 原理详解
1.1 GRU 概述
GRU 是 LSTM(长短期记忆网络)的变体。与 LSTM 类似,GRU 也是为了解决 RNN 中的 梯度消失 和 梯度爆炸 问题而设计的,但 GRU 相比 LSTM 结构更为简单。GRU 去除了 LSTM 中的输出门,并结合了输入门和遗忘门为一个更新门。这使得 GRU 在某些情况下比 LSTM 更高效。
1.2 GRU 的门控机制
GRU 有两个门:更新门 (update gate) 和 重置门 (reset gate)。
- 更新门 (update gate): 控制当前隐藏状态中保留多少信息,决定保留多少先前的状态,以及从当前输入中引入多少新信息。
- 重置门 (reset gate): 决定如何将新信息与之前的记忆结合起来,类似于 LSTM 的遗忘门,但工作方式稍有不同。
GRU 的公式为:
- 更新门:
z t = σ ( W z x t + U z h t − 1 ) z_t=σ(W_zx_t+U_zh_{t-1}) zt=σ(Wzxt+Uzht−1) - 重置门:
r t = σ ( W r x t + U r h t − 1 ) r_t=σ(W_rx_t+U_rh_{t-1}) rt=σ(Wrxt+Urht−1) - 候选隐藏状态:
h ~ t = t a n h ( W h x t + U h ( r t ⊙ h t − 1 ) ) \widetilde{h}_t=tanh(W_hx_t+U_h(r_t⊙h_{t-1})) h t=tanh(Whxt+Uh(rt⊙ht−1)) - 隐藏状态更新:
h t = z t ⊙ h t − 1 + ( 1 − z t ) ⊙ h ~ t h_t=z_t⊙h_{t-1}+(1-z_t)⊙\widetilde{h}_t ht=zt⊙ht−1+(1−zt)⊙h t
其中:
- z t z_t zt是更新门,控制先前状态和当前候选状态的平衡。
- r t r_t rt是重置门,控制前一时刻隐藏状态的影响程度。
- h ~ t \widetilde{h}_t h t是候选的隐藏状态,使用当前输入和前一时刻的隐藏状态生成。
- h t h_t ht是当前的隐藏状态。
1.3 GRU 的优缺点
- 优点: 结构更简单,计算量较小,比 LSTM 更快,适合不需要复杂表达能力的场景。
- 缺点: 由于少了一个门控机制(没有输出门),在某些任务中表现略逊于 LSTM。
1.4 GRU 的应用
GRU 和 LSTM 类似,广泛应用于序列数据处理任务,包括:
- 自然语言处理 (NLP):如机器翻译、文本生成等。
- 语音识别:处理连续的语音数据。
- 时间序列预测:用于预测未来的趋势,例如股票预测等。
2.Python 实现 GRU 的实例
我们使用 PyTorch 实现一个基于 GRU 的文本分类模型。与前面 RNN 实例类似,我们将训练一个二分类模型。
2.1GRU 实现及应用实例
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# 构造简单的示例数据集
# 假设有两个类别的句子,分别标注为 0 和 1
X = [
[1, 2, 3, 4], # "I love machine learning"
[5, 6, 7, 8], # "deep learning is great"
[1, 9, 10, 11], # "I hate spam emails"
[12, 13, 14, 15] # "phishing attacks are bad"
]
y = [0, 0, 1, 1] # 标签
# 转换为 Tensor 格式
X = torch.tensor(X, dtype=torch.long)
y = torch.tensor(y, dtype=torch.long)
# 定义数据集和数据加载器
dataset = TensorDataset(X, y)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
# 定义 GRU 模型
class GRUModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers):
super(GRUModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.embedding = nn.Embedding(input_size, hidden_size) # 嵌入层
self.gru = nn.GRU(hidden_size, hidden_size, num_layers, batch_first=True) # GRU 层
self.fc = nn.Linear(hidden_size, output_size) # 全连接层
def forward(self, x):
# 初始化隐藏状态
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
# 嵌入层
out = self.embedding(x)
# 通过 GRU
out, _ = self.gru(out, h0)
# 取最后一个时间步的隐藏状态
out = out[:, -1, :]
# 全连接层进行分类
out = self.fc(out)
return out
# 模型参数
input_size = 16 # 假设词汇表有 16 个词
hidden_size = 8 # 隐藏层维度
output_size = 2 # 输出为二分类
num_layers = 1 # GRU 层数
# 创建模型
model = GRUModel(input_size, hidden_size, output_size, num_layers)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 训练模型
num_epochs = 20
for epoch in range(num_epochs):
for data, labels in dataloader:
# 前向传播
outputs = model(data)
loss = criterion(outputs, labels)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
if (epoch+1) % 5 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
# 测试模型
with torch.no_grad():
test_sentence = torch.tensor([[1, 2, 3, 4]]) # 测试句子 "I love machine learning"
prediction = model(test_sentence)
predicted_class = torch.argmax(prediction, dim=1)
print(f'Predicted class: {predicted_class.item()}')
2.2 代码解释
1.定义 GRU 模型:
self.embedding = nn.Embedding(input_size, hidden_size)
:将输入的单词索引转换为高维向量表示。self.gru = nn.GRU(hidden_size, hidden_size, num_layers, batch_first=True)
:定义 GRU 层,输入和输出维度为hidden_size
,batch_first=True
表示输入序列按批次为第一维度。self.fc = nn.Linear(hidden_size, output_size)
:全连接层将 GRU 输出映射为分类输出。
2.GRU 的前向传播:
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
:初始化 GRU 的隐藏状态。out, _ = self.gru(out, h0)
:通过 GRU 层,out
是每个时间步的输出。out = out[:, -1, :]
:取最后一个时间步的隐藏状态作为最终输出。out = self.fc(out)
:通过全连接层进行分类。
3.数据集与加载器:
- 使用简单的二分类文本数据,将其转换为 PyTorch 的
TensorDataset
和DataLoader
。
4.训练与测试:
- 使用 Adam 优化器和交叉熵损失函数训练模型,在每 5 个 epoch 打印一次损失。
- 测试阶段输入测试句子,输出分类结果。
3.总结
GRU 是一种简化的循环神经网络,与 LSTM 类似,适用于处理时间序列数据或具有顺序依赖的任务。
相比于 LSTM,GRU 计算效率更高,但表达能力稍弱。在实际应用中,GRU 常用于自然语言处理、语音识别和时间序列预测等领域。通过 Python 和 PyTorch 实现的 GRU 模型,展示了其在文本分类中的应用。