1.背景:
最早看到Item2vec是微软研究院的这篇文章,发表于2016年ICML。本文主要是对这篇论文做一些介绍,Item2vec主要思想是借鉴了Word2Vec,并且采用SGNS(Skip-gram + Negative Sampling,思想是用中心词预测周围的词)的方法来生成物品向量,最后只需要计算当前浏览的物品与其它物品的向量相似度,从而找到相似物品。一般像电商网站的“看了也看”、“买了也买”、“相似物品”模块比较适合应用Item2Vec算法。
主要做法是把item视为word,用户的行为序列视为一个集合,item间的共现为正样本,并按照item的频率分布进行负样本采样,缺点是相似度的计算还只是利用到了item共现信息,1).忽略了user行为序列信息; 2).没有建模用户对不同item的喜欢程度高低。
Item2Vec这个名词的由来:在隐空间中产生的item embeding向量用在基于item的协同过滤,这种方法称之为item2vec。(原文:we name Item2Vec for item-based CF that produces embedding for items in a latent space)
2.原理
SGNS:
优化目标:中心词存在的情况下周围词存在的概率最大,从而得到所有词的向量:
negative sampling--- 提升计算性能
在词库数量10万-100万的量级下,计算p(wj |wi)的代价会非常大,因此采用负采样来减少计算。对每个正样本,根据3/4指数分布采样N个负样本,这个采样比例是在实验中效果显著的。
这个公式的意义:u是target,v是context,最大化和u有关联的v,最小化和u没关联的v.sigmod函数。
对于常见词和不常见词的不平衡性问题,这里做了一下下采样,给出一个输入序列,以一定概率丢弃这个词w,频率越高,丢弃的概率越大。
Item2Vec – SGNS for item-based CF
实验结果好于SVD,item2vec对出现次数少的item也有较好的表示,得益于负采样和丢词优化。
3.代码注解:
sparkML中的demo,配合自己的输入,做轻微改动:
//输入是一个item list
val splitUDF = udf({str: String => str.split(",")})
val trainData = df.withColumn("itemList", splitUDF(col("itemlist"))).cache()
val item2Vec = new Word2Vec()
.setInputCol("itemlist")
.setOutputCol("itemvector")
.setMinCount(100)
.setVectorSize(64)
val model = item2Vec.fit(trainData)
val itemVector = model.getVectors
.withColumn("itemVectorStr", mkStringUDF(col("vector")))
.select("word", "itemVectorStr")
.cache()
itemVector.show(false)
//user的vector是由用户对item有过交互的item的list求平均
val userData = getData.getUserBehavioralSequenceData()
.withColumn("itemList", splitUDF(col("itemlist")))
.cache()
val userVector = model.transform(userData)
.withColumn("userVectorStr", mkStringUDF(col("userVector")))
.select("user_id", "userVectorStr")
.cache()
userVector.show(false)
4.论文精读:
参考:
1.论文:https://arxiv.org/vc/arxiv/papers/1603/1603.04259v2.pdf
3.介绍word2vector和item2vector:https://blog.csdn.net/fuzi2012/article/details/91345164
4.个性化召回的应用:https://www.cnblogs.com/hellojamest/p/11766401.html
5.原理概要:https://zhuanlan.zhihu.com/p/24339183?refer=deeplearning-surfing
6.python实现 地址