在DeepFM的代码中,embedding向量与特征值相乘时用到广播机制, 其含义:
广播是指在不同形状的张量之间进行逐元素操作时,TensorFlow 自动扩展较小的张量以匹配较大张量的形状的过程。这样可以避免显式复制数据,提高计算效率。
# model embeddings = [batch_size, field_size, embedding_size]
self.embeddings = tf.nn.embedding_lookup(self.weights['feature_embeddings'], self.feat_index) # (batch_size、field_size、embedding_size)
feat_value = tf.reshape(self.feat_value, shape=[-1, self.field_size, 1]) # -1 让 TensorFlow 自动确定第一个维度的大小,
# 以保证总的元素数量不变。-1(N)表示样本数量,
# self.field_size(F)表示特征域数量
# print(feat_value.shape)
# (batch_size、field_size、embedding_size)
self.embeddings = tf.multiply(self.embeddings, feat_value) # 逐元素相乘,內积 tf.multiply支持广播机制
示例:
self.feat_value 的形状为 [2, 3],其中 batch_size=2,field_size=3:
self.feat_value = [
[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]
]
self.embeddings 的形状为 [2, 3, 8],其中 batch_size=2,field_size=3,embedding_size=8:
self.embeddings = [
[
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],
[0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6],
[1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4]
],
[
[2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2],
[3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 4.0],
[4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8]
]
]
在将 self.feat_value 调整形状后:
self.feat_value = tf.reshape(self.feat_value, shape=[-1, self.field_size, 1])
调整后的 self.feat_value 的形状为 [2, 3, 1]:
self.feat_value = [
[
[1.0],
[2.0],
[3.0]
],
[
[4.0],
[5.0],
[6.0]
]
]
当与 self.embeddings 进行逐元素相乘时:
self.embeddings = tf.multiply(self.embeddings, self.feat_value)
结果将是:
self.embeddings = [
[
[0.1 * 1.0, 0.2 * 1.0, 0.3 * 1.0, 0.4 * 1.0, 0.5 * 1.0, 0.6 * 1.0, 0.7 * 1.0, 0.8 * 1.0],
[0.9 * 2.0, 1.0 * 2.0, 1.1 * 2.0, 1.2 * 2.0, 1.3 * 2.0, 1.4 * 2.0, 1.5 * 2.0, 1.6 * 2.0],
[1.7 * 3.0, 1.8 * 3.0, 1.9 * 3.0, 2.0 * 3.0, 2.1 * 3.0, 2.2 * 3.0, 2.3 * 3.0, 2.4 * 3.0]
],
[
[2.5 * 4.0, 2.6 * 4.0, 2.7 * 4.0, 2.8 * 4.0, 2.9 * 4.0, 3.0 * 4.0, 3.1 * 4.0, 3.2 * 4.0],
[3.3 * 5.0, 3.4 * 5.0, 3.5 * 5.0, 3.6 * 5.0, 3.7 * 5.0, 3.8 * 5.0, 3.9 * 5.0, 4.0 * 5.0],
[4.1 * 6.0, 4.2 * 6.0, 4.3 * 6.0, 4.4 * 6.0, 4.5 * 6.0, 4.6 * 6.0, 4.7 * 6.0, 4.8 * 6.0]
]
]
广播机制使得 self.feat_value 的形状 [batch_size, field_size, 1] 可以与 self.embeddings 的形状 [batch_size, field_size, embedding_size] 进行逐元素相乘,从而无需显式地复制 self.feat_value 的数据。这提高了计算的效率和内存的利用率。