20

数据与广告系列十九:推荐召回与广告LookAlike,万物皆可Embedding

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAxMjM2MTY0OQ%3D%3D&%3Bmid=2650474368&%3Bidx=1&%3Bsn=89eab1cc8a23e6414bd6e5d9b4902bf6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

作者·黄崇远

『数据虫巢』

全文共 1000

题图ssyer.com

rUFfaeZ.jpg!web

万物皆可Embedding,开启全面数据化的时代。

正式打算写Embedding相关话题之前,有突然想到N年前看过的《黑客帝国》,如果人或者其他事物只是一串数字或者一行代码,那的多虚幻。但难以想象的是,我们的世界离那种“境界”已经不是遥不可及了。

01

对事物描述方式的变迁

通常我们对一个事物的描述,都会从各个维度去描述它,并附带上其各种属性来描述它的唯一性。
比如,我们描述一辆车可能会从什么颜色,几座,价格,动力类型,品牌等维度去定义一辆汽车。如果以广告来看的话,我们可能从规格,素材,出价,投放内容,广告位,广告主,广告类型,投放时间等等来描述这个广告,定义这个广告的唯一性。
这是一种非常通用,又非常被人类所理解的方式。请注意,这里说的是以人类容易理解的方式,很长一段时间我们都是这样去描述一件事物的,哪怕是我们开始使用机器去定义一个事物的时候,也是以这种方式去定义,然后再逐步转换成事物的属性,或者说特征。
我依稀还记得六七年前所经历的项目,那是在一个内容流里做视频的关联推荐,当初绞尽脑汁能想的是,如何构建待推荐视频和内容流相同或者相类似的属性,然后根据属性的关联行来构建推荐的关联性,然后在线上去做偏实时的属性关联检索召回。
哪里能想得到,有一天能够使用纯粹的一串数字(矩阵向量)来描述不同的事物,然后在相同事物或者不同的事物间只需要做简单的数学计算,就把事物时间的关联性给构建起来了。
并且这种关联性并不是那种显性的关联,所谓显性的关联就是,A事物拥有c属性,B事物也拥有c属性,所以,我们通过属性的关联把A跟B关联起来。
上升到机器学习领域,在过去很长的一段时间,我们都在致力于寻找数据的特征上,想方设法从各个维度去描述数据,然后进一步把特征抽象出来,用于算法模型的训练,然后再做分类或者预测以实现我们的自动化学习的目的,而这些特征大多数是具有具象意义的,可解释的。
而Embedding的方式则打破了这一“定律”,致力于将任何事物通过一个向量得以描绘,并且这个向量是具有实际意义,但又无法具象化解释的存在。

02

什么是Embedding

什么是Embedding?

从谷歌词典上的翻译来看,是“把...牢牢地嵌入(插入或者埋入)”,很贴切。因为它源自于谷歌开源的word2vec模型,并且源自于“word embedding”,意义为将word映射(嵌入)到另一个空间。

而word2vec的核心输出就是word embedding,也是word向量矩阵。里头每个word的向量都具有实质上的意义,虽然通过空间变换已经很难看出具象化的意义,但是它确实能够很好的表征这个词,并依赖不同word之间的向量计算具有实际上的关联意义。

既然语句能够通过这种方式将单个的word做embedding,从而保留word本身的语义,且最终输出如此便捷便于计算的形态,那么,能不能扩展出去呢?扩展到非单纯的NLP领域。

所以,就有了微软在2016年基于推荐领域研究发布的一篇论文《Item2Vec:Neural Item Embedding for Collaborative Filtering》。

67RzEvR.jpg!web

这篇论文其实并不算很复杂,其核心是立足于Skip-gram加上Negative Sampling的逻辑,去做item-based CF。而前两者本身就是word2vec的核心理论逻辑,所以这整体的方法逻辑被命名为item2vec就非常好理解了。

这篇论文就如同开启了万物皆可embedding的“潘多拉魔盒”。在过去,我们总是想方设法给事务寻找特征和属性,然后基于这些属性去构建推逻辑或者其他机器学习的逻辑。

而item2vec的出现告诉我们,不需要这么复杂,我们只需要用户使用这些实体的所有记录就可以了,我们甚至不需要深究这个实体的具体属性是如何的,基于人和实体的交互序列,我们就可以使用一串“神秘的数字”(embedding的向量)来描述它,然后将它用于推荐逻辑上,当我们看到A电影时,通过他们神秘数字的数学计算,就可以很快的知道更相关的内容是什么。

至此,我们再来梳理一下,embedding这种表征的意义在哪里。

在过去,我们对于实体的描述,通常会使用one-hot编码,这也是一种非常通用的做法。但当我们的编码池非常大的时候,这会导致我们的one-hot编码非常稀疏,而异常稀疏的特征描述对于很多算法模型来说是灾难性的。

embedding的一大作用是,能够对实体进行降维,并且保留实体的语义关联性,带来的是训练效率的数量级提升。

同时,由于embedding的生成过程中保留了实体原有的“语义”关系,所以,最终输出的向量仍具有可比性,可以关联计算,并且由于转换为了向量形态,各种数学计算逻辑依然保留了其实际的作用。

在embedding实际的应用中,有直接基于其向量构建相似关系,比如应用于推荐领域,或者一些召回场景,也有构建不同实体之间的embedding,做不同实体之间的关联计算,这就是后面会补充说到DSSM模型,还有将embedding转化后的特征,作为模型的输入,加快模型训练的效率等等。

对于实现层面来说,其实embedding更多提出的是一种将item embedding化的概念,而并非限制于说一定使用word2vec对item进行向量化,而是item2vec这篇论文为大家打开了另一种构建实体描述方式并加以应用的思路。

所以,只要是将item映射到另一个空间维度的方式都可以称之为embedding,比如PCA降维,又比如之前我们在《数据与广告系列十四:智能定向&基于FM的标签组合推荐思路》中提到过的FM特征输出,同样可以把FM模型矩阵分解中间过程中产生的分解矩阵作为embedding。

另一个思路就是深度神经网络,比如基于word2vec序列输入的思路,其实就有点类似单隐藏层的神经网络。还有基于有监督的一些比如DNN之类的模型,同样可以把节点参数最终构建成实体的embedding向量。

而后面两种,一种基于无监督序列作为输入的方式,以及基于有监督NN训练的节点参数作为输出的方式,成为了当前计算embedding主流方式,我们接着会看到大量经典工业案例,都是基于这两种基础的输出方式构建embedding的。

当然,在实际的工程逻辑上他们进行了大量的改进和以及结合自身业务落实的优化手段,最后输出成学术界可参考的工程论文(学术界越来越具有务实的风格了)。

03

Embedding的应用

为了更容易理解embedding的作用,感受它的魅力,我们必须要拿点证据出来,上面那篇论文只是提出这一种embedding的方法,并未从实际工业角度证明这种方式有多么的好使。

真正证明其价值并让其大放光彩,让各大司争相“抄作业”的是YouTube和Airbnb,国内的代表是阿里。

分别对应三篇论文:

《Deep Neural Networks for YouTube Recommendations(2016)》

《Real-time Personalization using Embeddings for Search Ranking at Airbnb(2018)》

《Learning and Transferring IDs Representation in E-commerce(2018)》

并且涉及到的实际应用领域覆盖推荐,广告,搜索等全是核心关键的技术领域,解决的都是万年难题,任何一个基数点的优化提升都是百万千万的现金收入。

就论文的应用场景来看,YouTube应用于其推荐系统,并且核心是构建推荐系统的深度模型,而Airbnb则应用于相似推荐和检索召回的场景,对于阿里的论文来说更多的是一种特征的生成方式,而不涉及具体的上层场景。

YouTube的论文其实感觉核心不在Embedding上,更多篇幅讲解的是整个召回和排序的深度模型如何构建,Embedding的特征输入反倒没有重点说。

ArqUfqY.jpg!web

上图为YouTube排序阶段的网络结构。

真正重点突出Embedding的作用的是Airbnb的论文,按论文的说法就是通过对访客访问Listing Embedding构建,突破了以往难以对于酒旅这种低频交互场景精准预测的难题。

论文中使用了大量的篇幅介绍了Airbnb是如何结合业务特点,来构建用户的Listing序列,以及在构建Listing Embedding过程的注意事项,包括对Listing的去噪,截断等等。

除此之外,虽然核心同样是基于序列输入做Embedding输出,Airbnb还重点介绍了如何结合自身业务来优化目标函数。最后基于生成的Listing Embedding作用于冷启动的相似房源推荐中,而在检索模型里,则把Embedding作为NN的特征输入。

iMFjien.jpg!web

上图为Airbnb最终输入搜索排序的embedding再加工之后的特征,以及特征的最终重要度。

针对于Embedding的形态,在同一类的相似关系计算上,应该是非常便捷的,不需要额外的模型设计,直接计算向量内积就可以构建相关关系了,而同类的相似推荐有太多的场景例子可以举例了。

而推荐系统作为同类型实体推荐的场景,简直太适合了,所以很多时候可以通过相似关系计算,来做快速召回。

由于Embedding的构建方式,使得其避免了传统特征处理导致的稀疏问题,而过于稀疏的特征不管是在传统的LR模型上,还是深度模型上都是不利的,所以很多场景下都是把Embedding作为特征输入来使用。

结合YouTube的使用方式,即构建user embedding与video embedding的关联空间的方式,使得不同主体之间同样可以构建相同关联关系维度的向量,基于这个向量快速计算相关关系,甚至如论文中所说,很多时候在线上实际的serving中,放弃了复杂的模型,直接快速的近邻检索(检索相近向量),然后作为结果进行输出。

关于不同实体间的embeding关联关系计算,又衍生出来所谓的“双塔模型”DSSM,包括一系列的变种C-DSSM,LSTM-DSSM等等,由于DSSM也不是固定的模型逻辑,更多提供的是一种双塔计算架构,所以业界各种大公司(微软,谷歌,IBM,淘宝,美团等等)都不亦乐乎的改进这种初始架构,然后以适应自身的数据特点和业务。

这些东西任何一个点,展开来说都远不止一个章节,甚至不止一篇文章,所以这里就不会再往细的地方展开说。

结合诸如YouTube这种计算user embedding 与video embedding,然后做近邻搜索的方式,我们再来看下广告领域。在过去,我们做Lookalike的时候,绞尽脑汁地去计算种子用户候选用户池的关系评分,并尽量的让点击auc提升。

基于YouTube的方式,我们完全也可以计算user embedding与关联的ad embedding,然后再结合当前投放ad,直接圈选近邻的user,这是一种考虑上下文(ad投放场景)的用户查找,并且完全抛开了定向条件,完全可以作为在线的LookAlike使用。

由于Embedding本身就是一种非常偏原始数据描述的存在,所以在上层可以有非常多的想象空间,关键在于这种突破了以往逻辑的实体描述与特征构建方式,非常契合当前大规模数据机器化描述的场景。

04

基于开源Movies数据集手撸embedding

科普再多,不如近身的体验一把,才有更深刻的印象。

这里,我们将基于word2vec的方式,构建item 的embedding,其实也就是上面提到的item2vec,然后再基于计算的item embedding做一下简单的相似推荐。

这里我们就直接使用现成的word2vec模型,核心在于输入item序列的构建。

在word2vec模型训练方面,我们使用gensim这一NLP“神器”,它提供了经典的TFIDF,LSA,LDA以及word2vec等NLP领域常用的算法模型的实现。

如果没有安装的话,使用anaconda安装一下。

6fUVbar.jpg!web

至于数据集,使用了经典的开源数据集movieens,包含了138000名用户完成关于27000部电影的2000万个评价数据和46.5万个标签数据,是做推荐系统实践的不二选择。

巧了,刚好我们也要使用embedding体验一把相似推荐。

JfeaYvn.jpg!web

我们主要使用这两个数据文件,两个文件的字段以及数据样式如下。

NrENniY.jpg!web

ratings文件可以看作是user与movies的交互行为文件,这是我们构建item序列的基础,我们将以单个user作为group,组合movies的序列输入。而movies文件则作为字典文件存在。

gensim的word2vec模型输入是一个sentences (iterable of iterables, optional)。所以,我们以用户+评分类别(好坏)作为分组,构建输入。

##构建item序列,并根据分数来做类别划分

def rating_splitter(df):

df['liked'] = np.where(df['rating'] >= 4, 1, 0) #输出0/1划分

df['movieId'] = df['movieId'].astype('str')

gp_user_like = df.groupby(['liked', 'userId'])


splitted_movies = rating_splitter(df_ratings_train)

调用gensim进行模型训练:

model = Word2Vec(sentences=splitted_movies, #迭代序列

iter=5, #迭代次数

min_count=4, #忽略词频,小于10的将被忽略掉

size=32, #训练后的向量维度

workers=2, #设置的线程数

sg=1, #训练模型的模型选择,1=skip-gram,0=CBOW

hs=0, #训练代价函数的选择

negative=5, #负采样

window=5) #当前词和预测词的最大间隔

跑起来的时候,我的阿里云小服务器CPU直接就99%了。

fQF7BzF.jpg!web

这小服务器,还是为了跑这个实例临时升级的,从单核4G,直接升级为2核8G,补了一年的差价近2000大洋(为了跑个demo,我把一个月的饭钱贴进去了)。

然后输出就是“词”向量,就是movies的向量model.wv。除此之外,gensim提供了指定word的相似向量输出的方法,可以用来做简单的推荐,来验证向量计算的合理性。

movieId_to_name = pd.Series(df_movies.title.values, index = df_movies.movieId.values).to_dict()

name_to_movieId = pd.Series(df_movies.movieId.values, index = df_movies.title.values).to_dict()


def produce_list_of_movieId(list_of_movieName):

list_of_movie_id = []

for movieName in list_of_movieName:

if movieName in name_to_movieId.keys():

print(f"model:produce_list_of_movieId, movieName: "+ movieName)

list_of_movie_id.append(str(name_to_movieId[movieName]))

print(f"model:produce_list_of_movieId, list_of_movie_id:{list_of_movie_id}")

return list_of_movie_id


def recommender(positive_list=None, negative_list=None, topn=20):

recommend_movie_ls = []

if positive_list:

print(f"model:recommender, positive_list:{positive_list}")

positive_list = produce_list_of_movieId(positive_list)

if negative_list:

print(f"model:recommender, negative_list:{negative_list}")

negative_list = produce_list_of_movieId(negative_list)


print(f"model:recommender, positive_list:{positive_list}")

for movieId, prob in model.wv.most_similar_cosmul(positive=positive_list, negative=negative_list, topn=topn):

recommend_movie_ls.append(movieId)

return recommend_movie_ls

这里我们以玩具总动员为例,作为输入,通过model.wv.most_similar_cosmul输出topN的相似item。

m_now="Toy Story 3 (2010)"

ls = recommender(positive_list=[m_now], topn=5)

print(f'Recommendation Result based on "{m_now}":')

display(df_movies[df_movies['movieId'].isin(ls)])

3AJnYzN.png!web

全是英文片名,不是很直观,为了验证合理性,我分别取了一些不同类别的典型知名电影作为输入,观测其top5的相似电影。

m6vIRvy.jpg!web

输入是玩具总动员3,输出的top5分别如上,整体而言应该没有很大的毛病,从个人的角度来看相关性还是挺大的。

yqQ7rai.jpg!web

这波的输入是变形金刚,输出是蜘蛛侠3,无敌浩克,我是传奇,通缉令,全民超人汉考克,整体而言捕捉到了类似的元素。

YRbURbq.jpg!web

选择了灾难片2012作为输入,这波的输出有点看不懂。

IJ7VFfm.jpg!web

泰坦尼克号作为输入,整体的输出偏剧情和文艺,并且年代也很符合很相近,要知道我们根本就没有模型中输入任何电影年份相关的特征属性。

zIFFvqZ.jpg!web

最后一组是偏战争类电影,同样也挺ok的输出,偏战争,大规模的枪战等。

最后,我们可以看到,虽然是一次最简单的embedding的实践,学习库是现成的,数据集是开源的,但是结果并没有让人太失望,反而有点小惊喜(不信的话可以用传统的CF对比看看)。

05

总结

Embedding的这种事物描述方式,决定了将不再依赖于事物本身固有的属性对事物加以理解,而是依赖于事物本身与其他实体间产生的交互行为作为输入,最终获取到事物实体的数据化描述。

正如题头所说,万物皆可embedding,开启全面数据化时代并非一个虚言。

随着5G网络的覆盖,进一步让通讯以及数据传送效率提升,这就意味着终端的数量会海量暴增,所谓终端即一切可以收集数据的感应器,包括我们所熟悉的手机电脑等,还有摄像头,各种智能家居,甚至包括各种工业农业感应器。

你会发现,任何事物的变化,最终都会形成网络上的一段数据记录,当我们有了对数据更好的理解方式或者转换方式(embedding或者其他更好的方式)之后,数据的应用效率也将大大提升,全面数据化时代真的不是一句空想。

而我们所关注的商业化广告,也只是茫茫数据海中的一小部分。

参考文献

【01】

《Item2VecNeural Item Embedding for Collaborative Filtering(2016)》

【02】

《Deep Neural Networks for YouTube Recommendations(2016)》

【03】

《Real-time Personalization using Embeddings for Search Ranking at Airbnb(2018)》

【04】

《Learning and Transferring IDs Representation in E-commerce(2018)》

【05】

https://radimrehurek.com/gensim/models/word2vec.html

【06】

https://grouplens.org/datasets/movielens/

文章都看完了,还不点个赞来个赏~

OTHER 相关系列文章(数据与广告系列)

《数据与广告系列八:广告与二类电商》

《数据与广告系列九:有意思的本地化广告》

《数据与广告系列十一:从性别预测的CASE开始手撕机器学习代码》


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK