共计 1770 个字符,预计需要花费 5 分钟才能阅读完成。
前言
ok,继续开展召回的学习。这一篇是阿里的2018 kdd的文章,属于Graph Embedding领域。在我们的场景中会用在i2i的召回环节当中。
阿里发布这篇文章提到想要解决的问题:可扩展性、稀疏性和冷启动问题。
稀疏性:目前大部分推荐系统都是28原则,所以肯定是会存在很多物料的真实用户行为比较少,这部分的数据表现的稀疏性
冷启动:新物品的上架,如何给量,如何评估与库里的物品之间的相似度
可扩展性:
通篇文章我觉得最主要的还是 side information的引入。也许你会想这篇文章使用了有向图,但是这个有向图在所有的场景中都是必须的?是不是无向图也是可以的?DeepWalk 生成序列受转移概率的影响,这里涉及到边权重的问题,这里可能跟node2vec不太一样吧。训练的时候也是跟word2vec差不多,使用skip-gram的方式训练。
至此序列生成或者训练基本上都是遵循前者的经验,非要说可能有些业务上的trick,比如序列的切分等。
模型逻辑
- 构建有向图
- 生成序列
- skip-gram训练
细节阐述
回顾 word2vec ,这里只需要物料的id即可,不需要其他任何特征。但是物料的价格、颜色、标签等信息都是描述商品很有效的信息,这里面包含大量的先验信息。EGES很好的融合这些特征信息,并且将这些特征的向量映射到同一个向量空间里,然后通过信息融合的方式融合所有的先验信息来全方位表征物料。并且在融合的过程中引入权重,类似Attention那样输出权重,强调重要特征与次要特征的差异性,保留更多的有效信息。
上图中a_0…a_n表示是的对应的每个side information 的特征的权重。
代码实践
代码可以参考这个仓库 https://github.com/wangzhegeek/EGES
下面给出部分的介绍
def attention_merge(self):
'''
各个特征的权重以及特征Embedding的融合
'''
embed_list = []
num_embed_list = []
for i in range(self.num_feat):
cat_embed = tf.nn.embedding_lookup(self.embedding[i], self.inputs[i])
embed_list.append(cat_embed)
stack_embed = tf.stack(embed_list, axis=-1)
# attention merge
alpha_embed = tf.nn.embedding_lookup(self.alpha_embedding, self.inputs[0])
alpha_embed_expand = tf.expand_dims(alpha_embed, 1)
alpha_i_sum = tf.reduce_sum(tf.exp(alpha_embed_expand), axis=-1)
merge_emb = tf.reduce_sum(stack_embed * tf.exp(alpha_embed_expand), axis=-1) / alpha_i_sum
return merge_emb
def make_skipgram_loss(self):
'''
skip gram 训练
'''
loss = tf.reduce_mean(tf.nn.sampled_softmax_loss(
weights=self.softmax_w,
biases=self.softmax_b,
labels=self.inputs[-1],
inputs=self.merge_emb,
num_sampled=self.n_samped,
num_classes=self.num_nodes,
num_true=1,
sampled_values=tf.random.uniform_candidate_sampler(
true_classes=tf.cast(self.inputs[-1], tf.int64),
num_true=1,
num_sampled=self.n_samped,
unique=True,
range_max=self.num_nodes
)
))
return loss
问题思考
- 新物品来了,不在训练的图中,如何生成Embedding?
- 图数据边权为1 的边有没有意义?
- 有向图是必须的?