文章推荐系统

本文深入探讨了推荐系统的方法,包括基于用户和物品的协同过滤算法,详细介绍了相似度计算和算法优缺点。接着,讨论了基于内容的推荐,通过构建特征权重矩阵和使用TF-IDF进行内容匹配。最后,引入了矩阵分解的协同过滤系统,以及混合型推荐算法,通过模型评估比较了不同推荐策略的准确率。
摘要由CSDN通过智能技术生成

1.以用户为基础的协同过滤

基于用户对某些商品进行打分
在这里插入图片描述
在这里插入图片描述

*1.1相似度运算:

1.1.1欧几里得距离评价

在这里插入图片描述
在这里插入图片描述

1.1.2皮尔逊相关度评价

依旧对商品进行打分

在这里插入图片描述
在这里插入图片描述
1.1为用户推荐商品 (加权排序推荐)
在这里插入图片描述

1.2算法缺点

在这里插入图片描述

2.基于物品的协同过滤算法

在这里插入图片描述

2.1基于物品对用户进行打分

在这里插入图片描述在这里插入图片描述

2.1 相似度评价

在这里插入图片描述皮尔逊相关度评价
在这里插入图片描述
通过计算可以发现,商品1&2,商品3&4&5的相似度较⾼。下⼀步我们可以依据这些商品间的相关度对⽤户进⾏商品推荐。

2.2 为⽤户提供基于相似物品的推荐

在这里插入图片描述
在这里插入图片描述

协同过滤优缺点

在这里插入图片描述

3.基于内容的推荐算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据集读取

数据集包含了某新闻类APP上近12个⽉内的⽤户⾏为数据、以及具体的新闻⽂章内容。
现在需要根据⽂章的内容、⽤户和⽂章的互动⾏为数据,基于推荐算法,为⽤户推荐他可能会感兴趣且尚未看过的新闻⽂章。
数据集由2个csv⽂件组成:
shared_articles.csv: ⽂章的具体内容数据
users_interactions.csv: ⽤户与⽂章互动的⾏为数据(分享⽂章)

import numpy as np
import scipy
import pandas as pd
import math
import random
import sklearn
from nltk.corpus import stopwords
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from scipy.sparse.linalg import svds
import matplotlib.pyplot as plt

⽂章的具体内容(shared_articles.csv)

⽂章的具体内容数据中,还包括⽂章被操作的时间、⽂章id、作者id、作者所在地等。
⽂章的操作类型(eventType)包括content shared与content removed;为了简化问题,我们仅考虑被分享过的⽂章。

# 读取⽂章的具体内容数据 为articles_df,articles_df的每条记录均有对应的contentId
articles_df = pd.read_csv('shared_articles.csv')
articles_df = articles_df[articles_df['eventType'] == 'CONTENT SHARED'] #我们仅考虑被分享过的⽂章
articles_df.head(3)

在这里插入图片描述
在这里插入图片描述

⽤户与⽂章互动的⾏为数据(users_interactions.csv)

#⽤户与⽂章互动的⾏为数据(users_interactions.csv)
#users_interactions.csv是⽤户与⽂章互动的⾏为数据
#⾏为类型有:
“”"
VIEW: 浏览
LIKE: 点赞
COMMENT CREATED: 评论
FOLLOW: 关注该⽂章
BOOKMARK: 给⽂章地址加书签
“”"

# 每条记录由 contentId与personId 的组合来对应
interactions_df = pd.read_csv('C:/Users/lb/Desktop/test/users_interactions.csv')
interactions_df.head(3)
#users_interactions.csv之后可以与articles_shared.csv 连接,连接键为 contentId

在这里插入图片描述

数据处理

基于⽤户与⽂章的互动⾏为建⽴量化体系、统计评分数据
我们需要对不同的⾏为类型赋予合适的评分,之后才能量化⽤户的互动⾏为数据,⽐如评论的分数会⾼于浏览与点赞的分数。
基于⽤户对⽂章的互动⾏为数据构建评分体系,⽬的是科学地评估⽤户对不同⽂章感兴趣的程度,进⽽去做推荐。

event_type_strength = {
   
'VIEW': 1.0,
'LIKE': 2.0,
'BOOKMARK': 2.5,
'FOLLOW': 3.0,
'COMMENT CREATED': 4.0,
}
# 评论的分数最⾼,其次是关注,然后是保存地址于书签。
# 基于评分标准,量化⽤户的互动⾏为数据
interactions_df['eventStrength'] = interactions_df['eventType'].apply(lambda x: event_type_strength[x])

也有类似采用replace()的用法

# status_replace =  { 
#     "eventType" :{
   
#     'VIEW':1.0,
#     'LIKE':2.0,
#     'BOOKMARK':2.5,
#     'FOLLOW':3.0,
#     'COMMENT CREATED':4.0,
    
#     } 
# }
# ## 评论的分数最⾼,其次是关注,然后是保存地址于书签。

# # 基于评分标准,量化⽤户的互动⾏为数据

# interactions_df = interactions_df.replace(status_replace)

在这里插入图片描述
基于冷启动问题,只取⽂章互动次数在5次及以上的⽤户
由于推荐系统存在冷启动的问题,即很难为那些尚未买过⼀定数量的物品(或接触过⼀定数量的⽂章)的⽤户提供个性化的推荐,因为历史数据中他们买过的物品(接触的⽂章)的信息有限。
因此我们⽬前的案例只对互动过的⽂章数在5篇及以上的⽤户进⾏研究。
现在我们要计算每个⽤户互动过的⽂章数量,然后再限制数量>=5,把互动⽂章数超过5的⽤户筛选出来。
df.groupby(‘personId’).size() 和
df.groupby([‘personId’, ‘contentId’]).size().groupby(‘personId’).size() 的区别

interactions_df.groupby('personId').size()

在这里插入图片描述

interactions_df.groupby('personId')['contentId'].count()

在这里插入图片描述

上⾯这两种⽅法都没有对contentId去重

去重办法:
利用groupby 进行去重

interactions_df.groupby(['personId', 'contentId']).size().groupby('personId').size()

在这里插入图片描述
验证:
loc[] 表根据标签或者索引

len(interactions_df.loc[interactions_df['personId']==-9212075797126931087, 'contentId'].unique())

在这里插入图片描述
users_interactions_count_df

#区别在于⼀个⽤户对同⼀篇⽂章可能有多次互动操作(包括浏览、分享、点赞等),因此如果仅仅df.groupby('personId').size() ,会包含重复的数量。
users_interactions_count_df = interactions_df.groupby(['personId', 'contentId']).size().groupby('personId').size()
print('# users: %d' % len(users_interactions_count_df))

在这里插入图片描述

对聚合操作后的数据(此时已经是从dataframe转换至series),那么就需要进行series至dataframe的转换。

使用reset_index() 就可以转换成dataframe

pandas小技巧将Series转换为DataFrame
https://zhuanlan.zhihu.com/p/64083572

计算每个⽤户互动过的⽂章数量,然后再限制数量>=5,把互动⽂章数超过5的⽤户筛选出来。

# 计算每个⽤户互动过的⽂章数量,然后再限制数量>=5,把互动⽂章数超过5的⽤户筛选出来。
users_with_enough_interactions_df = users_interactions_count_df[users_interactions_count_df >= 5].reset_index()[['personId']]
print('# users with at least 5 interactions: %d' % len(users_with_enough_interactions_df))

在这里插入图片描述在这里插入图片描述变成dataFRAME 了
在这里插入图片描述

#[[‘personId’]]和[‘personId’]的区别

在这里插入图片描述

用户操作数量大于5篇文章 那些用户id 与原表进行匹配

interactions_from_selected_users_df

interactions_from_selected_users_df = interactions_df.merge(users_with_enough_interactions_df,
how = 'inner',
on = 'personId')
len(interactions_from_selected_users_df)

4.构建⽤户-物品评分数据表

由于⽤户可能会多次浏览、评论同⼀篇⽂章,所以我们在量化⽤户对某⼀篇⽂章的⾏为数据时,是先将⽤户的⾏为赋值、然后加和得到⼀个互动数值。所以现在我们要做的就是加和。
同时我们对最后的互动数值取对数值,使得其分布更符合正态分布且更平滑。

用np.log() 不合适 不清楚数据类型

def smooth_user_preference(x):
return math.log(1+x, 2)
interactions_full_df = interactions_from_selected_users_df \
.groupby(['personId', 'contentId'])['eventStrength'].sum() \
.apply(smooth_user_preference).reset_index()
print('# of unique user/item interactions: %d' % len(interactions_full_df))
interactions_full_df.head(10)

或者:a = interactions_from_selected_users_df.groupby(['personId','contentId'])['eventStrength'].sum().apply(lambda x :math.log(1+x, 2) )\ .reset_index() #reset_index() ,改成dataFRAME

在这里插入图片描述

5.具体的推荐算法

对推荐算法效果的评估是⼗分重要的,这⾥我们使⽤了交叉验证⽅法,即随机取20%的数据集作为测试集,80%的数据集作为训练集。

stratify参数作用

interactions_train_df, interactions_test_df = train_test_split(interactions_full_df,
stratify=interactions_full_df['personId'],
test_size=0.20,
random_state=42)
print('# interactions on Train set: %d' % len(interactions_train_df))
print('# interactions on Test set: %d' % len(interactions_test_df))

在这里插入图片描述

6.Top-N推荐的准确性评测

在这里插入图片描述
在这里插入图片描述

使⽤personId(⽤户id)作为⽤户-物品评分数据集的索引,提⾼之后获取数据的速度

使⽤personId(⽤户id)作为⽤户-物品评分数据集的索引

# 使⽤personId(⽤户id)作为⽤户-物品评分数据集的索引,提⾼之后获取数据的速度
interactions_full_indexed_df = interactions_full_df.set_index('personId')
interactions_train_indexed_df = interactions_train_df.set_index('personId')
interactions_test_indexed_df = interactions_test_df.set_index('personId')

在这里插入图片描述

def get_items_interacted(person_id, interactions_df):

#集合可以相减

#集合可以相减
def get_items_interacted(person_id, interactions_df):
    # Get the user's data and merge in the movie information.
    #得到指定得person_id 的所对应的那些contentId
    interacted_items = interactions_df.loc[person_id]['contentId']
    return set(interacted_items if type(interacted_items) == pd.Series else [interacted_items])

按照索引之后 跳了一步
在这里插入图片描述

7.Top-N推荐的准确性评测⽅法

# Top-N推荐的准确性
EVAL_RANDOM_SAMPLE_NON_INTERACTED_ITEMS = 100
class ModelEvaluator:
	

下面都是上面的子函数

⽤于随机取出 sample_size篇、先前该⽤户没有互动过的⽂章

# ⽤于随机取出 sample_size篇、先前该⽤户没有互动过的⽂章
    def get_not_interacted_items_sample(self, person_id, sample_size, seed=42):
        interacted_items = get_items_interacted(person_id, interactions_full_indexed_df)
        #全部的文章
        all_items = set(articles_df['contentId'])
        #减去指定得文章(即互动过的文章&
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值