趋近智
门控循环单元(GRU)是长短期记忆(LSTM)架构的近亲。与LSTM相比,GRU提供了一种简化的门控机制,通常能以更少的参数获得相似的性能,并且计算可能更快。这里将展示如何使用流行的深度学习框架,如TensorFlow(使用Keras API)和PyTorch,来实现GRU层。
TensorFlow的高级Keras API提供了一种直接的方法,可以使用tf.keras.layers.GRU将GRU层添加到您的模型中。它的使用方式与我们已经接触过的SimpleRNN和LSTM层非常相似。
要创建一个基本的GRU层,您主要需要指定层中的单元数量。这个数量决定了隐藏状态的维度,并且如果return_sequences=False,也决定了输出的维度。
import tensorflow as tf
# 定义一个包含64个单元的GRU层
# 'units' 指定了隐藏状态和输出空间的维度
gru_layer = tf.keras.layers.GRU(units=64)
# 示例输入形状:(batch_size, timesteps, features)
# 例如,一个包含32个序列的批次,每个序列长10步,每步有8个特征
sample_input = tf.random.normal([32, 10, 8])
# 将输入通过层
output = gru_layer(sample_input)
# 默认情况下,GRU只返回最后一个时间步的输出
# 默认输出形状:(batch_size, units)
print(f"Input shape: {sample_input.shape}")
print(f"Output shape (default): {output.shape}")
以下是tf.keras.layers.GRU最常用的一些参数:
units: (必需) 整数,表示输出空间和隐藏状态的维度。activation: 候选隐藏状态计算的激活函数。默认为tanh,这是GRU的标准选择,允许状态值在-1到1之间。recurrent_activation: 用于重置门 (rt) 和更新门 (zt) 的激活函数。默认为sigmoid。这一点很重要,因为门控需要输出0到1之间的值来有效控制信息流动。return_sequences: 布尔值。如果为True,则层会返回输入序列中每个时间步的隐藏状态输出。输出形状变为(batch_size, timesteps, units)。如果为False(默认),它只返回最后一个时间步的最终隐藏状态输出,导致输出形状为(batch_size, units)。通常,除了堆叠中的最后一个循环层,或者当后续层期望序列时,您会为所有循环层设置return_sequences=True。return_state: 布尔值。如果为True,则层除了输出外,还会返回最终的隐藏状态张量。对于GRU层,这是一个表示最后一个时间步隐藏状态的单个张量。输出会是一个列表:[output, final_state]。go_backwards: 布尔值(默认:False)。如果为True,输入序列将按逆序处理,并且如果return_sequences=True,则返回逆序的序列。reset_after: 布尔值(默认:True)。决定GRU的计算变体。True对应于在候选隐藏状态的矩阵乘法之后应用重置门的变体。False则是在之前应用。默认的True在实践中通常效果很好。让我们观察return_sequences=True的效果:
# 创建一个返回完整输出序列的GRU层
gru_layer_seq = tf.keras.layers.GRU(units=64, return_sequences=True)
# 传递相同的示例输入
output_seq = gru_layer_seq(sample_input)
# 输出形状现在包含了时间步维度
# 输出形状:(batch_size, timesteps, units)
print(f"Output shape (return_sequences=True): {output_seq.shape}")
如您所见,设置return_sequences=True会保留输出中的时间维度,使其适合输入到后续的循环层,或用于需要在每个时间步生成输出的任务。
在PyTorch中,torch.nn.GRU模块提供了等效的功能。初始化此模块时,您需要指定输入特征的大小和所需的隐藏状态大小。
PyTorch中一个需要特别注意的地方是输入序列的默认预期形状。与Keras不同,PyTorch的循环层,包括torch.nn.GRU,默认期望输入张量的形状为(sequence_length, batch_size, features)。然而,数据加载和预处理流程通常会生成(batch_size, sequence_length, features)格式的数据。为了直接处理这种常见格式,在创建GRU实例时,您必须将batch_first参数设置为True。
import torch
import torch.nn as nn
# 定义网络参数
input_features = 8 # 输入中每个时间步的特征数量
hidden_units = 64 # GRU隐藏状态中的单元数量
batch_size = 32 # 批次中的序列数量
seq_length = 10 # 每个序列的长度
# 定义一个GRU模块
# 确保 batch_first=True 以使用 (batch, seq, feature) 输入格式
gru_module = nn.GRU(input_size=input_features,
hidden_size=hidden_units,
batch_first=True) # 对常见数据形状很重要
# 示例输入:张量形状 (batch_size, seq_length, input_features)
sample_input_pt = torch.randn(batch_size, seq_length, input_features)
# 将输入通过模块。
# 默认情况下,PyTorch GRU返回两项:
# 1. output_seq: 包含每个时间步的输出隐藏状态的张量。
# 2. final_hidden_state: 包含最后一个时间步的隐藏状态的张量。
output_seq_pt, final_hidden_state_pt = gru_module(sample_input_pt)
# 输出序列形状:(batch_size, seq_length, hidden_size)
print(f"PyTorch Input shape: {sample_input_pt.shape}")
print(f"PyTorch Output sequence shape: {output_seq_pt.shape}")
# 最终隐藏状态形状:(num_layers * num_directions, batch_size, hidden_size)
# 对于单层、单向GRU,num_layers=1, num_directions=1。
print(f"PyTorch Final hidden state shape: {final_hidden_state_pt.shape}")
torch.nn.GRU的重要参数:
input_size: (必需) 输入 xt 中预期特征的数量。hidden_size: (必需) 隐藏状态 ht 中特征的数量。num_layers: 整数(默认:1)。堆叠的GRU层数量。这个参数可以方便地处理堆叠。我们将在后面的章节中讨论堆叠。bias: 布尔值(默认:True)。如果为False,则层将不使用偏置权重 bir,bhr 等。batch_first: 布尔值(默认:False)。如果为True,则输入和输出张量会以批次维度优先的方式提供:(batch, seq, feature)。如果您的数据遵循此常见约定,请将其设置为True。dropout: 浮点数(默认:0)。如果非零,则在除最后一层外的每个GRU层的输出上引入一个Dropout层,并使用指定的dropout概率。用于正则化。bidirectional: 布尔值(默认:False)。如果为True,则创建一个双向GRU。我们将在本章后面介绍这种架构。请注意,PyTorch的GRU模块自然会将其输出元组的第一个元素作为完整的输出序列返回(类似于Keras中的return_sequences=True)。如果您的任务只需要最终隐藏状态的输出(等同于Keras的默认return_sequences=False),您可以轻松地从output_seq_pt张量中提取它。一种常见的方法是选择批次中每个序列的最后一个时间步的输出:
# 提取批次中每个序列的最后一个时间步的输出
last_step_output_pt = output_seq_pt[:, -1, :]
print(f"PyTorch Last time step output shape: {last_step_output_pt.shape}")
# 形状:(batch_size, hidden_size)
第二个返回项final_hidden_state_pt包含最终隐藏状态,它对于初始化后续层或进行序列到序列任务非常有用。它的形状包括层数和方向,这在使用堆叠式或双向GRU时会变得重要。
现在您已经可以实现LSTM和GRU,那么何时选择哪一种呢?
在学会了如何在TensorFlow/Keras和PyTorch中实例化和使用基本的GRU层之后,您已准备好将它们集成到序列建模流程中。以下部分将在此基础上,展示如何进一步配置这些层,通过堆叠将它们组合成更深的网络结构,并使用双向处理来提升它们获取上下文的能力。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造