目录
一、核心定义与区别
二、常见Encoding编码
(1) 独热编码(One-Hot Encoding)
(2) 位置编码(Positional Encoding)
(3) 标签编码(Label Encoding)
(4) 注意事项
三、常见Embedding词嵌入
(1) 基础词嵌入(nn.Embedding)
(2) 预训练嵌入(from_pretrained)
(3) 类别特征嵌入(自定义类)
(4) 注意事项
四、对比总结
五、编码与嵌入的联合使用
总结
新年快乐,这几天将之前做的笔记整理了一下,补充了一点,正式开始学习!
—— 24.2.4
一、核心定义与区别
特性 | Encoding(编码) | Embedding(嵌入) |
---|---|---|
目标 | 将数据转换为特定格式(如数值、二进制、位置信息等),以满足模型输入要求。 | 将离散符号(如单词、类别)映射到低维连续向量空间,捕捉语义或结构关系。 |
数学形式 | 通常为确定性规则或固定函数(如独热编码、位置编码)。 | 通过可学习的参数矩阵(如神经网络中的嵌入层)生成。 |
维度 | 维度可能较高(如独热编码的维度等于类别数量)。 | 维度固定且较低(如词嵌入常用 100~1000 维)。 |
可训练性 | 不可训练(静态规则)。 | 可训练(通过反向传播优化)。 |
应用场景 | 数据预处理、位置信息编码、分类标签处理。 | 词向量表示、类别特征嵌入、图节点表示。 |
二、常见Encoding编码
(1) 独热编码(One-Hot Encoding)
-
定义:将离散类别映射为二进制向量,仅一个位置为1,其余为0。
-
注意:
独热编码 使用 torch.nn.functional.one_hot
,注意设置num_classes
参数。 -
示例:
# 类别:["猫", "狗", "鸟"]
"猫" → [1, 0, 0]
"狗" → [0, 1, 0]
"鸟" → [0, 0, 1]
-
缺点:维度爆炸(高维稀疏),无法表达类别间关系。
参数 | 类型 | 描述 | 是否必需 | 默认值 |
---|---|---|---|---|
tensor | torch.Tensor | 输入的整数类别索引张量(如 [0, 2, 1] ) | 是 | - |
num_classes | int | 类别总数(决定输出维度) | 是 | - |
(2) 位置编码(Positional Encoding)
-
定义:为序列数据(如文本、时间序列)添加位置信息,常用正弦/余弦函数生成。
-
注意:
位置编码 自定义生成矩阵后叠加到词嵌入上,需与输入张量形状匹配。 -
Transformer 中的公式:
参数 | 类型 | 描述 | 是否必需 | 默认值 |
---|---|---|---|---|
max_seq_len | int | 最大序列长度(决定编码矩阵的行数) | 是 | - |
d_model | int | 特征维度(决定编码矩阵的列数) | 是 |
(3) 标签编码(Label Encoding)
-
定义:将类别映射为整数(如 "红"→0, "蓝"→1, "绿"→2),但可能引入错误的大小关系。
(4) 注意事项
-
独热编码的输入限制:
-
输入张量必须是整数类型(如
torch.long
)。 -
索引值必须小于
num_classes
,否则会越界。
-
-
位置编码的叠加方式:
-
需与词嵌入维度一致(
d_model
),且直接相加前确保形状匹配。
-
独热编码 | num_classes | 控制输出维度,避免索引越界 |
位置编码 | max_seq_len , d_model | 定义编码矩阵的尺寸和特征维度 |
三、常见Embedding词嵌入
(1) 基础词嵌入(nn.Embedding
)
nn.Embedding()模块
注意:
词嵌入 | 使用 nn.Embedding 层,输入为整数索引张量,输出为浮点数向量。 |
embedding_layer = nn.Embedding(num_embeddings=10000, embedding_dim=300)
参数 | 类型 | 描述 | 是否必需 | 默认值 |
---|---|---|---|---|
num_embeddings | int | 词汇表大小(唯一符号数量) | 是 | - |
embedding_dim | int | 嵌入向量的维度 | 是 | - |
padding_idx | int | 填充符索引(对应向量初始化为零) | 否 | None |
max_norm | float | 向量最大范数(超过时缩放) | 否 | None |
scale_grad_by_freq | bool | 根据词频缩放梯度(罕见词更大更新) | 否 | False |
import torch.nn as nn
# 定义嵌入层:词汇表大小=10000,嵌入维度=300
embedding_layer = nn.Embedding(num_embeddings=10000, embedding_dim=300)
# 输入:单词索引(形状 [batch_size, seq_len])
input_ids = torch.LongTensor([[1, 22, 45], [3, 8, 2]]) # 示例输入
# 获取词嵌入向量
embeddings = embedding_layer(input_ids) # 输出形状 [2, 3, 300]
(2) 预训练嵌入(from_pretrained
)
nn.Embedding.from_pretrained()
注意:
预训练嵌入 | 通过 from_pretrained 加载,freeze=True 可固定嵌入参数(适用于迁移学习)。 |
pretrained_emb = nn.Embedding.from_pretrained(glove.vectors, freeze=True)
参数 | 类型 | 描述 | 是否必需 | 默认值 |
---|---|---|---|---|
embeddings | torch.Tensor | 预训练嵌入矩阵(形状 [num_emb, dim] ) | 是 | - |
freeze | bool | 是否冻结参数(不更新) | 否 | True |
padding_idx | int | 同基础 nn.Embedding | 否 | None |
max_norm | float | 同基础 nn.Embedding | 否 | None |
如GloVe:
from torchtext.vocab import GloVe
# 加载预训练的 GloVe 词向量
glove = GloVe(name='6B', dim=100) # 使用 100 维的 GloVe
# 获取单词 "apple" 的向量
apple_vector = glove['apple'] # 形状 [100]
# 将预训练向量转换为嵌入层
pretrained_emb = nn.Embedding.from_pretrained(glove.vectors, freeze=False) # freeze=True 表示不更新
(3) 类别特征嵌入(自定义类)
CategoryEmbedding
user_embedding = CategoryEmbedding(num_categories=1000, embedding_dim=64)
参数 | 类型 | 描述 | 是否必需 | 默认值 |
---|---|---|---|---|
num_categories | int | 类别总数(如用户数、商品数) | 是 | - |
embedding_dim | int | 嵌入向量的维度 | 是 | - |
注意:
类别嵌入 | 将高基数类别(如用户ID)映射为低维向量,避免维度爆炸。 |
import torch.nn as nn
class CategoryEmbedding(nn.Module):
def __init__(self, num_categories, embedding_dim):
super().__init__()
self.embedding = nn.Embedding(num_categories, embedding_dim)
def forward(self, category_ids):
return self.embedding(category_ids)
# 示例:用户ID嵌入(假设有 1000 个用户)
user_embedding = CategoryEmbedding(num_categories=1000, embedding_dim=64)
user_ids = torch.tensor([5, 12, 8]) # 输入用户ID
embedded_users = user_embedding(user_ids) # 形状 [3, 64]
(4) 注意事项
-
嵌入层的输入要求:
-
nn.Embedding
的输入为整数索引,非浮点数。
-
-
预训练嵌入的兼容性:
-
加载预训练向量时,需确保
num_embeddings
和embedding_dim
与预训练矩阵一致。
-
基础词嵌入 | num_embeddings , embedding_dim | 决定嵌入层的输入输出维度 |
预训练嵌入 | embeddings , freeze | 加载外部知识,控制参数更新 |
类别嵌入 | num_categories , embedding_dim | 处理高基数离散特征,避免维度灾难 |
四、对比总结
维度 | Encoding | Embedding |
---|---|---|
语义保留 | 无(仅符号化) | 高(捕捉语义相似性) |
计算开销 | 低(静态计算) | 高(需训练参数) |
灵活性 | 固定规则 | 可自适应任务优化 |
典型应用 | 数据预处理、位置编码 | 词向量、推荐系统、图表示学习 |
场景 | 推荐方法 |
---|---|
类别特征且维度低 | 独热编码(简单高效) |
类别特征维度高(如用户ID) | 嵌入(避免维度灾难) |
序列位置信息 | 位置编码(如 Transformer) |
需要捕捉语义相似性 | 嵌入(如词向量) |
计算资源有限 | 优先选择静态编码(如哈希编码) |
五、编码与嵌入的联合使用
在 Transformer 中,词嵌入和位置编码共同构成输入表示:
参数 | 类型 | 描述 | 是否必需 | 默认值 |
---|---|---|---|---|
vocab_size | int | 词汇表大小(词嵌入参数) | 是 | - |
d_model | int | 特征维度(词嵌入和位置编码共享) | 是 | - |
max_seq_len | int | 最大序列长度(位置编码参数) | 是 | - |
import torch
import torch.nn as nn
class TransformerInput(nn.Module):
def __init__(self, vocab_size, d_model, max_seq_len):
super().__init__()
self.token_embedding = nn.Embedding(vocab_size, d_model)
self.position_encoding = self._generate_position_encoding(max_seq_len, d_model)
def _generate_position_encoding(self, max_len, d_model):
position = torch.arange(max_len).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model))
pe = torch.zeros(max_len, d_model)
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
return pe # 形状: [max_len, d_model]
def forward(self, x):
# x: [batch_size, seq_len]
token_emb = self.token_embedding(x) # [batch_size, seq_len, d_model]
seq_len = x.size(1)
positions = self.position_encoding[:seq_len, :] # [seq_len, d_model]
return token_emb + positions # [batch_size, seq_len, d_model]
总结
-
Encoding 是广义的数据转换方式,强调格式兼容性(如独热编码、位置编码)。
-
Embedding 是特殊的编码方法,通过可学习的低维向量捕捉语义信息(如词嵌入)。
-
两者常结合使用(如 Transformer 中的词嵌入+位置编码),分别处理不同维度的信息。