Bidirectional 是一种神经网络的结构特性,表示网络在处理序列数据时,同时考虑正向和反向的上下文信息。这种结构通常用于循环神经网络(RNN)及其变体(如 LSTM 和 GRU)中,以提高模型对序列数据的理解能力。

作用

  • 正向处理:从序列的开头到结尾依次处理每个时间步。

  • 反向处理:从序列的结尾到开头依次处理每个时间步。

  • 合并结果:将正向和反向的输出结果合并(通常是拼接,但也可以是求和、平均等),作为最终的输出。

特点

  • 双向上下文:双向模型可以同时利用过去和未来的上下文信息,这对于需要理解完整上下文的任务(如语言处理、语音识别等)非常有用。

  • 更高的准确性:由于双向模型能够捕捉到更多的上下文信息,通常比单向模型具有更高的预测准确性。

  • 计算复杂度增加:双向模型需要同时处理正向和反向的序列,因此计算复杂度和内存需求会增加

模型结构

输入序列: x₁, x₂, x₃, x₄, x₅, x₆, x₇, x₈

正向 RNN:
h₁ → h₂ → h₃ → h₄ → h₅ → h₆ → h₇ → h₈

反向 RNN:
h₈ ← h₇ ← h₆ ← h₅ ← h₄ ← h₃ ← h₂ ← h₁

最终输出: [h₁; h₈], [h₂; h₇], [h₃; h₆], [h₄; h₅], [h₅; h₄], [h₆; h₃], [h₇; h₂], [h₈; h₁]

[h₁; h₈] 表示将正向和反向的隐藏状态进行拼接。

通过这种方式,双向模型能够充分利用序列的完整上下文信息,从而在许多任务中表现出色。

PyTorch 实现

import torch
import torch.nn as nn

# 定义一个双向 GRU 模型
class BiGRU(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(BiGRU, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.bigru = nn.GRU(
            input_size=input_size,
            hidden_size=hidden_size,
            num_layers=num_layers,
            batch_first=True,
            bidirectional=True
        )
        self.fc = nn.Linear(hidden_size * 2, output_size)  # 因为是双向,所以输出维度是 hidden_size * 2

    def forward(self, x):
        # 初始化隐藏状态
        h0 = torch.zeros(self.num_layers * 2, x.size(0), self.hidden_size).to(x.device)
        # 前向传播
        out, _ = self.bigru(x, h0)
        # 取最后一个时间步的输出
        out = self.fc(out[:, -1, :])
        return out

# 示例输入
input_size = 10
hidden_size = 20
num_layers = 2
output_size = 5
batch_size = 32
seq_length = 100
x = torch.randn(batch_size, seq_length, input_size)

# 创建模型并前向传播
model = BiGRU(input_size, hidden_size, num_layers, output_size)
output = model(x)
print(output.shape)  # 输出形状为 (batch_size, output_size)