当前位置: 首页 > 科技观察

深度学习在电商商品推荐中的应用

时间:2023-03-18 14:22:37 科技观察

1.常用算法套路在电商行业,为用户推荐商品一直是一个非常热门和重要的话题。成熟的方法有很多,但各有优缺点,大致如下:基于产品相似度:比如食品A和食品B,对于它们的价格、口味、保质期、品牌等维度,可以计算他们的相似性。可以想象,我买包子的时候,可能会顺路带一盒饺子回家。优点:冷启动,其实只要有产品数据,在业务前期用户数据不多的时候也可以做推荐。缺点:复杂的预处理,任何产品至少可以有数百个维度,如何选择合适的这些是典型的用钱买不到的例子:亚马逊早期的推荐系统是基于关联规则的:最常见的是通过用户的购买习惯上,最经典的案例就是“啤酒尿布”案例,但在实际操作中,这种方式用得最少。首先,必须制定关联规则。数据量一定要足够,否则置信度会太低。当数据量变大的时候,我们有更多优秀的方法,可以说是没有亮点了。业界的算法具有apriori和ftgrow的优点:简单易操作,上手速度快,部署非常方便。缺点:需要更多的数据,准确率效果一般:早期运营商的包裹推荐是基于物品的协同推荐:假设物品A已经被小张、小明、小东买过,物品B有已被小红、小李、小陈购买,C项已被小张、小明、小李购买;直观上,itemA和itemC的买家有更高的相似度(相较于itemB)。现在我们可以向小东推荐C项,向小李推荐A项。可解释性强,副产品可以用来排序热门商品缺点:计算复杂,数据存储瓶颈,冷门商品推荐效果差火锅底料,用户B买过卫生纸,衣服,鞋子,用户C买过火锅、汁、七夕;直观上,用户A和用户C更相似(相对于用户B),现在我们可以给用户A买推荐用户C买的其他东西,把用户A买的其他东西推荐给用户C。优缺点类似基于项目的协同推荐,不再赘述。基于模型的推荐:svd+、特征值分解等,将用户的购买行为矩阵拆分为两组权重矩阵的乘积,一组矩阵代表用户的行为特征,一组矩阵代表商品的重要性.在推荐过程中,在历史训练矩阵下计算每个商品给用户推荐的可能性。优点:准确,对冷门商品有很好的推荐效果缺点:计算量非常大,矩阵拆分的性能和容量瓶颈一直受到约束典型:惠普的电脑推荐是基于时序推荐:这个是特别的,在电商里面用的很少,推特、脸书、豆瓣用的比较多,就是只有赞同和不赞成的评论怎么排序。具体可以参考我之前写的一篇文章:应用:推荐系统-Wilson区间基于深度学习的推荐:CNN(卷积神经网络)、RNN(递归神经网络)、DNN(深度神经网络),比较流行现在,都有用在推荐上的例子,但是都还在实验阶段,但是有一个基于word2vec的方法比较成熟,也是我们今天介绍的重点。优点:推荐效果非常准确,对基础存储资源占用少。缺点:工程应用不成熟,模型训练和调参技巧有难度。典型:苏宁易购会员产品推荐2、item2vec项目介绍。现在苏宁有大约4个产品,10000多个产品品类,近40个大品类。如果采用传统的协同推荐进行实时计算,服务器成本和计算能力都非常有限。之前有过几次申请。简介:基于推荐的交叉销售,基于用户行为的推荐预估。由于会员研发部门不是主要的推荐应用部门,我们期望在选择方面有一个更高效、高速、相对准确的简化版模型,所以我们在word2vec原有算法的基础上模仿了itemNvec的方法.首先我们从理论上拆分itemNvec:第一部分:n-gram目标产品前后的产品对目标产品的影响程度。这是两个用户userA和userB在e-buy上的消费时间线。灰色方框是让我们观察对象,问一下,如果我们改变灰色方框内userA和userB的购买项目,直观的可能性有多大?直觉经验告诉我们这是不可能的,或者说肯定不会经常发生,所以,我们有一个初步的假设,对于特定品类中的某些用户,用户的消费行为是持续受到影响的。换句话说,我买什么取决于我以前买过什么。如何通过算法语言来解释上述事情?让我们回忆一下,朴素贝叶斯是如何进行垃圾邮件分类的?假设“我公司可以提供发票、军售、航母维修”这句话不是垃圾邮件?P1("垃圾邮件"|"我司可提供发票、军售、航母维修")=p("垃圾邮件")p("我司可提供发票、军售、航母维修"/"垃圾邮件")/p("我司可提供发票、军售、航母维修")=p("垃圾邮件")p("发票","军火","航母"/"垃圾邮件")/p("发票","军火","航母")同理P2("平邮"|"我司可提供发票,军售,航母维修")=p("平邮")p("发票","arms","aircraftcarrier"/"normalmail")/p("invoice","arms","aircraftcarrier")我们只需要比较p1和p2的大小,可以直接写成:P1("垃圾邮件"|"我司可提供发票、军售、航母维修")=p("垃圾邮件")p("发票"/"垃圾邮件")p("军火"/"垃圾邮件")p("航母"/"垃圾邮件")P2("普通邮件"|"我司可提供发票,军售,航母维修")=p("普通邮件")p("发票"/"普通邮件”)p("arms"/"normalmail")p("aircraftcarrier"/"normalmail")但是,我们看到无论顺序如何“我公司可以提供发票,军售,和航空母舰维修”的变化,不影响其最终的结果判断,但在我们的需求中,较早购买的物品对后者的影响较大。冰箱=>洗衣机=>衣柜=>电视=>汽水,这样的排序流程是合理的>洗衣机=>汽水=>电视=>衣柜,这个排序流程相对不太可能但是对于朴素的贝叶斯来说,它们是相同的.所以,我们考虑这里的顺序,或者上面spam的问题。P1("垃圾邮件"|"我司可提供发票、军售、航母维修")=p("垃圾邮件")p("发票")p("军火"/"发票")p("军火"/"航母")P1("平邮"|"我司可提供发票,军售,航母维修")=p("平邮")p("发票")p("军火"/"发票")p("arms"/"aircraftcarrier")在这里我们只依赖于每个单词的前一个单词。理论上,依靠1-3个词通常是可以接受的。上述考虑顺序的贝叶斯是基于著名的马尔可夫假设(MarkovAssumption):下一个词的出现只取决于它前面一个或几个词下的联合概率问题,并没有给出相关详细的理论数学公式.out,这里涉及到一个思想。第二部分:哈夫曼编码的大数据存储形式。我们常用的用户到项目的映射是以一种热编码的形式实现的。这有一个很大的缺点就是数据存储系数和维度灾难的可能性非常高。回到原来的那组数据:苏宁现拥有约4亿种商品,1万多个商品品类,近40个大品类。同时,会员数量已达3亿。如果需要构建一个用户产品对应的购买关系矩阵,如果是基于用户的协同推荐,我们需要做一个4亿X6亿的1/0矩阵,这几乎是不可能的。哈夫曼采用近似二叉树进行存储:我们以采购量为例,说明如何以二叉树的形式代替onehotencoding存储方式:假设,在818苏宁促销期间,经过统计,有是冰箱=>洗衣机=>干衣机=>电视=>衣柜=>钻石的用户订单链(以及购买物品的顺序如上),其中冰箱共售出15万台,洗衣机售出8万台共售出60000台烘干机,共售出50000台电视机,共售出衣柜30000台,共售出10000颗钻石哈夫曼树构建过程1.给定{15,8,6,5,3,1}作为二叉树的节点,每棵树只有一个节点,则有6颗菱形分离树2。选择节点权值最小的两棵树进行合并,即{3}和{1},以及计算合并后的新权重3+1=43。从节点列表中删除{3}和{1}树,将3+1=4的新组合树放回原节点列表中4.重复2-3直到只剩下一棵树。对于每一层的每个分支过程,我们可以将拥有最重要所有权的节点视为1,将权重较小的节点视为0,反之亦然。现在举例,我们要知道钻石的编码是1000,也就是灰色框的位置,洗衣机的编码是111;数据存储空间。第三部分:节点概率最大化当前数据可能出现的概率密度函数。对于菱形的位置,它的霍夫曼编码是1000,也就是说每进行一次二元选择,就需要将它分成1次。分三次为0,每次分的过程中,只能选择1/0。这是不是类似于逻辑回归中的0/1分类,所以这里我们也直接使用lr中的交叉熵作为损失函数。其实对于很多机器学习算法来说,都是基于先假设一个模型,然后构造一个损失函数,用数据训练损失函数,找到argmin(损失函数)的参数,然后放回原来的模型.让我们详细看一下这个菱形例子:第一步p(1|No.1层未知参数)=sigmoid(No.1层未知参数)第二步p(0|No.2层未知参数)=sigmoid(No.2层未知参数)同理,第三层和第四层:p(0|No.3层未知参数)=sigmoid(No.3层未知参数)p(0|No.4层未知参数)=sigmoid(第4层未知参数)然后求p(1|第1层未知参数)xp(0|第2层未知参数)xp(0|第3层未知参数)xp(0|第2层未知参数)4层未知参数)可以使用最大值对应的每一层的未知参数,求解方法类似logistic求解方法,未知参数的分布偏导数,梯度下降法(最大值,batch,Newtonondemand)第四部分在后续采用:刚才近似神经网络乘积的相似度在第三部分有p(1|No.1layerunknownparameter)的逻辑ee,NO.1层未知参数之一是乘积向量。例如:有1000万用户吃过:“啤酒=>西瓜=>剃须刀=>百事可乐”10万用户吃过:“啤酒=>苹果=>剃须刀=>百事可乐”商品的采购订单,如果查看根据naviebayes或n-grams等传统概率模型,P(beer=>watermelon=>razor=>Pepsi)>>p(beer=>apple=>razor=>Pepsi),但实际上,两个人应该是同一波人,属性肯定是一样的。在我们这边,我们随机初始化每个商品的特征向量,然后通过第三部分的概率模型进行训练,最后确定词向量的大小。另外,这样的事情也可以通过神经网络算法来完成。详细的方法在Bengioetal.,《A Neural Probabilistic Language Model》,2001年发表在NIPS中。这里需要知道的是,对于最小维度的商品,我们将0-1点(0,0,0,0,0,1,0,0,0,0...),单一的乘积向量是没有意义的,但是对于成对的乘积向量我们可以比较它们之间的余弦相似度,我们可以比较类别的相似度,甚至类别的相似性。三、Python代码实现1、数据读取#-*-coding:utf-8-*-importpandasaspdimportnumpyasnpimportmatplotlibasmtfromgensim.modelsimportword2vecfromsklearn.model_selectionimporttrain_test_splitorder_data=pd.read_table('C:/Users/17031877/Desktop/SuNing_t/cross_sell_tdata).data'=orderdrop('member_id',axis=1)dealed_data=pd.DataFrame(dealed_data).fillna(value='')2.简单的数据合并排序#datamergingdealed_data=dealed_data['top10']+[""]+dealed_data['top9']+[""]+dealed_data['top8']+[""]+\dealed_data['top7']+[""]+dealed_data['top6']+[""]+dealed_data['top5']+[""]+dealed_data['top4']+[""]+dealed_data['top3']+[""]+dealed_data['top2']+[""]+dealed_data['top1']#数据列dealed_data=[s.encode('utf-8').split()forsindealed_data]#datasplittrain_data,test_data=train_test_split(dealed_data,test_size=0.3,random_state=42)3.模型训练#Original数据训练#sg=1,skipgram;sg=0,SBOW#hs=1:hierarchicalsoftmax,huffmantree#nagative=0非负采样模型=word2vec.Word2Vec(train_data,sg=1,min_count=10,window=2,hs=1,negative=0)接下来就是用模型训练得到我们推荐的商品了。这里有三个思路,可以根据具体业务需求和实际数据量选择:3.1相似商品映射表#最近浏览过的商品最相似的商品组top3x=1000result=[]result=pd.DataFrame(结果)foriinrange(x):test_data_split=[s.encode('utf-8').split()forsintest_data[i]]k=len(test_data_split)last_one=test_data_split[k-1]last_one_recommended=model.most_similar(last_one,topn=3)tmp=last_one_recommended[0]+last_one_recommended[1]+last_one_recommended[2]last_one_recommended=pd.concat([pd.DataFrame(last_one),pd.DataFrame(np.array(tmp))],axis=0)last_one_recommended=last_one_recommended.Tresult=pd.concat([pd.DataFrame(last_one_recommended),result],axis=0)考虑用户对关注商品x的最后一次操作,将那些用户已经购买过的商品kill掉.剩下的item表示用户仍然感兴趣但是因为没有找到合适或者便宜的item,通过商品向量之间的相似度可以直接计算出来,将高度相似的商品推荐给用户。他最有可能购买什么?例如,历史数据告诉我们,购买过手机+电脑的用户最有可能在一周内购买背包,所以我们会针对最近购买过电脑+手机的用户推送电脑包产品。给他,激发他潜在的规律性需求。#向量库rbind_data=pd.concat([order_data['top1'],order_data['top2'],order_data['top3'],order_data['top4'],order_data['top5'],order_data['top6'],order_data['top7'],order_data['top8'],order_data['top9'],order_data['top10']],axis=0)x=50start=[]output=[]score_final=[]foriinrange(x):score=np.array(-100000000000000)name=np.array(-100000000000000)newscore=np.array(-100000000000000)tmp=test_data[i]k=len(tmp)last_one=tmp[k-2]tmp=tmp[0:(k-1)]forjinrange(number):tmp1=tmp[:]target=rbind_data_level[j]tmp1.append(target)test_data_split=[tmp1]newscore=model.score(test_data_split)ifnewscore>score:score=newscorename=tmp1[len(tmp1)-1]else:passstart.append(last_one)output.append(name)score_final.append(score)3.3联想记忆推荐在3.2中,我们根据该用户最近的购买行为,从历史购买用户的购买行为数据中发现规律,提供推荐产品。还有一个大概的逻辑,就是根据目标用户的最近一次购买,参考历史用户单次购买附近的数据进行推测。具体如下:这个实现也很简单,我这里就不写代码了,我就不贴了,我还是在word2vec中使用predict_output_word(context_words_list,topn=10),报告给定上下文词作为训练模型输入的中心词的概率分布其实做起来还是蛮复杂的详细到这里,我这里也简单贴出一些思路,有不懂的可以私信我,就这些,最后感谢阅读。