elasticsearch算法之推荐系统的相似度算法(一)
一、推荐系统简介
推荐系统主要基于对用户历史的行为数据分析处理,寻找得到用户可能感兴趣的内容,从而实现主动向用户推荐其可能感兴趣的内容;
从物品的长尾理论来看,推荐系统通过发掘用户的行为,找到用户的个性化需求,从而将长尾商品准确地推荐给需要它的用户,帮助用户发现那些他们感兴趣但很难发现的商品。
推荐系统使用的是基于邻域的算法,一类是基于用户的协同过滤算法,另一类是基于物品的协同过滤算法;
二、数据集准备
我们采用GroupLens提供的MovieLens数据集
These files contain 1,000,209 anonymous ratings of approximately 3,900 movies
made by 6,040 MovieLens users who joined MovieLens in 2000.
使用一下code加载评分文件ml-1m/ratings.dat
def get_ratings():ratings = pd.read_csv('ml-1m/ratings.dat',sep='::',names=['UserID', 'MovieID', 'Rating', 'Timestamp'],nrows=100000)return ratings
我们可以查看前五行的数据情况
rating = get_ratings()
print(rating.head())UserID MovieID Rating Timestamp
0 1 1193 5 978300760
1 1 661 3 978302109
2 1 914 3 978301968
3 1 3408 4 978300275
4 1 2355 5 978824291
了解一下用户感兴趣的电影数量
rating = get_ratings()
plt.hist(rating['UserID'], bins=100, edgecolor='black')
plt.show()
三、基于用户的协同过滤算法
基于用户的协同过滤算法是推荐系统中最古老的算法,该算法首先需要找到跟当前用户兴趣相似的用户,然后将找到的用户感兴趣却不在当前用户兴趣列表的物品推荐给当前用户;
基于用户的协同过滤算法主要分为两步
- 找到和当前用户兴趣相似的用户集合;
该算法基于用户对物品的历史的正反馈行为计算用户兴趣相似度;我们给定用户u、v,令N(u)表示用户u曾经有过正反馈的物品集合,N(v)表示用户v曾经有过正反馈的物品集合;我们可以通过余弦相似度来计算用户u和v的相似度:
w_{uv} = \frac{N(u) \cap N(v)}{\sqrt {N(u) \cup N(v)}}
例如用户U对a、b、c有过正反馈记录,用户V对a、c有过正反馈记录;
U a b c
V a c
我们利用余弦相似度可以计算U和V的兴趣相似度
wUV=∣{a,b,c}∩{a,c}∣∣{a,b,c}∣∣{a,c}∣=26w_{UV}=\frac{|\{a,b,c\} \cap \{a,c\}|}{\sqrt {|\{a,b,c\}| |\{a,c\}|}} = \frac{2}{\sqrt{6}} wUV=∣{a,b,c}∣∣{a,c}∣∣{a,b,c}∩{a,c}∣=62
我们使用如下的user_similarity来计算用户相似性
def user_similarity(ratings):matrix = []rating_groups = ratings.groupby('UserID')for u_id, u_ratings in rating_groups:row = []matrix.append(row)u_movieIds = u_ratings['MovieID'].valuesfor v_id, v_ratings in rating_groups:v_movieIds = v_ratings['MovieID'].valuesu_v_movieIds = np.intersect1d(u_movieIds, v_movieIds)similarity = len(u_v_movieIds)/math.sqrt(len(u_movieIds) * len(v_movieIds))row.append(similarity)result = pd.DataFrame(matrix, columns= rating_groups.groups.keys(), index=rating_groups.groups.keys())return resultrating = get_ratings()
similarity_matrix = user_similarity(rating)
print(similarity_matrix.head(10))1 2 3 ... 667 668 669
1 1.000000 0.084657 0.115406 ... 0.010504 0.068680 0.076194
2 0.084657 1.000000 0.147945 ... 0.087529 0.161416 0.048839
3 0.115406 0.147945 1.000000 ... 0.085666 0.070014 0.077674
4 0.119898 0.153704 0.152783 ... 0.083438 0.036370 0.000000
5 0.097618 0.125142 0.059708 ... 0.119562 0.142134 0.059131
6 0.163017 0.114939 0.099710 ... 0.063529 0.000000 0.032915
7 0.049341 0.284641 0.150899 ... 0.164817 0.179605 0.099627
8 0.116508 0.201633 0.083139 ... 0.090808 0.113092 0.023525
9 0.200125 0.162482 0.122407 ... 0.118842 0.178069 0.053877
10 0.240081 0.215441 0.216773 ... 0.126021 0.083229 0.096951[10 rows x 669 columns]
在以上代码中直接遍历所有的用户进行计算相似性,很多时候由于物品的数量比较多或者每个用户的兴趣关注点比较少,这会导致大量用户并不存在所谓的并集;我们可以先将数据结构反转为产品用户,然后计算不同用户感兴趣的产品总数和相关用户之间感兴趣的产品交集,最后再进行余弦相似性计算;
import math
import numpy as np
import pandas as pddef change_user_ratings(rating):grouped = rating.groupby('MovieID')result = {}for movieId,m_rating in grouped:result[movieId] = m_rating['UserID'].valuesdf = pd.DataFrame({'MovieID': result.keys(),'UserIDs': result.values()})return df.set_index(df.columns.values[0])def cal_count(product_users):user_counts = {}rel_user_counts = {}for movieId, row in product_users.iterrows():userIds = row['UserIDs']for uid in userIds:if uid not in user_counts:user_counts[uid] = 0user_counts[uid] += 1for vid in userIds:if (uid, vid) not in rel_user_counts:rel_user_counts[(uid, vid)] = 0rel_user_counts[(uid, vid)] += 1user_counts = pd.DataFrame({'UserID': user_counts.keys(), 'Movie_Count': user_counts.values()})rel_user_counts = pd.DataFrame({'Rel_UserID':rel_user_counts.keys(), 'Movie_Count':rel_user_counts.values()})return user_counts.set_index(user_counts.columns.values[0]), rel_user_counts.set_index(rel_user_counts.columns.values[0])def cosin_similarity(user_counts, rel_user_counts):result = []for u, u_row in user_counts.iterrows():row = []result.append(row)u_count = u_row['Movie_Count']for v, v_row in user_counts.iterrows():v_count = v_row['Movie_Count']if rel_user_counts.index.isin([(u,v)]).any():count = rel_user_counts.at[(u,v), 'Movie_Count']row.append(count/math.sqrt(u_count * v_count))else:row.append(0)return pd.DataFrame(result, index=user_counts.index.values, columns=user_counts.index.values)def user_similarity(ratings):rating_users = change_user_ratings(ratings)user_counts, rel_user_counts = cal_count(rating_users)s = cosin_similarity(user_counts, rel_user_counts)return sratings = get_ratings()
similarity_matrix = user_similarity(ratings)
print(similarity_matrix.head(10))1 2 3 ... 667 668 669
1 1.000000 0.084657 0.115406 ... 0.010504 0.068680 0.076194
2 0.084657 1.000000 0.147945 ... 0.087529 0.161416 0.048839
3 0.115406 0.147945 1.000000 ... 0.085666 0.070014 0.077674
4 0.119898 0.153704 0.152783 ... 0.083438 0.036370 0.000000
5 0.097618 0.125142 0.059708 ... 0.119562 0.142134 0.059131
6 0.163017 0.114939 0.099710 ... 0.063529 0.000000 0.032915
7 0.049341 0.284641 0.150899 ... 0.164817 0.179605 0.099627
8 0.116508 0.201633 0.083139 ... 0.090808 0.113092 0.023525
9 0.200125 0.162482 0.122407 ... 0.118842 0.178069 0.053877
10 0.240081 0.215441 0.216773 ... 0.126021 0.083229 0.096951[10 rows x 669 columns]
- 找到这个用户集合感兴趣的且当前用户没有听说过的物品推推荐给他;
通过以上计算我们得到了用户相似性的矩阵,接下来我们需要找到跟目标用户兴趣最相似的K个用户,然后将只有这K个用户喜欢的物品推荐给目标用户;这里我们需要进一步度量目标用户对特定产品的感兴趣程度
在这个公式中,S(u,K)包含和用户u兴趣最接近的K个用户,N(i)是对物品i有过行为的用户集合,Wuv 是用户u和用户v的兴趣相似度,rvi 代表用户v对物品i的兴趣,因为使用的是单一行为的隐反馈数据,所以所有的rvi=1。
p(u,i)=∑v∈s(u,K)∩N(i)wuvrvip(u,i) = \sum_{v \in s(u,K) \cap N(i)} w_{uv} r_{vi} p(u,i)=v∈s(u,K)∩N(i)∑wuvrvi
我们使用以下的recommend方法实现这个推荐
def recommend(ratings,u, matrix, k):result = pd.Series(dtype='float64');grouped = dict(list(ratings.groupby('UserID')))u_ratings = grouped[u][['MovieID','Rating']]row = matrix.loc[u].sort_values(ascending=False)for v in row.index:if u != v:similarity = row.loc[v]v_ratings = grouped[v][['MovieID','Rating']]diff = pd.concat([v_ratings, u_ratings, u_ratings]).drop_duplicates(subset=pd.Index(['MovieID']), keep=False)for movieId, s_rating in diff.set_index('MovieID').iterrows():like = similarity * (s_rating['Rating']/5)s_movieId = str(movieId)if movieId in result:result[s_movieId] += likeelse:result[s_movieId] = likereturn result.sort_values(ascending=False).head(k)
我们计算推荐给用户A且其最感兴趣的前三件商品;从计算结果可以看到是商品c和e;
ratings = get_ratings()
similarity_matrix = user_similarity(ratings)
recommend_movies = recommend(ratings, 1, similarity_matrix, 10)
print(recommend_movies.head(10))2049 0.240081
3292 0.212965
1067 0.204131
2559 0.193922
3620 0.168068
963 0.168068
2179 0.165928
2211 0.165928
1817 0.165928
2227 0.165928
dtype: float64
注:由于rating.data的数据实际情况,每个用户以及每个电影都会有对应的评分,所以第二种算法并不具有什么性能优势,需要根据自己数据的实际情况进行选择;
elasticsearch算法之推荐系统的相似度算法(一)相关推荐
- 【推荐系统->相似度算法】余弦相似度
转自相似度算法之余弦相似度 余弦距离,也称为余弦相似度,是用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小的度量. 余弦值越接近1,就表明夹角越接近0度,也就是两个向量越相似,这就叫&qu ...
- pbewithmd5anddes算法 对应.net_文本相似度算法之-simhash
文本相似度算法种类繁多,今天先介绍一种常见的网页去重算法Simhash. 1.什么是simhash simhash是google于2007年发布的一篇论文<Detecting Near-dupl ...
- Atitit 算法之道 attilax著 1. 编码算法 3 1.1. Base64 htmlencode urlencode 3 2. Ui方面的算法 3 2.1. 软键盘算法 计算软键盘上下
Atitit 算法之道 attilax著 1. 编码算法 3 1.1. Base64 htmlencode urlencode 3 2. Ui方面的算法 3 2.1. 软键盘算法 计算软键盘上下左 ...
- 基于协同过滤推荐+余弦相似度算法实现新闻推荐系统
针对海量的新闻资讯数据,如何快速的根据用户的检索需要,完成符合用户阅读需求的新闻资讯推荐?本篇文章主要采用余弦相似度及基于用户协同过滤算法实现新闻推荐,通过余弦相似度算法完成针对不同新闻数据之间的相似 ...
- 基于大数据分析架构设计采用基于协同过滤推荐+余弦相似度算法+springboot+vue.js 实现新闻推荐系统
针对海量的新闻资讯数据,如何快速的根据用户的检索需要,完成符合用户阅读需求的新闻资讯推荐?本篇文章主要采用余弦相似度及基于用户协同过滤算法实现新闻推荐,通过余弦相似度算法完成针对不同新闻数据之间的相似 ...
- 数据算法:推荐系统的实践与思考(下)【转】
原文地址:http://www.woshipm.com/data-analysis/2193844.html 推荐系统之在线服务 在解决了算法和数据层面的问题之后,我们需要构建一个推荐系统的在线服务, ...
- spark MLlib平台的协同过滤算法---电影推荐系统
又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实 ...
- [机器学习] 推荐系统之协同过滤算法(转)
[机器学习]推荐系统之协同过滤算法 在现今的推荐技术和算法中,最被大家广泛认可和采用的就是基于协同过滤的推荐方法.本文将带你深入了解协同过滤的秘密.下面直接进入正题. 1. 什么是推荐算法 推荐算法最 ...
- 推荐系统常用的推荐算法
转载自 推荐系统常用的推荐算法 一.推荐系统概述和常用评价指标 1.1 推荐系统的特点 在知乎搜了一下推荐系统,果真结果比较少,显得小众一些,然后大家对推荐系统普遍的观点是: (1)重要性UI> ...
最新文章
- HDU4738(割点)
- 比较两个字符串是否相等
- oss2模块和aliyun oss连接
- Ueditor百度编辑器中的 setContent()方法的使用
- leetcode初级算法6.字符串转整数(atoi)
- python倒排索引搜索引擎_【Python】倒排索引
- github java开源项目经验_Java 开源项目 GitHub 趋势周报 20201230
- oracle 分区表进行shrink操作
- ffmpeg java 使用教程_Java使用ffmpeg
- 网络计算机怎么使用,如何让电脑使用ipv6地址?一文了解清楚
- EM78P153单片机构成433MHz发射电路
- c语言生日蛋糕图片,poj1190生日蛋糕
- directshow视频旋转90度
- 不要过于积极表现自己
- 中文命名实体识别(ner)迁移学习
- 计算机本科核心课程教学视频,绝对经典(28门核心视频课程)
- 用python写学籍管理系统_使用Python实现 学生学籍管理系统
- ADB 命令结合 monkey 的简单使用,超详细
- 新华三的“加班事件”说明码农的时代已经过去?
- 微信小程序开发:一个音乐播放器