Seq2Seq 架构 - 任务介绍
1 课程概览
本课介绍 Seq2Seq(Sequence to Sequence)架构,用于机器翻译、文本摘要、对话等任务。架构由三部分组成:编码器(Encoder)、解码器(Decoder)、中间语义张量 C。以英译法案例讲解编码和解码流程,以及不加注意力机制时的问题。
2 核心概念与定义
- Seq2Seq(Sequence to Sequence):序列到序列架构,将输入序列映射为中间状态,再生成目标序列。
- 编码器(Encoder):理解语义,将输入序列编码为中间语义张量 C。
- 解码器(Decoder):负责生成,基于中间语义张量 C 生成目标序列。
- 中间语义张量 C:编码器的总输出,作为解码器的输入。
- GO:代表开始(句子的起始标志)。
- EOS(End of Sequence):代表结束(句子的结束标志)。
3 模型与算法详解
Seq2Seq 架构组成
| 组件 | 作用 |
|---|---|
| 编码器(Encoder) | 理解语义,将输入序列编码为中间语义张量 C |
| 解码器(Decoder) | 负责生成,基于 C 生成目标序列 |
| 中间语义张量 C | 编码器的总输出,作为解码器的输入 |
编码流程
- 文本经过词嵌入层(Encoding)转为数值
- 一个时间步一个时间步地编码
- 每个时间步有隐藏层的输出
- 最后组合成中间语义张量 C
解码流程
- 将中间语义张量 C 作为输入
- 结合上一时刻的隐藏状态 $S_{t-1}$
- 生成当前时刻的输出 $Y_t$
不加注意力机制的问题
如果不加注意力机制,所有时间步用同一个 C。
示例:"欢迎来北京" 翻译为 "Welcome to Beijing"
- 翻译 "Beijing" 时,对 "北京" 这个词的依赖应该最高
- 如果不加注意力机制,所有词的权重相同
- 导致翻译效果不佳
加注意力机制的改进
- 每个时间步使用不同的 C($C_1, C_2, C_3$)
- 生成 "Welcome" 时,用 $Q_1$ 算出 $C_1$
- 生成 "to" 时,用 $Q_2$ 算出 $C_2$
- 生成 "Beijing" 时,用 $Q_3$ 算出 $C_3$
特殊标志
| 标志 | 含义 |
|---|---|
| GO | 句子的开始 |
| EOS | 句子的结束(End of Sequence) |
4 数学原理与推导
编码过程
$$h_t = \text{Encoder}(x_t, h_{t-1})$$ $$C = h_T$$
其中 $h_T$ 是最后一个时间步的隐藏状态。
解码过程(不加注意力)
$$Y_t = \text{Decoder}(C, S_{t-1})$$
其中 $C$ 是固定的中间语义张量。
解码过程(加注意力)
$$C_t = \text{Attention}(Q_t, K, V)$$ $$Y_t = \text{Decoder}(C_t, S_{t-1})$$
其中 $C_t$ 是每个时间步动态计算的中间语义张量。
5 代码示例
本课为概念介绍,具体代码实现见后续课程。
# Seq2Seq 架构概念示例(伪代码)
import torch.nn as nn
class Encoder(nn.Module):
"""编码器:理解语义,输出中间语义张量 C"""
def __init__(self, input_size, hidden_size):
super().__init__()
self.gru = nn.GRU(input_size, hidden_size)
def forward(self, x, hidden):
output, hidden = self.gru(x, hidden)
return output, hidden # hidden 即为中间语义张量 C
class Decoder(nn.Module):
"""解码器:基于 C 生成目标序列"""
def __init__(self, hidden_size, output_size):
super().__init__()
self.gru = nn.GRU(hidden_size, hidden_size)
self.linear = nn.Linear(hidden_size, output_size)
self.softmax = nn.LogSoftmax(dim=1)
def forward(self, x, hidden):
# x 是中间语义张量 C
output, hidden = self.gru(x, hidden)
output = self.linear(output)
output = self.softmax(output)
return output, hidden
class Seq2Seq(nn.Module):
"""Seq2Seq 架构"""
def __init__(self, encoder, decoder):
super().__init__()
self.encoder = encoder
self.decoder = decoder
def forward(self, src, trg):
# 1. 编码
encoder_output, C = self.encoder(src, None)
# 2. 解码(不加注意力,所有时间步用同一个 C)
decoder_output, hidden = self.decoder(C, None)
return decoder_output
6 重难点与易错提醒
- ❗重点:Seq2Seq 由三部分组成——编码器、解码器、中间语义张量 C。
- ❗重点:编码器理解语义,解码器负责生成。
- ⚠️易错:不加注意力机制时,所有时间步用同一个 C。
- 💡深入理解:加注意力机制后,每个时间步用不同的 C($C_1, C_2, C_3$)。
- 💡深入理解:GO 代表开始,EOS 代表结束。
7 课堂问答精选
Q1:Seq2Seq 架构由哪三部分组成?
A:①编码器(Encoder):理解语义,将输入序列编码为中间语义张量 C;②解码器(Decoder):负责生成,基于 C 生成目标序列;③中间语义张量 C:编码器的总输出,作为解码器的输入。
Q2:编码和解码的流程是什么?
A:编码:一个时间步一个时间步地编码,每个时间步有隐藏层的输出,最后组合成中间语义张量 C。解码:将 C 作为输入,结合上一时刻的隐藏状态 $S_{t-1}$,生成当前时刻的输出 $Y_t$。
Q3:不加注意力机制会有什么问题?
A:不加注意力机制时,所有时间步用同一个 C。例如翻译"欢迎来北京"时,翻译"Beijing"应该对"北京"依赖最高,但如果所有词的权重相同,翻译效果不佳。
Q4:GO 和 EOS 代表什么?
A:GO 代表句子的开始,EOS(End of Sequence)代表句子的结束。
8 本课小结
- Seq2Seq 三部分:编码器、解码器、中间语义张量 C。
- 编码器:理解语义,输出 C。
- 解码器:基于 C 生成目标序列。
- 不加注意力:所有时间步用同一个 C。
- 加注意力:每个时间步用不同的 C($C_1, C_2, C_3$)。
9 延伸思考
- 如何在 Seq2Seq 中加入注意力机制?
- 中间语义张量 C 是如何计算的?