你是否有过这样的经历?当你在亚马逊商城浏览一些书籍,或者购买过一些书籍后,你的偏好就会被系统学到,系统会基于一些假设为你推荐相关书目。为什么系统会知道,在这背后又藏着哪些秘密呢?

          

 

  荐系统可以从百万甚至上亿的内容或商品中把有用的东西高效地显示给用户,这样可以为用户节省很多自行查询的时间,也可以提示用户可能忽略的内容或商品,使用户更有黏性,更愿意花时间待在网站上,从而使商家赚取更多的利润,即使流量本身也会使商家从广告中受益。

  

  那么推荐系统背后的魔术是什么呢?其实任何推荐系统本质上都是在做排序。

  你可能注意到了,排序的前提是对喜好的预测。那么喜好的数据从哪里来呢?这里有几个渠道,比如你和产品有过互动,看过亚马逊商城的一些书,或者买过一些书,那么你的偏好就会被系统学到,系统会基于一些假设给你建立画像和构建模型。你和产品的互动越多,数据点就越多,画像就越全面。除此之外,如果你有跨平台的行为,那么各个平台的数据汇总,也可以综合学到你的偏好。比如谷歌搜索、地图和应用商城等都有你和谷歌产品的互动信息,这些平台的数据可以通用,应用的场景有很大的想象力。平台还可以利用第三方数据,比如订阅一些手机运营商的数据,用来多维度刻画用户

那推荐系统又是如何建立模型、知道用户爱好的?作者提供了两种重要的算法:矩阵分解模型和深度模型,快来一起探个究竟吧!

1.矩阵分解模型

  矩阵分解可以认为是一种信息压缩。这里有两种理解。第一种理解,用户和内容不是孤立的,用户喜好有相似性,内容也有相似性。压缩是把用户和内容数量化,压缩成 k 维的向量。把用户向量维度进行压缩,使得向量维度变小,本身就是信息压缩的一种形式;向量之间还可以进行各种计算,比如余弦(Cosine)相似性,就可以数量化向量之间的距离、相似度等。第二种理解,从深度学习的角度,用户表示输入层(User Representation)通常用 One Hot编码,这没问题,但是通过第一层全连接神经网络就可以到达隐藏层,就是所谓的嵌入层(Embedding Layer),也就是我们之前提到的向量压缩过程。紧接着这个隐藏层,再通过一层全连接网络就是最终输入层,通常用来和实际标注数据进行比较,寻找差距,用来更新网络权重。从这个意义上讲,完全可以把整个数据放进神经系统的框架中,通过浅层学习把权重求出来,就是我们要的向量集合了。经过这么分析,矩阵分解在推荐系统中是如何应用的就显而易见了。

  

  这两种情形都可以用矩阵分解来解决。假设数据库里m 个用户和 n 部电影,那么用户电影矩阵的大小就是 m×n。每个单元 (i,j) 用R ij 表示用户是否看了该电影,即0 或 1。我们把用户和电影用类似 Word2Vec 的方法分别进行向量表示,把每个用户 i 表示成 d 维向量 X i ,把每部电影 j 表示成 d 维向量 Y j 。我们要寻找 X i 和 Y j ,使得 X i ×Y j和用户电影矩阵 R ij 尽可能接近,如图所示。这样对于没出现过的用户电影对,通过 X i ×Y j 的表达式可以预测任意用户对电影的评分值。

  

            

           

  用数学表达式可以这么写:

           

  注意:这里d 是一个远小于m; n 的数。从机器学习的角度来说,模型是为了抓住数据的主要特征,去掉噪声。越复杂、越灵活的模型带来的噪声越多,降低维度则可以有效地避免过度拟合现象的出现。

2.深度神经网络模型

  下面展示进阶版的深度模型。我们将建立多层深度学习模型,并且加入 Dropout技术。

  

  这个模型非常灵活。因为如果有除用户、电影之外的数据,比如用户年龄、地区、电影属性、演员等外在变量,则统统可以加入模型中,用嵌入的思想把它们串在一起,作为输入层,然后在上面搭建各种神经网络模型,最后一层可以用评分等作为输出层,这样的模型可以适用于很多场景。深度模型的的架构如下图所示。

  

             

           

  首先,做用户和电影的嵌入层。

1 k = 128
2 model1 = Sequential()
3 model1.add(Embedding(n_users + 1, k, input_length = 1))
4 model1.add(Reshape((k,)))
5 model2 = Sequential()
6 model2.add(Embedding(n_movies + 1, k, input_length = 1))
7 model2.add(Reshape((k,)))

  第三个小神经网络,在第一、二个网络的基础上把用户和电影向量结合在一起。

1 model = Sequential()
2 model.add(Merge([model1, model2], mode = 'concat'))

  然后加入Dropout 和relu 这个非线性变换项,构造多层深度模型。

1 model.add(Dropout(0.2))
2 model.add(Dense(k, activation = 'relu'))
3 model.add(Dropout(0.5))
4 model.add(Dense(int(k/4), activation = 'relu'))
5 model.add(Dropout(0.5))
6 model.add(Dense(int(k/16), activation = 'relu'))
7 model.add(Dropout(0.5))

  因为是预测连续变量评分,最后一层直接上线性变化。当然,读者可以尝试分类问

题,用Softmax 去模拟每个评分类别的概率。

model.add(Dense(1, activation = 'linear'))

  将输出层和最后的评分数进行对比,后向传播去更新网络参数。

model.compile(loss = 'mse', optimizer = "adam")

  接下来要给模型输入训练数据。

  首先,收集用户索引数据和电影索引数据。

1 users = ratings['user_id'].values
2 movies = ratings['movie_id'].values

5 推荐系统

  收集评分数据。

label = ratings['rating'].values

  构造训练数据。

1 X_train = [users, movies]
2 y_train = label

  然后,用小批量更新权重。

model.fit(X_train, y_train, batch_size = 100, epochs = 50)

  模型训练完以后,预测未给的评分。

1 i,j = 10,99
2 pred = model.predict([np.array([users[i]]), np.array([movies[j]])])

  最后,对训练集进行误差评估。

1 sum = 0
2 for i in range(ratings.shape[0]):
3 sum += (ratings['rating'][i] - model.predict([np.array([ratings['user_id'
][i]]), np.array([ratings['movie_id'][i]])])) ** 2
4 mse = math.sqrt(sum/ratings.shape[0])
5 print(mse)

  训练数据的误差在0.8226 左右,大概一个评分等级不到的误差。

  你可能会问,为什么这个误差和之前矩阵分解的浅层模型误差的差距比较大?作者的理解是,这里的Dropout 正则项起了很大的作用。虽然我们建了深层网络,但是由于有了Dropout 这个正则项,必然会造成训练数据的信息丢失(这种丢失会让我们在测试数据时受益)。就好比加了L1, L2 之类的正则项以后,估计的参数就不是无偏的了。因此,Dropout 是训练误差增加的原因,这是设计模型的必然结果。但是,需要记住的是,我们始终要对测试集上的预测做评估,训练集的误差只是看优化方向和算法是否大致有效。

  

  本文选自《Keras快速上手:基于Python的深度学习实战》,点此链接可在博文视点官网查看此书。

  

                    

  想及时获得更多精彩文章,可在微信中搜索“博文视点”或者扫描下方二维码并关注。

                        

揭秘Keras推荐系统如何建立模型、获取用户爱好的更多相关文章

  1. Keras之函数式(Functional)模型

    函数式(Functional)模型 我们起初将Functional一词译作泛型,想要表达该类模型能够表达任意张量映射的含义,但表达的不是很精确,在Keras2里我们将这个词改移为“函数式”,函数式模型 ...

  2. 【NetDevops】网络自动化运维--1获取用户基本信息

     版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.  之前博客的云主机到期了没续费,被删啦最重要的是没有备份!此处省略几个字.....      ...

  3. SharePoint 2013 开发——获取用户配置文件属性内容(User Profile)

    博客地址:http://blog.csdn.net/FoxDave 本篇我们应用SharePoint CSOM(.NET)来读取用户配置文件的信息,个人开始逐渐倾向于客户端模型,因为不用远程登录到 ...

  4. 微信网页授权获取用户基本信息--PHP

    现在就说说怎么通过网页授权获取用户基本信息(国家,省,市,昵称)等. 必要条件: 1)公众号认证 2)有网页授权获取用户基本信息的权限接口 注意:最近有朋友说:在公众平台申请的测试号,会出现无法取到用 ...

  5. [iOS微博项目 - 3.4] - 获取用户信息

    github: https://github.com/hellovoidworld/HVWWeibo   A.获取用户信息 1.需求 获取用户信息并储存 把用户昵称显示在“首页”界面导航栏的标题上   ...

  6. php微信网页授权获取用户信息

    配置回调域名: 1. 引导用户进入授权页面同意授权,获取code 2. 通过code换取网页授权access_token(与基础支持中的access_token不同) 3. 如果需要,开发者可以刷新网 ...

  7. 微信小程序登录流程及解析用户openid session_key,获取用户信息

    为优化用户体验,使用 wx.getUserInfo 接口直接弹出授权框的开发方式将逐步不再支持.从2018年4月30日开始,小程序与小游戏的体验版.开发版调用 wx.getUserInfo 接口,将无 ...

  8. 小程序wx.getUserInfo获取用户信息方案介绍

    问题模块 框架类型 问题类型 API/组件名称 终端类型 操作系统 微信版本 基础库版本 API和组件 - -   - -     背景 小程序一个比较重要的能力就是获取用户信息,也就是使用 wx.g ...

  9. 微信小程序获取用户手机号详解

    最近在做一款微信小程序,需要获取用户手机号,具体步骤如下: 流程图: 1.首先,客户端调用wx.login,回调数据了包含jscode,用于获取openid(用户唯一标识)和sessionkey(会话 ...

随机推荐

  1. UVa 10723 电子人的基因(LCS)

    https://vjudge.net/problem/UVA-10723 题意: 输入两个A~Z组成的字符串,找一个最短的串,使得输入的两个串均是它的子序列,另外还需要统计长度最短的串的个数. 思路: ...

  2. UVa 1606 两亲性分子

    https://vjudge.net/problem/UVA-1606 题意:平面上有n个点,每个点为白点或者黑点.现在需放置一条隔板,使得隔板一侧的白点数加上另一侧的黑点数总数最大.隔板上的点可以看 ...

  3. vue v-model 表单控件绑定

    v-model 指令在表单控件元素上创建双向数据绑定,下面一一进行示例解释. 1.v-model 双向绑定文本 <!DOCTYPE html> <html> <head ...

  4. Linux基础※※※※Linux中的图形相关工具

    kolourPaint类似于Win中个mspaint: Ubuntu安装:sudo apt-get install kolourpaint4 图1 kolourPaint界面 其他类似的画图工具见链接 ...

  5. ubuntu 14.04 安装 gflags

    1.下载 git clone https://github.com/gflags/gflags 2.编译 进入源码目录(即gflags文件夹) cmake . make -j 24 sudo make ...

  6. 适用于目前环境的bug记录

    问测试,bugtracker.JIRA,你们用起来啊? 难道bugtracker/JIRA只有测试用吗? 截屏忽略,只有测试人员自己提bug,开发不管不顾,解决了也不关闭bug,bug提得太多,还嫌测 ...

  7. C#一套简单的单例系统

    单例基类 public class CSingletonBase<TYPE> { public static TYPE Singleton { get { return m_singlet ...

  8. springboot入门(一)--快速搭建一个springboot框架

    原文出处 前言在开始之前先简单介绍一下springboot,springboot作为一个微框架,它本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速.敏捷地开发新一代基于Spring框架 ...

  9. Confluence 6 从外部目录中同步数据如何工作

    下面是有关缓存功能的一些摘要信息: 用户和用户组的缓存信息保存在应用程序的数据库中. 当你连接一个新的外部目录到系统中的时候,一个同步任务将会启动被,并且在后台运行拷贝所有需要的用户和用户组信息,以及 ...

  10. layui图片显示

    有些东西看文档可以实现,但当真不如自己写的实在.所以还是记录下来吧. 1. 图片赋值 <div id="layer-photos-demo" class="laye ...