# 推荐系统 **Repository Path**: goalaaa/recommendation_system ## Basic Information - **Project Name**: 推荐系统 - **Description**: No description available - **Primary Language**: Python - **License**: MulanPSL-1.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 4 - **Created**: 2021-04-15 - **Last Updated**: 2021-08-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 推荐系统 ## 推荐概念 信息过滤系统解决信息过载用户需求不明确的问题 * 利用一定的规则将物品排序展示给需求不明确的用户 推荐搜索区别 * 推荐个性化较强,用户被动的接受,希望能够提供持续的服务 * 搜索个性化弱,用户主动搜索,快速满足用户的需求 ## 推荐和web项目区别 * 构建稳定的信息流通通道 * 推荐信息过滤系统 * web对结果有明确预期 * 推荐结果是概率问题 ## Lambda架构介绍 * 离线计算和实时计算共同提供服务的问题 * 离线计算优缺点 * 优点 能够处理的数据量可以很大比如pb级别 * 缺点 速度比较慢分钟级别的延迟 * 实时计算 * 优点 响应快来一条数据处理一条 ms级别响应 * 缺点 处理的数据量小一些 * 离线计算的框架 * hadoop * spark core , spark sq| * hive * 实时计算框架 * spark streaming * storm * flink * 消息中间件 * flume日志采集系统 * kafka 消息队列 * 存储相关 * hbase noq|数据库 * hive sq|操作hdfs数据 * 推荐算法框架 * 召回->排序->策略调整 ## 推荐算法架构 * 召回 * 协同过滤 * 算相似度 memory base * 基于模型的 model base 矩阵分解 * 基于内容 * 分词 * 词权重(提取关键词)tf-idf * word2Vec 词向量 * 物品向量 * 排序 * 逻辑回归 * 策略调整 ## **推荐模型构建流程** * 数据收集 * 显性评分 * 隐性数据 * 特征工程 * 协同过滤:**用户-物品 评分矩阵** * 基于内容:**分词tf-idf word2Vec** * 训练模型 * 协同过滤 * KNN * 矩阵分解 梯度下降 * 评估、模型上线 ## **协同过滤思路介绍** CF(collaborative filtering )物以类聚人以群分,做协同过滤的话首先特征工程把用户-物品的评分矩阵创建出来 * 基于用户的协同过滤 1. 给用户A找到最相似的N个用户 2. N个用户消费过哪些物品 3. N个用户消费过的物品中-A用户消费过的就是推荐结果 * 基于物品的协同过滤 1. 给物品A找到最相似的N个物品 2. A用户消费记录找到这些物品的相似物品 3. 从这些相似物品先去重-A用户消费过的就是推荐结果 ## 相似度计算 * 余弦相似度、皮尔逊相关系数(矩阵需**稠密型、连续型**) * 向量的夹角余弦值 * 皮尔逊会对向量的每一个分量做中心化 * 余弦只考虑方向不考虑向量长度 * 如果评分数据是连续的数值比较适合中,余弦、皮尔逊计算相似度 * 杰卡德相似度 * 交集/并集 * 计算评分是0、1布尔值的相似度 * 使用不同相似度计算方式实现协同过滤 1. 如果买/没买点/没点数据0/1适合使用**杰卡德相似度** from sklearn.metrics import jaccard_score jaccard_score(df[ltemA]df[ltemB']) from sklearn.metrics.pairwise import pairwise_distances user_ similar= 1-pairwise_distances(df.value,metric="jaccard) 2. 一般用评分去做协同过滤推荐使用**皮尔逊相关系数**,评分预测基于用户和基于物品的协同过滤严格上说,属于两种算法,实践中可以都做出来,对比效果,选择最靠谱的 ## **协同过滤基于模型的算法** 1. 用户-物品矩阵比较稀疏的时候,直接去取物品向量、用户向量,计算相似度不太适合 2. 基于模型的方法可以解决用户-物品矩阵比较稀疏的问题 3. 矩阵分解 1. 把大的矩阵拆成两个小的 用户矩阵、物品矩阵 MxK KxN K<基于内容的推荐 * 随着用户行为积累的越来越多->协同过滤 * 基于内容和协同过滤共同工作 ## 基于内容的推荐 * 给物品打标签 * 系统自己提取从业务数据库中提取 * 用户填写 * 中文分词利用算法计算词的权重 * tf-idf(**tf term frequency 词频、idf inverse document frequency 逆文档频率**) * **tf 词频** 文章中出现次数/全文总词数 5/100 * **idf 逆文档频率** log以10为底数,文本库篇数/出现关键词的文章篇数,1000篇中10篇出现python这个词,1000/10=100,idf=log10(100)=2 * tf-idf = 5/100*2 = 0.1 * 当每篇文章中都会出现的关键词 ,比如“的”,“我”,idf = 1000/1000 log(1) ,= 0 * textrank * 利用标签的文字转换成词向量 * **word2Vec词**->向量 * 用向量来表示语义 * 如果两个词的词向量相似度比较高,认为这两个词的语义相近 * 利用词向量构建物品的向量 * 一个物品有N个关键词,每个关键词对应一个词向量 * 求和(权重*词向量)/ N * 利用N个关键词的词向量获取物品向量 * 通过物品向量计算相似度 * 皮尔逊相关系数 计算物品的相似度 ## 基于内容的推荐 基于物品的协同过滤 区别 * content_base : 词向量->物品向量->计算相似度 * item_base cf : user-item matrix->物品向量->计算相似度 * content_base item_base cf 来源不一样 * 物品向量构建过程有区别 * 基于内容的推荐,物品向量文本(物品描述信息,系统填标签,用户填标签) * 基于物品的协同过滤,用户对物品的评分矩阵用户的行为数据中来(需要上线一会,统计数据) ## K近邻协同过滤 * 用户向量物品向量计算相似度,MemoryBased CF * 之前没有考虑近邻问题而是利用所有正相关用户 * 考虑K近邻只需要按照相似度找到相似度最高的N个用户 * similar_users =self.similar[uid].drop([uid]).dropna().sort_values(ascending=False)[:self.k] ## Baseline:基准预测 * 所用物品评分平均值 * 找到每一个用户对物品平均评分的bias bu * 找到每一个物品对平均分bias bi * 预测的得分mean+bu+bi u代表第u个用户,i代表第i个物品 * 可以使用梯度下降来优化损失 ## Model-Based 协同过滤算法 * baseline思想来解决协同过滤问题 * 计算出所有用户对所有物品评分的平均值 * 预测的评分 = 在平均值的基础上 + 用户评分偏置 + 物品的评分偏置 * 求解所有用户的评分偏置 和 所有物品的得分偏置 * 这个问题可以转化成损失优化的过程 * 梯度下降 * 交替最小二乘法 ## 矩阵分解 * SVD 奇异值分解 * 一个大矩阵分成3个小矩阵中间的是一个k方阵 * SVD只适用于没有缺失必须是稠密矩阵 * Funk SVD * 一个大的分成两个小矩阵 * LFM Latent factor model 隐语义原理 * BiasSVD矩阵分解+ baseline * SVD++ 矩阵分解+baseline+其它影响(点击,收藏,购买) ## 基于内容的推荐 * 画像构建给用户/物品打标签(至少50) * 物品画像 * 分类信息 * 标题 * 电影/音乐主演、歌手 * 用户画像 * 喜好的物品类别 行为偏好 * 基本人口学属性 * 活跃程度 * 风控纬度 * PGC 应用自己生产 * UGC 用户来生成 * 基于内容推荐的算法流程 * 用户画像/物品画像 * 匹配用户画像 物品画像 * 物品冷启动问题 * 画像->词向量->物品向量->计算物品相似度了 * 从文本描述的角度找相似的物品 * 当用户在浏览A的时候 通过上述套路找到跟物品A相似的一系列物品 ## 基于内容推荐流程 * 建立物品画像 * 数据来源:用户打tag 和 电影的分类值 * 根据tf-idf的结果 为每部电影筛选出top-n(td-idf较大)个关键词 * 电影id-关键词-关键词权重 * 建立倒排索引 * 通过关键词找到电影 * 遍历 电影id-关键词-关键词权重 读取每一个关键词,用关键词作为key [(关键词对应电影id,tfidf)]作为value 保存到dict中 * 用户画像 * 看用户看过电影(打过分的),到电影的id-关键词-关键词权重数据中 找到所有的关键词 * 把用户看过的所有关键词 放到一起 统计词频 * 出现多的关键词 作为用户的兴趣词 实际上就是用户画像的关键词 * 根据用户的兴趣词 找到兴趣词对应的电影 多个兴趣值可能对应一个电影 {电影id:[关键词1权重,关键词2权重]} * 把每一个电影对应的关键词权重求和 排序 推荐给用户 ##词向量 * 用向量来表示词语可以表示语义层面的含义 * 如果用word2vec模型创建的词向量,两个词向量相似度比较高,说明这两个词是近义词 * 词向量作用把含义相近的判断转换成向量的相似度计算 * 使用gensim Word2Vec模块训练词向量模型 * sentences = list(movie_profile['profile'].values) #准备所有用来训练词向量模型的文本 * model = gensim.models.Word2Vec(sentences,window=3,min_count = 1,iter = 20) #参数1 文本 参数2 window 观察上下文关系的窗口长度 min_count 训练模型时要保留下的词语出现的频率 iter 迭代次数 * 通过词向量模型找到topn相似词 * model.wv.most_similar(positive=['要找到相似词的词语'],topn = 10) * 文档向量 * from gensim.models.doc2vec import Doc2Vec,TaggedDocument * documents = [TaggedDocument(words,[movie_id]) for movie_id,words in movie_profile['profile'].iteritems()] #训练模型并保存 通过向量来表示一篇文档 一篇文档对应一个电影 向量的相似度代表 电影的相似度 * model = Doc2Vec(documents,vector_size=100,window=3,min_count=1,workers=4,epochs=20) * words = movie_profile['profile'].loc[6] * inferred_vector = model.infer_vector(words) #传入电影的标签 找到电影文档所对应的向量 * model.docvecs.most_similar([inferred_vector],topn=10) #找到最相似的n个向量