赞
踩
背景: 在广告系统中,ctr、cvr预估模型训练时通常将样本转换成embedding输入网络进行训练,得到最终的预估值。embedding被称为sparse model、大模型等,是模型训练和预估中极其重要的一环。但关于embedding的含义和使用对于非科班人士比较晦涩,在这里对embedding的引入、含义、应用作系统性的介绍。
分类数据:从有限候选集中选择一个或多个离散项作为输入特征,如电影集、单词集
在分类数据的表示上,最直接的方法使用id唯一表示候选集中的项,但在训练的时候会带来维度的不统一,以电影集为例,对于不同用户观看过的电影数量不同,导致特征维度不同。一个有效的方法是稀疏向量表示,类似one hot 编码。(另一种说法是将每个稀疏向量表示为数字向量,以便语义上相似的项(电影或单词)在向量空间中具有相似的距离)
ont hot编码:将离散的分类变量转换为稀疏的二进制向量表示,以便更好地在机器学习模型中使用。One-Hot编码将每个分类变量的取值映射为一个只有一个元素为1,其余元素为0的向量。向量的长度等于分类变量的取值个数。对于给定的样本,如果它属于某个分类变量的某个取值,那么该取值对应的位置为1,其他位置为0。
但one hot编码及衍生的离散变量表示仍存在显著的缺点:one hot vector维度太大,以及不同向量之间的距离刻画问题。大型稀疏向量直接导致网络层的节点数巨大,这意味着训练需要的有效数据量也要非常大才行,另一方面训练时的运算量也会成倍增加。 而向量中相邻的两个值并不见得有相近的语义关系,无法表示特征之间的相似性。
embedding可以很好解决上述分类数据表示的问题。embedding将大型离散向量转换到具有语义相似性的低维向量空间中,即将高维、稠密的向量映射到低维、连续的向量空间中。如大小为999的词汇集,映射到8维的embedding,维度直接少了两个数量级。在embedding中,语义不同的向量表示通常距离很远,这样同时解决了维度、语义两个问题。
embedding是一个矩阵,每列表示item的向量表示,要获取单个item的稠密向量,就检索对应的列。参照tensorflow中的tf.nn.embedding_lookup函数。
在推荐算法中,embedding的获取当做网络训练的一部分,这种方法可以为特定系统定制良好的embedding。
以tensorflow中api的使用来说明分类数据到模型输入embedding的过程
tf.feature_column.categorical_column_with_vocabulary_list
:用于创建分类特征列的方法。它用于将离散的分类特征转换为可以输入到 TensorFlow 模型中的特征列对象。
tf.feature_column.embedding_column
:用于将分类特征转换为嵌入(embedding)向量
具体过程如下(来自于chatgpt):
tf.feature_column.embedding_column
方法会创建一个嵌入表(embedding table),该表将每个离散取值映射为一个嵌入向量。嵌入表是一个可训练的参数,其维度由指定的嵌入维度决定。import tensorflow as tf
# 定义数据集
data = {
'gender': ['male', 'female', 'male', 'female', 'male'],
'occupation': ['engineer', 'doctor', 'teacher', 'doctor', 'engineer']
}
# 创建分类特征列
gender_column = tf.feature_column.categorical_column_with_vocabulary_list(
key='gender',
vocabulary_list=['male', 'female']
)
occupation_column = tf.feature_column.categorical_column_with_vocabulary_list(
key='occupation',
vocabulary_list=['engineer', 'doctor', 'teacher']
)
# 创建嵌入特征列
embedded_gender_column = tf.feature_column.embedding_column(
categorical_column=gender_column,
dimension=3 # 指定嵌入维度
)
embedded_occupation_column = tf.feature_column.embedding_column(
categorical_column=occupation_column,
dimension=5 # 指定嵌入维度
)
# 将特征列转换为输入层
input_layer = tf.keras.layers.DenseFeatures([
embedded_gender_column,
embedded_occupation_column
])
# 构建模型,此处仅为示例
model = tf.keras.Sequential([
input_layer,
# 添加其他层...
])
# 编译和训练模型...
tf.feature_column.embedding_column
方法将离散特征 occupation
转换为嵌入特征。
嵌入表查找的过程可以简述如下:
'engineer'
、'teacher'
、'doctor'
、'artist'
)和每个职业对应的 3 维嵌入向量。occupation
时,我们可以使用 tf.nn.embedding_lookup
函数来进行嵌入表的查找。该函数接受两个参数:嵌入矩阵和要查找的索引。occupation
特征,我们将其整数索引作为输入传递给 tf.nn.embedding_lookup
函数。函数将会在嵌入矩阵中查找对应索引的嵌入向量。tf.nn.embedding_lookup
函数返回的是查找到的嵌入向量。这些嵌入向量可以作为模型的输入,用于表示离散特征的信息。import tensorflow as tf
# 嵌入矩阵,维度为 (4, 3)
embedding_matrix = tf.Variable([[0.1, 0.2, 0.3],
[0.4, 0.5, 0.6],
[0.7, 0.8, 0.9],
[1.0, 1.1, 1.2]])
# 索引化特征列
occupation_column = tf.feature_column.categorical_column_with_vocabulary_list('occupation', vocabulary_list=['engineer', 'teacher', 'doctor', 'artist'])
indexed_occupation_column = tf.feature_column.indicator_column(occupation_column)
# 输入数据
inputs = {'occupation': [2, 0, 1]} # 假设有 3 个样本
# 查找嵌入向量
embedded_occupation = tf.nn.embedding_lookup(embedding_matrix, indexed_occupation_column)
embedded_occupation = tf.keras.layers.Flatten()(embedded_occupation) # 将嵌入向量展平
# 将嵌入向量作为模型的输入进行后续处理
# ...
# 在训练过程中,模型会根据损失函数对嵌入矩阵进行更新
# ...
refs:
深度学习中的embedding
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。