基于用户的协同过滤推荐算法(User_CF)

前言

协同过滤推荐算法是诞生最早,并且较为著名的推荐算法。主要的功能是预测和推荐。

协同过滤推荐系统在我们的日常生活之中无处不在,例如,在电子商城购物,系统会根据用户的记录或者其他的

信息来推荐相应的产品给客户。

协同过滤算法通过对用户历史行为数据的挖掘发现用户的偏好,基于不同的偏好对用户进行群组划分并推荐品味相似的商品。协同过滤推荐算法分为两类,分别是基于用户的协同过滤算法(user-based collaboratIve filtering),和基于物品的协同过滤算法(item-based collaborative filtering)。我们这篇文章主要讲基于用户的协同过滤,并附有python代码实现


基于用户的协同过滤算法

在下面的表格中,user_id_表示用户,Move_id_1表示用户喜爱的电影(如何知道用户喜爱与否,我们不考虑)

如下图所示,我们可以知道用户A(user_id_1)爱好的电影是Move_id_1,Move_id_2和Move_id_3

我们现在的目的是找到与用户A(user_id_1)具有相同兴趣爱好的用户群体集合Set<user_id>

找到该群体后,通过该群体找到该群体喜欢的电影集合Set<movie_id>

具体大致如下:

(1)假如横坐标Move_id_有10w个数据,纵坐标Move_id_有100w个数据

横纵坐标交叉处的‘1’代表用户喜爱这部电影,至入如何喜欢需要人为定义,例如浏览过,点赞过,从头到尾看完过等。

(2)如下表找到用户A(user_id_1)的兴趣爱好,我们可以看到,用户A喜欢电影{m1(这里简写一下), m2, m3}

3)找到与用户A(user_id_1)具有相同电影兴趣爱好的用户群体集合Set<user_id>

如上表,可以看到,喜欢{m1, m2, m3}的用户,除了u1,还有{u2, u3}

(4)找到该群体喜欢的电影集合Set<movie_id>

如上表,具备相同喜好的用户群里{u2, u3},还喜好的电影集合是{m4, m5}

划重点:“协同”就体现在这里。

(5)未来用户A(use_id_1)来访问网站时,我们便将要推荐电影{m4, m5}给他。


 

基于用户协同过滤的要点在于找与用户具有相同兴趣爱好的用户群体,在这些群体喜爱的项目群中我们可以找到可以向用户推荐的项目,我们可以通计算用户之间的相似度,来找到一个用户的与他拥有相同兴趣爱好的群体。


我们以电影推荐为例

假如我们现在有一份数据,里面记录的用户观看不同的电影后对电影的评分等一系列信息信息,下面的链接可以下载数据,建议使用1M大小的那个

去网站:  https://grouplens.org/datasets/movielens/       下载movieLen数据集

              或者

                      ml-latest-small(1MB):  http://files.grouplens.org/datasets/movielens/ml-latest-small.zip
                      ml-latest(234.2MB):http://files.grouplens.org/datasets/movielens/ml-latest.zip

上面数据的格式下载后自己看

第一步造数据

由于我们所给的数据时散杂的,当我们首先要对数据进行整理,整理后的数据保存到data.csv中,注意路径。

import pandas as pd

#数据整理
movies = pd.read_csv("C:\\Users\ever\\Desktop\\AI\ml-latest-small\movies.csv")
ratings = pd.read_csv("C:\\Users\ever\\Desktop\\AI\ml-latest-small\\ratings.csv") #ratings.csv开头是r要转义
data = pd.merge(movies, ratings, on = "movieId")#通过两个数据框之间的movieId属性连接
data[['userId', 'rating', 'movieId', 'title']].sort_values('userId').to_csv("C:\\Users\ever\\Desktop\\AI\\data.csv", index=False)
print(data)

结果:

data.csv用于存储数据

 

下面采用python字典来表示每位用户评论的电影和评分

#读取data.csv中每行除了名字外的数据
file = open("C:\\Users\ever\\Desktop\\AI\\data.csv", 'r', encoding = 'UTF-8')
#存放每位用户评论的电影和评分
data = {}

#readlines() 方法用于读取整个文件(所有行)到一个列表,可以由for... in ... 结构进行遍历。列表的每一行变成列表的每一个元素。
for line in file.readlines()[1:10000]:#循环结束后data中的数据都是电影名:评分形式的
    print('line:', line)
    # strip() 方法用于移除字符串头尾指定的字符,需要的朋友可以参考下
    #split() 通过指定分隔符对字符串进行切片
    line = line.strip().split(',')
    #如果字典中没有某位用户,则使用用户ID来创建这位用户
    if not line[0] in data.keys():
        data[line[0]] = {line[3]:line[1]}
        print('55555555',data[line[0]])
        
    else:
        data[line[0]][line[3]] = line[1]
     

print(data)

计算任何两位用户之间的相似度,由于每位用户评论的电影不完全一样,所以兽先要找到两位用户共同评论过的电影

然后计算两者之间的欧式距离,最后算出两者之间的相似度。根据相似度来推荐用户:

下面是完整的代码,造数据的代码单独放一个文件里面

代码中有一些输出项例如有55555555,111,等的print是我在调试的时候为了方便理解加的

import numpy as np

#取两位用户评论过的电影和评分
def Euclidean(user1, user2):
    user1_data = data[user1]
    user2_data = data[user2]
    
    
    distance = 0

    #找出user1和user2都看过的电影,计算二者的而是距离
    for key in user1_data.keys():
        if key in user2_data.keys():
            #user1_data和user2_data为电影的评分
           # print('user1_data', user1_data[key], '            user2_data', user2_data[key])
            distance += pow(float(user1_data[key]) - float(user2_data[key]), 2)
           # print('distance', distance, '\n')
    
    return 1/(1 + np.sqrt(distance))#
    
def top_simliar(userID):
    res = []
    for userid in data.keys():
        if not userid == userID:
            simliar = Euclidean(userID, userid)
            res.append((userid,simliar))
    res.sort(key = lambda val:val[1])
    print('已运行到这里111')
    return res[:4]
  
#根据用户推荐电影给其他人
def recommend(user):
    #相似度最高的用户
    top_sim_user = top_simliar(user)[0][0]
    #相似度最高的用户的观影记录
    items = data[top_sim_user]
    recommendations = []
    #筛选出该用户未观看的电影并添加到列表中
    for item in items.keys():
        if item not in data[user].keys():
            recommendations.append((item,items[item]))
    recommendations.sort(key=lambda val:val[1],reverse=True)#按照评分排序
    #返回评分最高的10部电影
    return recommendations[:10]
 
 


#读取data.csv中每行除了名字外的数据
file = open("C:\\Users\ever\\Desktop\\AI\\data.csv", 'r', encoding = 'UTF-8')
#存放每位用户评论的电影和评分
data = {}

#readlines() 方法用于读取整个文件(所有行)到一个列表,可以由for... in ... 结构进行遍历。列表的每一行变成列表的每一个元素。
for line in file.readlines()[1:10000]:#循环结束后data中的数据都是电影名:评分形式的
    print('line:', line)
    # strip() 方法用于移除字符串头尾指定的字符,需要的朋友可以参考下
    #split() 通过指定分隔符对字符串进行切片
    line = line.strip().split(',')
    #如果字典中没有某位用户,则使用用户ID来创建这位用户
    print('56464654465', line[0], line[3])#line[0]是userid,line[3]是电影名称
    if not line[0] in data.keys():
        data[line[0]] = {line[3]:line[1]}
        print('55555555',data[line[0]])
        
    else:
        data[line[0]][line[3]] = line[1]
        print('111', [data[line[0]][line[3]]])
        print('222', )

print(data)
print('keys', data.keys())

res = top_simliar('4')
print("运行完毕")
print(res)
print('推荐')
Recommendations = recommend('1')
print(Recommendations)   

print('相关系数')
R = pearson_sim('1','3')
print(R)

 

上面就是基于用户的协同过滤推荐算法以及其实现

下面是我学习过程中找到的一些较好的链接,可作为参考

https://blog.csdn.net/qq_25948717/article/details/81839463

https://blog.csdn.net/u012050154/article/details/52268057

https://blog.csdn.net/yimingsilence/article/details/54934302

好的,下面是基于用户协同过滤算法(UserCF)的Python实现。 首先,我们需要导入必要的库,包括pandas和numpy: ```python import pandas as pd import numpy as np ``` 接着,我们需要加载数据集。这里我们使用MovieLens 100k数据集,可以从以下链接下载: https://grouplens.org/datasets/movielens/100k/ 下载后,将数据集解压到当前目录下,并使用以下代码来加载数据: ```python # 加载用户评分数据 ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=['user_id', 'item_id', 'rating', 'timestamp']) # 加载电影标题数据 movies = pd.read_csv('ml-100k/u.item', sep='|', encoding='latin-1', usecols=[0, 1], names=['item_id', 'title']) ``` 接下来,我们需要将数据集划分为训练集和测试集。这里我们使用80%的数据作为训练集,20%的数据作为测试集: ```python # 将数据集划分为训练集和测试集 from sklearn.model_selection import train_test_split train_data, test_data = train_test_split(ratings, test_size=0.2) ``` 然后,我们需要构建用户-电影评分矩阵。这里我们使用pandas的pivot_table函数: ```python # 构建用户-电影评分矩阵 user_item_matrix = train_data.pivot_table(index='user_id', columns='item_id', values='rating') ``` 接着,我们需要计算用户之间的相似度。这里我们使用余弦相似度来计算用户相似度: ```python # 计算用户相似度 from sklearn.metrics.pairwise import cosine_similarity user_similarity = cosine_similarity(user_item_matrix) ``` 然后,我们可以使用用户相似度来预测用户对电影的评分。具体来说,我们需要先找到用户的k个最相似的用户,然后使用这k个用户的评分来预测当前用户对电影的评分。这里我们使用k=10: ```python # 预测用户对电影的评分 def predict(user_id, item_id): # 找到用户的k个最相似的用户 similar_users = user_similarity[user_id-1].argsort()[:-10:-1] # 计算这k个用户对电影的评分的加权平均值 similar_ratings = user_item_matrix.iloc[similar_users][item_id].dropna() weights = user_similarity[user_id-1][similar_users][:len(similar_ratings)] return np.dot(weights, similar_ratings) / weights.sum() if len(similar_ratings) > 0 else 0 ``` 最后,我们可以使用测试集来评估推荐算法的性能。具体来说,我们需要计算预测评分和实际评分之间的均方根误差(RMSE): ```python # 评估推荐算法的性能 from sklearn.metrics import mean_squared_error test_data['predicted_rating'] = test_data.apply(lambda x: predict(x['user_id'], x['item_id']), axis=1) rmse = np.sqrt(mean_squared_error(test_data['rating'], test_data['predicted_rating'])) print('RMSE:', rmse) ``` 完整的代码如下所示: ```python import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.metrics.pairwise import cosine_similarity from sklearn.metrics import mean_squared_error # 加载用户评分数据 ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=['user_id', 'item_id', 'rating', 'timestamp']) # 加载电影标题数据 movies = pd.read_csv('ml-100k/u.item', sep='|', encoding='latin-1', usecols=[0, 1], names=['item_id', 'title']) # 将数据集划分为训练集和测试集 train_data, test_data = train_test_split(ratings, test_size=0.2) # 构建用户-电影评分矩阵 user_item_matrix = train_data.pivot_table(index='user_id', columns='item_id', values='rating') # 计算用户相似度 user_similarity = cosine_similarity(user_item_matrix) # 预测用户对电影的评分 def predict(user_id, item_id): # 找到用户的k个最相似的用户 similar_users = user_similarity[user_id-1].argsort()[:-10:-1] # 计算这k个用户对电影的评分的加权平均值 similar_ratings = user_item_matrix.iloc[similar_users][item_id].dropna() weights = user_similarity[user_id-1][similar_users][:len(similar_ratings)] return np.dot(weights, similar_ratings) / weights.sum() if len(similar_ratings) > 0 else 0 # 评估推荐算法的性能 test_data['predicted_rating'] = test_data.apply(lambda x: predict(x['user_id'], x['item_id']), axis=1) rmse = np.sqrt(mean_squared_error(test_data['rating'], test_data['predicted_rating'])) print('RMSE:', rmse) ``` 希望这个实现对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值