机器学习之推荐算法
1、知识点
""" 推荐系统 1、相似度计算: 1、欧几里德距离 2、皮尔逊相关系数 3、Cosin距离 2、推荐相似度选择: 1、固定数量的邻居 2、基于相似度门槛的邻居 3、基于用户的协同过滤:根据用户和其他用户之间的相关系数值,选择值越小的用户数据,并和该用户比较,推荐物品 需要解决的问题:1、已知用户评分矩阵R(一般很稀疏) 2、推断矩阵中空格empty cells处的值 基于用户的协同过滤不利于对全0矩阵进行推荐,其解决方案: 1、相似度计算最好使用皮尔逊相似度 2、考虑共同打分物品的数目 3、对打分进行归一化处理 4、设置一个相似度阈值 缺点:1、稀疏问题(很多值为0) 2、大用户量不利于计算,因此不推荐基于用户的协同过滤 row:为用户 ,column:为物品 场景:实时新闻、突发情况(实时数据) 4、基于物品的协同过滤:根据物品和物品之间的相似度,然后取阈值,获取相邻的值,即推荐物品 (一般使用皮尔逊相关系数) 优点:1、计算性能高,用户数量大于物品数量 row:为用户物品 ,column:为用户 场景:图书、电子商务、电影(离线数据) 5、用户冷启动问题(即用户注册的时候): 1、引导用户把自己的一些属性表达出来 2、利用现有的开发数据平台 3、根据用户注册的属性 4、推荐排序榜单 6、物品冷启动问题: 1、文本分析 2、主题模型 3、打标签 4、推荐排行榜单 7、隐语义模型:将矩阵进行分解,然后求解隐含特征F,从而可以根据F得到一个先的具有填充值的NM矩阵,从而实现推荐,即NM = NF * FM 1、从数据出发,今天个性化推荐 2、用户和物品之间有着隐含联系 3、隐含因子让计算机能理解就好 4、将用户和物品通过中介隐含因子联系起来 隐语义模型参数选择: 1、隐特征的个数F,通常F=100 2、学习率alpha 别太大 3、正则化参数lambda,别太大 4、负样本和正样本比例ratio 8、协同过滤与 隐语义对比 1、原理:协同过滤基于统计方法,隐语义基于建模 2、空间复杂度,隐语义模型较小 3、实时推荐依旧难,目前离线计算多 9、模型评估指标 1、准确率 :均方误差 2、召回率 :正负样本中,推荐正样本中正确的比例 3、覆盖率 4、多样性 推荐难点: 1、计算量解决 2、模型的好坏怎么评估,怎么更新
- L1正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,可以用于特征选择
- L2正则化可以防止模型过拟合(overfitting);一定程度上,L1也可以防止过拟合
suprise 推荐系统api url:https://surprise.readthedocs.io/en/stable/getting_started.html 数据地址:http://files.grouplens.org/datasets/movielens/ml-100k-README.txt 基于用户的协同过滤: """
2、代码实现推荐案例
# coding = utf-8 from __future__ import (absolute_import,division,print_function,unicode_literals) from surprise import SVD,KNNBasic from surprise import Dataset from surprise import evaluate,print_perf from surprise import GridSearch import pandas as pd import os import io from surprise import KNNBaseline def collaborativeFiltering(): """ 协同过滤算法 :return: """ #1、加载数据 data = Dataset.load_builtin('ml-100k') data.split(n_folds=3)#3折,结果有3个 #2、实例化协同过滤算法对象 algo = KNNBasic() pref =evaluate(algo,data,measures=['RMSE','MAE'])#算法模型评估 print_perf(pref) def matrixFactorization(): """ SVD,矩阵分解 :return: """ param_grid = {'n_epochs':[5,10],'lr_all':[0.002,0.005],'reg_all':[0.4,0.6]} grid_search = GridSearch(SVD,param_grid,measures=['RMSE','FCP']) data = Dataset.load_builtin('ml-100k') data.split(n_folds=3) # 3折,结果有3个 grid_search.evaluate(data) print(grid_search.best_score['RMSE']) #最好的得分值 print(grid_search.best_params['RMSE']) # 最好的得分值 result_df =pd.DataFrame.from_dict(grid_search.cv_results) print(result_df) def recommendItem(): data = Dataset.load_builtin('ml-100k') #加载u.data文件 trainset = data.build_full_trainset() sim_options = {'name':'pearson_baseline','user_based':False} #皮尔逊相似度pearson_baseline ,'user_based':False表示基于物品的协同过滤 algo = KNNBaseline(sim_options=sim_options) #协同过滤 algo.train(trainset) #训练 #获取电影的id rid_to_name,name_to_rid = read_item_names() toy_story_raw_id = name_to_rid['Now and Then (1995)'] print(toy_story_raw_id) #数据文件中的id toy_story_inner_id =algo.trainset.to_inner_iid(toy_story_raw_id) print(toy_story_inner_id)#实际计算矩阵中的id toy_story_neighbors_id = algo.get_neighbors(toy_story_inner_id,k=10) print(toy_story_neighbors_id) #实际计算矩阵中的id toy_story_neighbors_id = (algo.trainset.to_raw_iid(inner_id) for inner_id in toy_story_neighbors_id) #数据文件中的id toy_story_neighbors_name = (rid_to_name[rid] for rid in toy_story_neighbors_id) #数据文件中的name print("##########推荐item#########") for movie in toy_story_neighbors_name: print(movie) def read_item_names(): file_name=('./ml-100k/u.item') rid_to_name={} name_to_rid={} with io.open(file_name,'r',encoding='ISO-8859-1') as f: for line in f: line = line.split('|') rid_to_name[line[0]] = line[1] name_to_rid[line[1]]=line[0] return rid_to_name,name_to_rid if __name__ == '__main__': recommendItem()
3、基于物品的协同过滤图
4、代码案例2
import recsys.algorithm recsys.algorithm.VERBOSE = True from recsys.algorithm.factorize import SVD from recsys.datamodel.data import Data from recsys.evaluation.prediction import RMSE import os,sys tmpfile = "/tmp/movielens.zip" moviefile = "./ml-1m/movies.dat" class RecommendSystem(object): def __init__(self, filename, sep, **format): self.filename = filename self.sep = sep self.format = format # 训练参数 self.k = 100 self.min_values = 10 self.post_normalize = True self.svd = SVD() # 判断是否加载 self.is_load = False # 添加数据处理 self.data = Data() # 添加模型评估 self.rmse = RMSE() def get_data(self): """ 获取数据 :return: None """ # 如果模型不存在 if not os.path.exists(tmpfile): # 如果数据文件不存在 if not os.path.exists(self.filename): sys.exit() # self.svd.load_data(filename=self.filename, sep=self.sep, format=self.format) # 使用Data()来获取数据 self.data.load(self.filename, sep=self.sep, format=self.format) train, test = self.data.split_train_test(percent=80) return train, test else: self.svd.load_model(tmpfile) self.is_load = True return None, None def train(self, train): """ 训练模型 :param train: 训练数据 :return: None """ if not self.is_load: self.svd.set_data(train) self.svd.compute(k=self.k, min_values=self.min_values, post_normalize=self.post_normalize, savefile=tmpfile[:-4]) return None def rs_predict(self, itemid, userid): """ 评分预测 :param itemid: 电影id :param userid: 用户id :return: None """ score = self.svd.predict(itemid, userid) print "推荐的分数为:%f" % score return score def recommend_to_user(self, userid): """ 推荐给用户 :param userid: 用户id :return: None """ recommend_list = self.svd.recommend(userid, is_row=False) # 读取文件里的电影名称 movie_list = [] for line in open(moviefile, "r"): movie_list.append(' '.join(line.split("::")[1:2])) # 推荐具体电影名字和分数 for itemid, rate in recommend_list: print ("给您推荐了%s,我们预测分数为%s" %(movie_list[itemid],rate)) return None def evaluation(self, test): """ 模型的评估 :param test: 测试集 :return: None """ # 如果模型不是直接加载 if not self.is_load: # 循环取出测试集里面的元组数据<评分,电影,用户> for value, itemid, userid in test.get(): try: predict = self.rs_predict(itemid, userid) self.rmse.add(value, predict) except KeyError: continue # 计算返回误差(均方误差) error = self.rmse.compute() print ("模型误差为%s:" % error) return None if __name__ == "__main__": rs = RecommendSystem("./ml-1m/ratings.dat", "::", row=1, col=0, value=2, ids=int) train, test = rs.get_data() rs.train(train) rs.evaluation(test) # rs.rs_predict(1,1) rs.recommend_to_user(1)
本文来自博客园,作者:小白啊小白,Fighting,转载请注明原文链接:https://www.cnblogs.com/ywjfx/p/11061313.html