原创-机器学习之推荐系统实战

如何实现一个电影推荐系统

原创内容ios

转载注明出处:http://www.vmfor.comgit

 

GavinHackergithub

推荐算法在互联网行业的应用很是普遍,今日头条、美团点评等都有个性化推荐,推荐算法抽象来说,是一种对于内容满意度的拟合函数,涉及到用户特征和内容特征,做为模型训练所需维度的两大来源,而点击率,页面停留时间,评论或下单等均可以做为一个量化的 Y 值,这样就能够进行特征工程,构建出一个数据集,而后选择一个合适的监督学习算法进行训练,获得模型后,为客户推荐偏好的内容,如头条的话,就是咨询和文章,美团的就是生活服务内容。算法

可选择的模型不少,如协同过滤,逻辑斯蒂回归,基于DNN的模型,FM等。咱们使用的方式是,基于内容类似度计算进行召回,以后经过FM模型和逻辑斯蒂回归模型进行精排推荐,下面就分别说一下,咱们作这个电影推荐系统过程当中,从数据准备,特征工程,到模型训练和应用的整个过程。sql

咱们实现的这个电影推荐系统,爬取的数据实际上维度是相对少的,特别是用户这一侧的维度,正常推荐系统涉及的维度,诸如页面停留时间,点击频次,收藏等这些维度都是没有的,以及用户自己的维度也相对要少,没有地址、年龄、性别等这些基本的维度,这样咱们爬取的数据只有打分和评论这些信息,因此以后咱们又从这些信息里再拿出一些统计维度来用。咱们爬取的电影数据(除电影详情和图片信息外)是以下这样的形式:app

image

这里的数据是有冗余的,又经过以下的代码,对数据进行按维度合并,去除冗余数据条目:机器学习

 1 # 处理主函数,负责将多个冗余数据合并为一条电影数据,将地区,导演,主演,类型,特点等维度数据合并
 2 
 3 def mainfunc():
 4     try:
 5         unable_list = []
 6         with connection.cursor() as cursor:
 7             sql='select id,name from movie'
 8             cout=cursor.execute(sql)
 9             print("数量: "+str(cout))
10 
11             for row in cursor.fetchall():
12                 #print(row[1])
13                 movieinfo = df[df['电影名'] == row[1]]
14                 if movieinfo.shape[0] == 0:
15                     disable_movie(row[0])
16                     print('disable movie ' + str(row[1]))
17                 else:
18                     g = lambda x:movieinfo[x].iloc[0]
19                     types = movieinfo['类型'].tolist()
20                     types = reduce(lambda x,y:x+'|'+y,list(set(types)))
21                     traits = movieinfo['特点'].tolist()
22                     traits = reduce(lambda x,y:x+'|'+y,list(set(traits)))
23                     update_one_movie_info(type_=types, actors=g('主演'), region=g('地区'), director=g('导演'), trait=traits, rat=g('评分'), id_=row[0])
24 
25         connection.commit()
26     finally:
27         connection.close()

 

以后开始准备用户数据,咱们从用户打分的数据中,统计出每个用户的打分的最大值,最小值,中位数值和平均值等,从而做为用户的一个附加属性,存储于userproex表中:函数

1 'insert into userproex(userid, rmax, rmin, ravg, rcount, rsum, rmedian) values(\'%s\', %s, %s, %s, %s, %s, %s)' % (userid, rmax, rmin, ravg, rcount, rsum, rmedium)
2 
3 
4 'update userproex set rmax=%s, rmin=%s, ravg=%s, rmedian=%s, rcount=%s, rsum=%s where userid=\'%s\'' % (rmax, rmin, ravg, rmedium, rcount, rsum, userid)

 

以上两个SQL是最终插入表的时候用到的,表明准备用户数据的最终步骤,其他细节能够参考文末的github仓库,不在此赘述,数据处理还用到了一些SQL,以及其余处理细节。学习

系统上线运行时,第一次是全量的数据处理,以后会是增量处理过程,这个后面还会提到。fetch

咱们目前把用户数据和电影的数据的原始数据算是准备好了,下一步开始特征工程。作特征工程的思路是,对type, actors, director, trait四个类型数据分别构建一个频度统计字典,用于以后的one-hot编码,代码以下:

 1 def get_dim_dict(df, dim_name):
 2   type_list = list(map(lambda x:x.split('|') ,df[dim_name]))
 3   type_list = [x for l in type_list for x in l]
 4   def reduce_func(x, y):
 5     for i in x:
 6       if i[0] == y[0][0]:
 7         x.remove(i)
 8         x.append(((i[0],i[1] + 1)))
 9         return x
10     x.append(y[0])
11     return x
12   l = filter(lambda x:x != None, map(lambda x:[(x, 1)], type_list))
13   type_zip = reduce(reduce_func, list(l))
14   type_dict = {}
15   for i in type_zip:
16     type_dict[i[0]] = i[1]
17   return type_dict

 

涉及到的冗余数据也要删除

df_ = df.drop(['ADD_TIME', 'enable', 'rat', 'id', 'name'], axis=1)

 

将电影数据转换为字典列表,因为演员和导演均过万维,实际计算时过于稀疏,当演员或导演只出现一次时,标记为冷门演员或导演
movie_dict_list = []
for i in df_.index:
  movie_dict = {}
  #type
  for s_type in df_.iloc[i]['type'].split('|'):
    movie_dict[s_type] = 1
  #actors
  for s_actor in df_.iloc[i]['actors'].split('|'):
    if actors_dict[s_actor] < 2:
      movie_dict['other_actor'] = 1
    else:
      movie_dict[s_actor] = 1
  #regios
  movie_dict[df_.iloc[i]['region']] = 1
  #director
  for s_director in df_.iloc[i]['director'].split('|'):
    if director_dict[s_director] < 2:
      movie_dict['other_director'] = 1
    else:
      movie_dict[s_director] = 1
  #trait
  for s_trait in df_.iloc[i]['trait'].split('|'):
    movie_dict[s_trait] = 1
  movie_dict_list.append(movie_dict)

 

使用DictVectorizer进行向量化,作One-hot编码

1 v = DictVectorizer()
2 X = v.fit_transform(movie_dict_list)

 

这样的数据,下面作余弦类似度已经能够了,这是特征工程的基本的一个处理,模型所使用的数据,须要将电影,评分,用户作一个数据拼接,构建训练样本,并保存CSV,注意这个CSV不用每次全量构建,而是除第一次外都是增量构建,经过mqlog中类型为'c'的消息,增量构建以comment(评分)为主的训练样本,拼接以后的形式以下:

USERID    cf2349f9c01f9a5cd4050aebd30ab74f
movieid    10533913
type    剧情|奇幻|冒险|喜剧
actors    艾米·波勒|菲利丝·史密斯|理查德·坎德|比尔·哈德尔|刘易斯·布莱克
region    美国
director    彼特·道格特|罗纳尔多·德尔·卡门
trait    感人|经典|励志
rat    8.7
rmax    5
rmin    2
ravg    3.85714
rcount    7
rmedian    4
TIME_DIS    15

 

这个数据的actors等字段和上面的处理是同样的,为了以后libfm的使用,在这里须要转换为libsvm的数据格式

dump_svmlight_file(train_X_scaling, train_y_, train_file)


有不少细节不在这里描述,这样大概的特征工程工做就作好了,以后使用类似度计算,FM,LR进行推荐模型的训练。 具体训练的过程不在这里进行阐述了,能够参考代码索引页

 

所有子项目代码地址

 

模型使用上遵循先召回,后精排的策略,先经过余弦类似度计算一个类似度矩阵,而后根据这个矩阵,为用户推荐类似的M个电影,在经过训练好的FM,LR模型,对这个M个电影作偏好预估,FM会预估一个用户打分,LR会预估一个点击几率,综合结果推送给用户做为推荐电影。

 

作了这个电影推荐系统后,感受算是对本身这么长时间学习机器学习知识作一个综合的实践,有很多的感悟,如今有不少学习机器学习的同窗,建议在你们刷论文的同时,也注重在项目中实践,计算机科学,虽然叫作科学,实际倒是一门实践性学科,一些AI顶级大牛,他们并非数学家,也不是理论家,大可能是从理论和实践结合这条路成就的,和金庸小说中的武林绝技是一个道理。说到这,你们都知道,最近朋友圈被《94射雕英雄传》AI换脸杨幂刷屏了,看来AI视频换脸技术发展已经至关快,仔细想一想,这已是AI进入艺术创做领域的一个表象,笔者认为AI以后的发展必定是从互联网行业扩展出去,变成IT产业当中的一个重要的技术支柱。

 

相关文章
相关标签/搜索