用户画像系统
2018-01-13 00:00
218 查看
用户画像分析是当前互联网产品对用户进行数据分析常用的一个手段,比如推荐场景,常见的算法是协同过滤算法,基于用户相似度和基于物品相似度,但是这两种算法适用的场景往往比较有限。
1. 基于物品相似度的推荐算法(Item CF),适用于在线网站中,用户数量远远超过商品数量的网站,同时用户购买的商品的往往相对固定,计算量也比较小,往往用于电子商务网站。对于新闻,博客或微内容的推荐系统,情况往往是相反的,物品数量是海量的,同时也是频繁更新的。
实现原理:评估用户未看到物品和过去购买物品的相似度,相似度大的加入推荐候选列表。
2. 基于用户相似对的推荐算法(User CF),用于社交网络系统,可信度够。
实现原理:基于两个用户对同一个物品的不同偏好,找到用户的相邻用户,然后将相邻用户的喜欢的物品推荐给用户。
3. SVD推荐系统,通过SVD分解找出用户-产品矩阵中的隐藏关联因子,然后根据隐藏关联因子计算用户和物品的相关度。
用户画像即用户信息标签化,通过收集用户的社会属性,消费习惯,偏好特征等各个维度的数据,进而对用户或产品特征属性刻画。用户画像推荐系统和第3点方法有相似,区别在于需要单独为用户和物品建立特征工程,然后使用一些关联算法将两者关联起来,比如隐义模型[LFM]等,下面我见阐述一下我在工程中的落地方案。
图片 摘自《推荐系统实践》
1.收集用户日志,来源有Nginx请求日志,APP打印日志等,我们将这些日志分布式收集到ElasticSearch,HDFS,HBase中。常见的内容格式如下。
2.定时计算用户的标签。我们可以使用程序定期去获取用户最近时间段的日志,然后计算每个用户的标签权重。
用户标签权重=行为类型权重x时间衰减x内容权重x行为次数。
(1)行为类型权重:点赞,收藏,点击,浏览,购买等行为所代表的权重。
(2)时间衰减:1/(log(t)+1) ,t为时间发生时间距离当前时间的大小。
(3)内容权重:对于互联网产品而言,访问的url或者页面 决定权重,内容决定标签。商品上架时打上的标签,或者文章发布时的关键字,网页关键字内容等。
(4)行为次数:用户在同一个产品的页面发生行为的次数,这个次数和计算的标签相关。
我们可以使用Hadoop或者Spark定期的从日志库中计算一段时间得日志,更新用户的的标签权重
B(u)是用户u打过的标签集合, B(i)是物品i被打过的标签集合, N(u,b)是用户u打过标签b
的次数, N(b,i)是物品i被打过标签b的次数。
这个公式倾向于给热门标签对应的热门物品很大的权重,因此会造成推荐热门的物品给
用户,从而降低推荐结果的新颖性。另外,这个公式利用用户的标签向量对用户兴趣建模,其中
每个标签都是用户使用过的标签,而标签的权重是用户使用该标签的次数。这种建模方法的缺点
是给热门标签过大的权重,从而不能反应用户个性化的兴趣。
N(u,b)是用户u打过标签b的次数, N(b,i)是物品i被打过标签b的次数。 Nb(u) 记录了标签b被多少个不同的用户使用过。
LFM通过如下公式计算用户u对物品i的兴趣:
这个公式中pu,k , 和 qi,k , 是模型的参数
pu,k , 度量了用户u的兴趣和第k个隐类的关系.
qi,k , 度量了第k个隐类和物品i之间的关系。
根据随机梯度下降法,需要将参数沿着最速下降方向向前推进,因此可以得到如下递推
代码见文章最后
离线计算的空间复杂度 基于邻域的方法需要维护一张离线的相关表。在离线计算相关表的过程中,如果用户/物品数很多,将会占据很大的内存。假设有M个用户和N个物品,在计算相关表的过程中,我们可能会获得一张比较稠密的临时相关表(尽管最终我们对每个物品只保留K个最相关的物品,但在中间计算过程中稠密的相关表是不可避免的),那么假设是用户相关表,则需要O(M*M)的空间,而对于物品相关表,则需要O(N*N)的空间。而LFM在建模过程中,如果是F个隐类,那么它需要的存储空间是O(F*(M+N)),这在M和N很大时可以很好地节省离线计算的内存。在Netflix Prize中,因为用户数很庞大(40多万),很少有人使用UserCF算法(据说需要30 GB左右的内存),而LFM由于大量节省了训练过程中的内存(只需要4 GB),从而成为Netflix Prize中最流行的算法。
离线计算的时间复杂度 假设有M个用户、 N个物品、 K条用户对物品的行为记录。那么,UserCF计算用户相关表的时间复杂度是O(N * (K/N)^2),而ItemCF计算物品相关表的时间复杂度是O(M*(K/M)^2)。而对于LFM,如果用F个隐类,迭代S次,那么它的计算复杂度是O(K * F * S)。那么,如果K/N > F*S,则代表UserCF的时间复杂度低于LFM,如果K/M>F*S,则说明ItemCF的时间复杂度低于LFM。在一般情况下, LFM的时间复杂度要稍微高于UserCF和ItemCF,这主要是因为该算法需要多次迭代。但总体上,这两种在时间复杂度上没有质的差别。
在线实时推荐 UserCF和ItemCF在线服务算法需要将相关表缓存在内存中,然后可以在线进行实时的预测。以ItemCF算法为例,一旦用户喜欢了新的物品,就可以通过查询内
存中的相关表将和该物品相似的其他物品推荐给用户。因此,一旦用户有了新的行为,而且该行为被实时地记录到后台的数据库系统中,他的推荐列表就会发生变化。 而从LFM
的预测公式可以看到, LFM在给用户生成推荐列表时,需要计算用户对所有物品的兴趣权重,然后排名,返回权重最大的N个物品。那么,在物品数很多时,这一过程的时间复杂度非常高,可达O(M*N*F)。因此, LFM不太适合用于物品数非常庞大的系统,如果要用,我们也需要一个比较快的算法给用户先计算一个比较小的候选列表,然后再用LFM重新排名。另一方面, LFM在生成一个用户推荐列表时速度太慢,因此不能在线实时计算,而需要离线将所有用户的推荐结果事先计算好存储在数据库中。因此, LFM不能进行在线实时推荐,也就是说,当用户有了新的行为后,他的推荐列表不会发生变化。
推荐解释 ItemCF算法支持很好的推荐解释,它可以利用用户的历史行为解释推荐结果。但LFM无法提供这样的解释,它计算出的隐类虽然在语义上确实代表了一类兴趣和物品,却很难用自然语言描述并生成解释展现给用户。
附 LFM预测代码Demo
1. 基于物品相似度的推荐算法(Item CF),适用于在线网站中,用户数量远远超过商品数量的网站,同时用户购买的商品的往往相对固定,计算量也比较小,往往用于电子商务网站。对于新闻,博客或微内容的推荐系统,情况往往是相反的,物品数量是海量的,同时也是频繁更新的。
实现原理:评估用户未看到物品和过去购买物品的相似度,相似度大的加入推荐候选列表。
2. 基于用户相似对的推荐算法(User CF),用于社交网络系统,可信度够。
实现原理:基于两个用户对同一个物品的不同偏好,找到用户的相邻用户,然后将相邻用户的喜欢的物品推荐给用户。
3. SVD推荐系统,通过SVD分解找出用户-产品矩阵中的隐藏关联因子,然后根据隐藏关联因子计算用户和物品的相关度。
用户画像即用户信息标签化,通过收集用户的社会属性,消费习惯,偏好特征等各个维度的数据,进而对用户或产品特征属性刻画。用户画像推荐系统和第3点方法有相似,区别在于需要单独为用户和物品建立特征工程,然后使用一些关联算法将两者关联起来,比如隐义模型[LFM]等,下面我见阐述一下我在工程中的落地方案。
图片 摘自《推荐系统实践》
物品特征工程
建立用户画像之前,首先要对物品建立一个特征工程,对物品进行分类,打标签,关键内容提取等,通过这些方法建立一个物品的属性集合。用户画像
对于APP或者网站等用户接入产品的系统,可以非常容易的记录用户的一些操作,比如Nginx日志或者应用本身打印的日志,通过这些日志,我们可以定制化的了解用户的些行为记录,通过日志,可以计算出用户的某个标签或者特征的权重。这就是用户画像的简略过程。1.收集用户日志,来源有Nginx请求日志,APP打印日志等,我们将这些日志分布式收集到ElasticSearch,HDFS,HBase中。常见的内容格式如下。
user_id | item_id | action | datetime | ..... |
183xxxx | 1324a2133acd | view | 2017-12-03 12:30 | .... |
154xxxxx | 1324a2cd24ad | buy | 2017-12-10 18:06 | .... |
用户标签权重=行为类型权重x时间衰减x内容权重x行为次数。
(1)行为类型权重:点赞,收藏,点击,浏览,购买等行为所代表的权重。
(2)时间衰减:1/(log(t)+1) ,t为时间发生时间距离当前时间的大小。
(3)内容权重:对于互联网产品而言,访问的url或者页面 决定权重,内容决定标签。商品上架时打上的标签,或者文章发布时的关键字,网页关键字内容等。
(4)行为次数:用户在同一个产品的页面发生行为的次数,这个次数和计算的标签相关。
我们可以使用Hadoop或者Spark定期的从日志库中计算一段时间得日志,更新用户的的标签权重
基于标签的推荐
(1). 简单算法
B(u)是用户u打过的标签集合, B(i)是物品i被打过的标签集合, N(u,b)是用户u打过标签b
的次数, N(b,i)是物品i被打过标签b的次数。
这个公式倾向于给热门标签对应的热门物品很大的权重,因此会造成推荐热门的物品给
用户,从而降低推荐结果的新颖性。另外,这个公式利用用户的标签向量对用户兴趣建模,其中
每个标签都是用户使用过的标签,而标签的权重是用户使用该标签的次数。这种建模方法的缺点
是给热门标签过大的权重,从而不能反应用户个性化的兴趣。
(2). TF-IDF思想改进算法
N(u,b)是用户u打过标签b的次数, N(b,i)是物品i被打过标签b的次数。 Nb(u) 记录了标签b被多少个不同的用户使用过。
LFM隐义模型
隐义模型。通过隐义模型算法,确定用户和物品的相关性。LFM通过如下公式计算用户u对物品i的兴趣:
这个公式中pu,k , 和 qi,k , 是模型的参数
pu,k , 度量了用户u的兴趣和第k个隐类的关系.
qi,k , 度量了第k个隐类和物品i之间的关系。
根据随机梯度下降法,需要将参数沿着最速下降方向向前推进,因此可以得到如下递推
代码见文章最后
LFM和基于邻域的方法的比较
LFM是一种基于机器学习的方法,具有比较好的理论基础。这个方法和基于邻域的方法(比如UserCF、 ItemCF)相比,各有优缺点。下面将从不同的方面对比LFM和基于邻域的方法。理论基础 LFM具有比较好的理论基础,它是一种学习方法,通过优化一个设定的指标建立最优的模型。基于邻域的方法更多的是一种基于统计的方法,并没有学习过程。离线计算的空间复杂度 基于邻域的方法需要维护一张离线的相关表。在离线计算相关表的过程中,如果用户/物品数很多,将会占据很大的内存。假设有M个用户和N个物品,在计算相关表的过程中,我们可能会获得一张比较稠密的临时相关表(尽管最终我们对每个物品只保留K个最相关的物品,但在中间计算过程中稠密的相关表是不可避免的),那么假设是用户相关表,则需要O(M*M)的空间,而对于物品相关表,则需要O(N*N)的空间。而LFM在建模过程中,如果是F个隐类,那么它需要的存储空间是O(F*(M+N)),这在M和N很大时可以很好地节省离线计算的内存。在Netflix Prize中,因为用户数很庞大(40多万),很少有人使用UserCF算法(据说需要30 GB左右的内存),而LFM由于大量节省了训练过程中的内存(只需要4 GB),从而成为Netflix Prize中最流行的算法。
离线计算的时间复杂度 假设有M个用户、 N个物品、 K条用户对物品的行为记录。那么,UserCF计算用户相关表的时间复杂度是O(N * (K/N)^2),而ItemCF计算物品相关表的时间复杂度是O(M*(K/M)^2)。而对于LFM,如果用F个隐类,迭代S次,那么它的计算复杂度是O(K * F * S)。那么,如果K/N > F*S,则代表UserCF的时间复杂度低于LFM,如果K/M>F*S,则说明ItemCF的时间复杂度低于LFM。在一般情况下, LFM的时间复杂度要稍微高于UserCF和ItemCF,这主要是因为该算法需要多次迭代。但总体上,这两种在时间复杂度上没有质的差别。
在线实时推荐 UserCF和ItemCF在线服务算法需要将相关表缓存在内存中,然后可以在线进行实时的预测。以ItemCF算法为例,一旦用户喜欢了新的物品,就可以通过查询内
存中的相关表将和该物品相似的其他物品推荐给用户。因此,一旦用户有了新的行为,而且该行为被实时地记录到后台的数据库系统中,他的推荐列表就会发生变化。 而从LFM
的预测公式可以看到, LFM在给用户生成推荐列表时,需要计算用户对所有物品的兴趣权重,然后排名,返回权重最大的N个物品。那么,在物品数很多时,这一过程的时间复杂度非常高,可达O(M*N*F)。因此, LFM不太适合用于物品数非常庞大的系统,如果要用,我们也需要一个比较快的算法给用户先计算一个比较小的候选列表,然后再用LFM重新排名。另一方面, LFM在生成一个用户推荐列表时速度太慢,因此不能在线实时计算,而需要离线将所有用户的推荐结果事先计算好存储在数据库中。因此, LFM不能进行在线实时推荐,也就是说,当用户有了新的行为后,他的推荐列表不会发生变化。
推荐解释 ItemCF算法支持很好的推荐解释,它可以利用用户的历史行为解释推荐结果。但LFM无法提供这样的解释,它计算出的隐类虽然在语义上确实代表了一类兴趣和物品,却很难用自然语言描述并生成解释展现给用户。
附 LFM预测代码Demo
# coding:utf-8 import pandas as pd import numpy as np import math import operator import time import random def initpara(users, items, F): p = dict() q = dict() for userid in users: p[userid] = [(-1 + 2 * random.random()) for f in range(0, F)] # / math.sqrt(F) for itemid in items: q[itemid] = [(-1 + 2 * random.random()) for f in range(0, F)] # / math.sqrt(F) return p, q def initsamples(user_items): user_samples = [] items_pool = [] for userid, items in user_items.items(): for item in items: items_pool.append(item) for userid, items in user_items.items(): samples = dict() for itemid, score in items.items(): if score != 0: samples[itemid] = score user_samples.append((userid, samples)) return user_samples def initmodel(user_items, users, items, F): p, q = initpara(users, items, F) user_samples = initsamples(user_items) return p, q, user_samples def predict(userid, itemid, p, q): a = sum(p[userid][f] * q[itemid][f] for f in range(0, len(p[userid]))) return a def lfm(user_items, users, items, F, N, alpha, lamda): ''' LFM计算参数 p,q :param user_items: user_items :param users: users :param items: items :param F: 隐类因子个数 :param N: 迭代次数 :param alpha: 步长 :param lamda: 正则化参数 :return: p,q ''' p, q, user_samples = initmodel(user_items, users, items, F) debugid1 = 0 debugid2 = 0 for step in range(0, N): random.shuffle(user_samples) # 乱序 error = 0 count = 0 for userid, samples in user_samples: for itemid, rui in samples.items(): pui = predict(userid, itemid, p, q) eui = rui - pui count += 1 error += math.pow(eui, 2) for f in range(0, F): p_u = p[userid][f] q_i = q[itemid][f] p[userid][f] += alpha * (eui * q_i - lamda * p_u) q[itemid][f] += alpha * (eui * p_u - lamda * q_i) rmse = math.sqrt(error / count) print "rmse:", rmse alpha *= 0.9 return p, q def predictlist(userid, items, p, q): predict_score = dict() for itemid in items: p_score = predict(userid, itemid, p, q) predict_score[itemid] = p_score return predict_score def recommend(): print 'start' user_items = {1: {'a': 1, 'b': -1, 'c': -1, 'd': -1, 'e': 1, 'f': 1, 'g': -1}, 2: {'a': -1, 'b': 1, 'c': -1, 'd': 1, 'e': 1, 'f': 1, 'g': 1}, 3: {'a': 1, 'b': -1, 'c': 0, 'd': -1, 'e': -1, 'f': -1, 'g': 1}, 4: {'a': 1, 'b': -1, 'c': -1, 'd': 0, 'e': 1, 'f': 1, 'g': 1}, 5: {'a': -1, 'b': 1, 'c': 1, 'd': 1, 'e': -1, 'f': -1, 'g': 0}, 6: {'a': 1, 'b': 0, 'c': -1, 'd': -1, 'e': 1, 'f': -1, 'g': -1}} users = {1, 2, 3, 4, 5, 6} items = {'a', 'b', 'c', 'd', 'e', 'f', 'g'} F = 5 N = 30 alpha = 0.3 lamda = 0.03 p, q = lfm(user_items, users, items, F, N, alpha, lamda) for userid, itemdic in user_items.items(): print userid print "target", itemdic predict_score = predictlist(userid, itemdic, p, q) print "predicted", predict_score print 'end' if __name__ == "__main__": recommend()
相关文章推荐
- <转>推荐系统原理介绍-用户画像简介
- 用户画像系统设计调研
- 推荐系统那点事 —— 什么是用户画像?
- 一号店用户画像系统实践
- 推送系统从0到1(七):推送用户画像建立
- 2017年,你还在用用户画像和协同过滤做推荐系统吗?
- 用户画像系统应用与技术解析
- 干货:如何利用CRM系统数据做用户画像?
- 推荐系统 用户画像 标签聚类 个性化搜索
- 【推荐系统】2017年,你还在用用户画像和协同过滤做推荐系统吗?
- 推荐系统那点事 —— 什么是用户画像?
- 用户画像与推荐系统的关系
- 利用Python搭建用户画像系统
- 用户画像系统
- 系统吞吐量(TPS)、用户并发量、性能测试概念和公式
- 360强行卸载金山网盾 致大量用户系统异常
- 《pigcms v6.2最新完美至尊版无任何限制,小猪微信源码多用户微信营销服务平台系统》
- 居然还有WM_TIMECHANGE(只在用户手动改变系统时间时才会产生作用)
- 《pigcms v6.2最新完美至尊版无任何限制,小猪微信源码多用户微信营销服务平台系统》
- Oracle sys和system用户、sysdba 和sysoper系统权限、sysdba和dba角色的区别