深度碎念(一):Embedding 层
简单解释:什么是 Embedding 层?
简单解释:什么是 Embedding 层?
Embedding 层就是一种“编码器”,它把离散的东西(比如文字、ID)变成稠密的、连续的向量。
举个最经典的例子:文本中的词嵌入(word embedding)
原本我们处理文字,比如 "apple","orange","cat",只能用数字ID表示:
词表 = {"apple": 1, "orange": 2, "cat": 3}
这些“词 ID”是离散的、没有实际意义,无法直接送入神经网络。
于是就有了:
Embedding(input_dim=10000, output_dim=128)
这个层会把每个词的编号 映射成一个128维的向量,比如:
| 词 | 原始ID | Embedding向量(128维) |
|---|---|---|
| apple | 1 | [0.12, -0.34, ..., 0.08] |
| orange | 2 | [0.02, -0.13, ..., 0.15] |
| cat | 3 | [0.76, 0.01, ..., -0.33] |
这个向量表示了词的“语义”,是可以学习的!
那它和 LSTM 有啥关系?
-
Embedding 层 通常在 LSTM 前面,作为输入的预处理步骤;
-
LSTM 接收的是时间序列(比如词向量序列),Embedding 就负责生成这些词向量;
-
LSTM 就可以处理这些连续的向量了,而不是那种死板的词ID;
你可以理解为:
Embedding 是预处理器(先转向量)
LSTM 是主处理器(提取时间特征)
在时序信号的场景下,还会用 embedding 吗?
不太会直接用传统的 Embedding() 层(它是专门为离散数据设计的),而我示例的数据是 连续的实数序列(如 (1000, 36))。
但在多模态/混合数据(如:患者ID、性别 )中,有可能会对 类别特征(如性别、病种)使用 embedding 层!
对于NLP
class Encoder(nn.Module): # 定义一个编码器类,用于seq2seq模型处理输入序列并生成隐藏状态
def __init__(self, dim_encoder_embbeding, dim_encoder_hidden, source_corpus_len): # 初始化函数
super().__init__() # 调用父类的初始化函数
self.embedding = nn.Embedding(source_corpus_len, dim_encoder_embbeding) # 定义嵌入层,将词转换为向量
self.lstm = nn.LSTM(dim_encoder_embbeding, dim_encoder_hidden, batch_first=True) # 定义LSTM层,用于处理序列数据
def forward(self, src_index): # 前向传播函数
en_embedding = self.embedding(src_index) # 对源索引进行嵌入操作
_, encoder_hidden = self.lstm(en_embedding) # 将嵌入后的向量输入LSTM,获取隐藏状态
return encoder_hidden # 返回编码器的隐藏状态
class Decoder(nn.Module): # 定义一个解码器类,与编码器配合使用,从编码器输出的隐藏状态开始生成目标序列
def __init__(self, dim_decoder_embedding, dim_decoder_hidden, target_corpus_len): # 初始化函数
super().__init__() # 调用父类的初始化函数
self.embedding = nn.Embedding(target_corpus_len, dim_decoder_embedding) # 定义嵌入层,将词转换为向量
self.lstm = nn.LSTM(dim_decoder_embedding, dim_decoder_hidden, batch_first=True) # 定义LSTM层,用于处理序列数据
def forward(self, decoder_input, hidden): # 前向传播函数
embedding = self.embedding(decoder_input) # 对解码器输入进行嵌入操作
decoder_output, decoder_hidden = self.lstm(embedding, hidden) # 将嵌入后的向量输入LSTM,获取输出和隐藏状态
return decoder_output, decoder_hidden # 返回解码器的输出和隐藏状态
class Seq2Seq(nn.Module): # 定义一个seq2seq模型类,用于将源序列映射到目标序列
def __init__(self, dim_encoder_embbeding, dim_encoder_hidden, source_corpus_len,
dim_decoder_embedding, dim_decoder_hidden, target_corpus_len): # 初始化函数
super().__init__() # 调用父类的初始化函数
self.encoder = Encoder(dim_encoder_embbeding, dim_encoder_hidden, source_corpus_len) # 初始化编码器
self.decoder = Decoder(dim_decoder_embedding, dim_decoder_hidden, target_corpus_len) # 初始化解码器
self.classifier = nn.Linear(dim_decoder_hidden, target_corpus_len) # 定义线性层,用于将解码器输出转换为词的概率分布
self.ce_loss = nn.CrossEntropyLoss() # 定义交叉熵损失函数
def forward(self, src_index, tgt_index): # 前向传播函数
decoder_input = tgt_index[:, :-1] # 获取目标索引的输入部分
label = tgt_index[:, 1:] # 获取目标索引的标签部分
encoder_hidden = self.encoder(src_index) # 将源索引输入编码器,获取隐藏状态
decoder_output, _ = self.decoder(decoder_input, encoder_hidden) # 将解码器输入和编码器隐藏状态输入解码器,获取输出
pre = self.classifier(decoder_output) # 将解码器输出输入线性层,获取预测结果
loss = self.ce_loss(pre.reshape(-1, pre.shape[-1]), label.reshape(-1)) # 计算损失
return loss # 返回损失
nn.Embedding(vocab_size, embedding_dim) 是 PyTorch 中专门用来实现词向量(word vector)映射的层。
vocab_size 是 vocabulary size(词汇表大小)的缩写
-
Vocabulary:指的是模型训练时所使用的词汇表,包含了所有在训练数据中出现过的单词(或子词、符号等)。
-
vocab_size:就是词汇表中单词的总数量。
举个例子: 假设你有一句话:“hello world”,你的模型可能会把每个单词映射为一个唯一的 ID。
"hello" -> 1
"world" -> 2
那么,这个小词汇表的 vocab_size 就是 2
输入是一个整数序列(表示单词编号、token id 等)
输出是每个编号对应的“向量”表示
这个向量是一个可以学习的、密集的表示(dense vector)
举个例子:
nn.Embedding(10000, 300)
表示词表大小 10,000,每个词用一个 300 维向量表示。
这段代码里 embedding 的体现:
在 Encoder 中:
self.embedding = nn.Embedding(source_corpus_len, dim_encoder_embbeding)
意思是:有一个源语言的词表(比如中文),每个 token 会被映射成 dim_encoder_embbeding 维的向量。
然后这段:
en_embedding = self.embedding(src_index)
src_index 是 "source index"。
-
"source" 表示源数据或源序列(例如,输入文本序列)。
-
"index" 表示该源数据中每个元素在词汇表中的位置或索引。
把原始的整型输入(如:句子中的每个词的 id)转换成向量序列,为后面的 LSTM 提供“有意义的输入”。
在 Decoder 中:
self.embedding = nn.Embedding(target_corpus_len, dim_decoder_embedding)
同理,把目标语言的词(比如英文)映射成向量,用于生成预测。
embedding 和 LSTM 的关系?
它们各司其职:
-
Embedding层负责:把离散的token转为可以训练的、语义相关的向量表示。 -
LSTM层负责:建模时间上的依赖关系(序列信息),并从 embedding 向量中学到上下文特征。
| 位置 | 起作用的代码 | 作用 |
|---|---|---|
| Encoder | self.embedding = nn.Embedding(...) |
把输入序列里的 token index 映射成向量序列 |
| Decoder | self.embedding = nn.Embedding(...) |
把目标序列输入的 token index 映射成向量,辅助预测 |
| 模型层次上 | encoder ➜ decoder ➜ classifier | embedding 是编码器和解码器的“词语理解层”,没有它们就没有语义含义 |
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)