zoukankan      html  css  js  c++  java
  • 机器学习之推荐算法

    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)
  • 相关阅读:
    cpu时钟周期
    调参学习
    力扣:堆
    学习率衰减问题
    力扣:图之并查集问题
    Java判断空字符串
    python读取文件通过正则过滤需要信息然后保存到新文件里
    python换行写入文件
    Robotium solo.goBack();不起作用,解决方案
    Android清除本地数据缓存代码
  • 原文地址:https://www.cnblogs.com/ywjfx/p/11061313.html
Copyright © 2011-2022 走看看