个性化推荐系统
(推荐系统)
推荐系统概述
2020-08
推荐系统
推荐系统概述
一.推荐系统的背景与价值
1.推荐系统的应用场景:网易音乐、电商推荐、新闻推荐
个性化推荐:在面向用户的互联网产品中发挥着极其重要的作用。
2.推荐系统的价值
在面向用户的互联网产品中,代替用户评估其从未看过、接触过和使用过的物品,包括电影、新闻、音乐、餐馆、旅游景点等。推荐系统作为一种信息过滤的重要手段,是解决“信息过载”问题的最有效的方法之一。
(1)对于用户来说:帮助用户准确找到感兴趣的信息;
具体表现:在有限时间内,给用户曝光他潜意识里想看的、想买的物品…
(2)对于商家来说:帮助商家带来更多的用户关注、销量;
具体表现:浏览更多、点击更多、购买更多…
3.推荐方式
(1)推荐用户感兴趣的
(2)推荐热门的商品
(3)随机的推荐,保证多样性
4.推荐系统的原理
(1)推荐系统:可以被简单的抽象成一个m*n的矩阵R,行和列分别表示:用户、物品,m,n分别表示用户和物品数量,矩阵中的每一项代表:一个用户对一个物品的评分,“空”表示用户和物品之间没有交互。
(2)目标:预测矩阵中所有未知项的评分,然后给用户推荐评分较高的未交互物品。
5.推荐引擎VS搜索引擎
(1)搜索引擎:满足了用户有明确目的的主动查找需求(主观意识的查询搜索关键词)。搜索引擎的输出更贴近用户的主管搜索(可能会有一定的“发散,如百度边栏信息”)。
(2)推荐引擎:在用户没有明确目的的时候,帮助用户发现感兴趣的新内容。推荐系统的输出会充分考虑“协同过滤”的结果,关联的结果在“深度”、“广度”上更进一步。
(3)相似之处:
①模型上:都存在猜测用户潜在心理、行为的味道
②形式上:都存在要输出一份“排序列表”的问题
二.推荐系统的历史与分类
1.推荐系统的发展历史
2.推荐系统分类发展
(1)基于内容的推荐
①基于物品的属性、用户的画像、一般需要人工打标签
②方法朴素、渐淡,工业界用的比较多
③可以作为解决冷启动的候选方法
# 评分预测:基于显式的信息进行推荐
# 非评分的:隐反馈(浏览,点击,收藏。。。)
(2)基于协同过滤的推荐
①基于用户的协同过滤推荐 (User-Based CF):本质就是计算用户之间的相似度,然后获取与目标用户相似度较高的用户,并将其交互物品中评分较高的推荐给目标用户。
②基于物品的协同过滤推荐 (Item-Base CF): 本质就是计算物品之间的相似度,然后获取与目标用户交互物品相似度较高的物品,并将其推荐给目标用户。
(3)基于隐语义模型的推荐
①矩阵分解:核心思想是认为用户的兴趣只受少数几个因素的影响,因此将稀疏且高维的User-Item评分矩阵分解为两个低维矩阵,即通过User,Item评分信息来学习用户特征矩阵P,物品特征矩阵Q,通过重构的低维矩阵来预测用户对物品的评分。
②宏观理解:一个向量表示:物品包含几个方面特征的程度;另一个向量表示:用户对特征的喜欢程度。两个向量的内积体现:用户对物品的喜欢程度。
三.个性化推荐的典型算法思想
1.算法1——基于内容的推荐
①基于物品的属性、用户的画像、一般需要人工打标签
②方法朴素、渐淡,工业界用的比较多
③可以作为解决冷启动的候选方法
2.算法2——基于协同过滤的推荐
(1)基于用户的协同过滤推荐 (User-Based CF):本质就是计算用户之间的相似度,然后获取与目标用户相似度较高的用户,并将其交互物品中评分较高的推荐给目标用户。
(2)基于用户协同过滤推荐思想
相似度矩阵(向量的余弦相似度)
# —*- coding: utf-8 -*-
# @time : 2020/8/21 23:07
# @Author : FZY
# 计算余弦相似度
import numpy as np
import pandas as pd
from pandas import DataFrame
n = [
[4, 3, 0, 0, 5, 0],
[5, 0, 4, 0, 4, 0],
[4, 0, 5, 3, 4, 0],
[0, 3, 0, 0, 0, 5],
[0, 4, 0, 0, 0, 4],
[0, 0, 2, 4, 0, 5],
]
n1 = []
count = 0
for i in range(6):
for j in range(6):
x1 = np.around(np.dot(n[i:i + 1][0], n[j:j + 1][0]), decimals=2)
x2 = np.around((np.linalg.norm(n[i:i + 1][0]) * np.linalg.norm(n[j:j + 1][0])), decimals=2)
n1.append(np.around((x1 / x2), decimals=2))
count += 1
# if count % 6 == 0:
# n1.append('\n')
# n1.append(((np.dot(n[i:i+1][0], n[j:j+1][0])/(np.linalg.norm(n[i:i+1][0])*np.linalg.norm(n[j:j+1][0])))))
print(np.array(n1).reshape(6, 6))
# n1.reshape(6,6)
生成相似度矩阵:
(3)基于用户的额协同过滤计算过程
推荐产生的结果一定是目标用户未交互过的物品。
3.基于物品的协同过滤的推荐
(1)基于物品的协同过滤推荐 (Item-Base CF): 本质就是计算物品之间的相似度,然后获取与目标用户交互物品相似度较高的物品,并将其推荐给目标用户。
(2)基于物品的协同过滤推荐思想
(3)基于物品的协同过滤计算过程
3.算法3——基于矩阵分解的推荐
宏观理解:一个向量表示:物品包含某几个方面特征的程度;另一个向量表示:用户对特征的喜欢程度。两个向量的内积体现:用户对物品的喜欢程度。
四.推荐系统面临的挑战与发展趋势
1.发展挑战
(1)冷启动问题:用户冷启动,物品冷启动
(2)数据稀疏条件下的推荐精度问题
(3)推荐的多样性、新颖性问题
(4)非结构化、多中模态,高质量的数据问题
(5)实时计算、大数据存储
(6)推荐系统中的用户隐私问题
2.发展趋势
(1)移动环境下推荐系统成为主流
(2)近乎实时的个性化推荐服务
(3)可解释的推荐系统
(4)完整的推荐系统引擎+推荐系统作为云服务方式提供
五.推荐系统Surprise
# —*- coding: utf-8 -*-
# @time : 2020/8/22 9:06
# @Author : FZY
import pandas as pd
# from surprise
import Reader
from IPython import get_ipython
import surprise
# from surprise
import Dataset
# from surprise.model_selection import cross_validate
# from surprise import NormalPredictor
#
import os
import zipfile
# os.chdir(r'F:\推荐系统\项目\03推荐系统相似度计算\home\aistudio\data\data17529')
# extracting = zipfile.ZipFile('BX-CSV-Dump.zip')
# extracting.extractall()
# get_ipython().system('ls F:\推荐系统\项目\03推荐系统相似度计算\home\aistudio\data')
user = pd.read_csv(r'F:\推荐系统\项目\03推荐系统相似度计算\home\aistudio\data\data17529\BX-Users.csv'
, sep=';', error_bad_lines=False, encoding="Latin-1")
user.columns = ['userID', 'Location', 'Age']
rating = pd.read_csv(r'F:\推荐系统\项目\03推荐系统相似度计算\home\aistudio\data\data17529\BX-Book-Ratings.csv',
sep=';', error_bad_lines=False, encoding="Latin-1")
rating.columns = ['userID', 'ISBN', 'bookRating']
print(len(user))
print(user.tail())
df = pd.merge(user, rating, on='userID', how='inner')
df.drop(['Location', 'Age'], axis=1, inplace=True)
print(len(df))
print(df.head())
输出:
from plotly.offline import init_notebook_mode, plot, iplot
#
get_ipython().run_line_magic('matplotlib', 'notebook')
import plotly.graph_objs as go
init_notebook_mode(connected=True)
data = df['bookRating'].value_counts().sort_index(ascending=False)
trace = go.Bar(x=data.index,
text=['{:.1f} %'.format(val) for
val in (data.values / df.shape[0] * 100)],
textposition='auto',
textfont=dict(color='#000000'),
y=data.values, )
layout = dict(title='Distribution Of {} book-ratings'.format(df.shape[0]),
xaxis=dict(title='Rating'),
yaxis=dict(title='Count'))
fig = go.Figure(data=[trace], layout=layout)
# 这里使用iplot(fig)就不会输出网页信息
# 网络查找答案为:py.plot会生成一个离线的html文件,里面放置图片。而py.iplot则直接在ipython notebook里面生成图片。
plot(fig)
结果:直方图中,x轴表示书籍被评分次数,Y轴表示书籍的数量,
df.groupby('ISBN')['bookRating'].count().reset_index().sort_values('bookRating', ascending=False)[:10]
# Number of ratings
per user
data =
df.groupby('userID')['bookRating'].count().clip(upper=50)
# Create trace
trace =
go.Histogram(x=data.values,
name='Ratings',
xbins=dict(start=0,
end=50,
size=2))
layout = go.Layout(title='Distribution Of Number of Ratings for
Users (Clipped at 50)',
xaxis=dict(title='Number of Rating for Users'),
yaxis=dict(title='Count'),
bargap=0.2)
fig = go.Figure(data=[trace], layout=layout)
plot(fig)
结果:直方图中,x轴表示所有用户的评分的次数,Y轴表示用户的数量
# 由上面两个直方图呈现的分布特性,为减少计算复杂度,避免在计算时出席那内存泄漏问题,需降低数据维度,将评分次数很低(小于50次)的书籍和用户过滤掉。
min_book_ratings
= 50
filter_books =
df['ISBN'].value_counts() > min_book_ratings
filter_books = filter_books[filter_books].index.tolist()
min_user_ratings = 50
filter_users =
df['userID'].value_counts() > min_user_ratings
filter_users = filter_users[filter_users].index.tolist()
df_new = df[(df['ISBN'].isin(filter_books)) & (df['userID'].isin(filter_users))]
print('The original data frame shape:\t{}'.format(df.shape))
print('The new data frame shape:\t{}'.format(df_new.shape))
结果:数据量由114万减少到14万
# 我们将使用load_from_df()方法从上面的 pandas dataframe 加载数据,我们还需要一个Reader对象,并且必须指定rating_scale参数。
# 数据必须有包含3列,对应于userID,ISBN和bookRating,必须严格按照这样的顺序排列。
reader = Reader(rating_scale=(0, 9))
data = Dataset.load_from_df(df_new[['userID','ISBN','bookRating']], reader)
benchmark = []
# 尝试所有算法
for algorithm in [SVD(), SVDpp(), SlopeOne(), NormalPredictor(), KNNBaseline(), KNNBasic(), KNNWithMeans(), KNNWithZScore(), BaselineOnly(), CoClustering()]:
#在交叉集上的表现
results = cross_validate(algorithm, data, measures=['RMSE'], cv=3, verbose=False)
# 记录结果
tmp = pd.DataFrame.from_dict(results).mean(axis=0)
tmp = tmp.append(pd.Series([str(algorithm).split(' ')[0].split('.')[-1]], index=['Algorithm']))
benchmark.append(tmp)
surprise_results = pd.DataFrame(benchmark).set_index('Algorithm').sort_values('test_rmse')
print(surprise_results)
结果:
# 训练和预测
# BaselineOnly算法给了我们最好的rmse,因此,我们将使用BaselineOnly训练和预测,并使用交替最小二乘法(ALS)寻找最优值。
print('Using ASL')
bsl_options = {'method': 'als',
'n_epochs': 5,
'reg_u': 12,
'reg_i': 5
}
algo = BaselineOnly(bsl_options)
cross_validate(algo, data, measures=['RMSE'], cv=3, verbose=False)
# 我们使用train_test_split()方法创建训练集和测试集,并使用rmse作为评估指标。
# 然后我们将使用fit()方法在训练集上进行训练,最后使用test()方法将返回测试集上做出的预测结果。
trainset, testset = train_test_split(data, test_size=0.25)
algo = BaselineOnly(bsl_options=bsl_options)
predictions = algo.fit(trainset).test(testset)
accuracy.rmse(predictions)
结果:
# 为了详细检查我们的预测,我们将构建一个包含所有预测的pandas的数据集。
def get_Iu(uid):
""" return the number of
items rated by given user
args:
uid: the id of the user
returns:
the number of items rated by
the user
"""
try:
return len(trainset.ur[trainset.to_inner_uid(uid)])
except ValueError: # user was not part of the trainset
return 0
def get_Ui(iid):
""" return number of users
that have rated given item
args:
iid: the raw id of the item
returns:
the number of users that have rated
the item.
"""
try:
return len(trainset.ir[trainset.to_inner_iid(iid)])
except ValueError:
return 0
df =
pd.DataFrame(predictions, columns=['uid', 'iid', 'rui', 'est', 'details'])
df['Iu'] = df.uid.apply(get_Iu)
df['Ui'] = df.iid.apply(get_Ui)
df['err'] = abs(df.est - df.rui)
best_predictions = df.sort_values(by='err')[:10]
worst_predictions = df.sort_values(by='err')[-10:]
print(best_predictions)
print(worst_predictions)
结果:
import matplotlib.pyplot as plt
#
get_ipython().run_line_magic('matplotlib', 'inline')
df_new.loc[df_new['ISBN'] == '0440241537']['bookRating'].hist()
plt.xlabel('rating')
plt.ylabel('Number of
ratings')
plt.title('Number of
ratings book ISBN 0440241537 has received')
plt.show()
结果:

浙公网安备 33010602011771号