当前位置:   article > 正文

《推荐系统笔记(十二)》聚类生成标签以及基于标签的TopN推荐_聚类标签

聚类标签

如何生成标签?

一般有

  • PGC(专家生成)
  • UGC(用户生成)

但是,面对海量的数据需要打标签时,人工打标签太过昂贵和耗时,一个可行方法是对数据使用聚类,然后将聚类结果作为标签使用。

下面给一个聚类的简单例子(数据集footballTeams已经上传,各位免费下载)。

# 第三方库
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn.preprocessing import MinMaxScaler
import seaborn as sns
import matplotlib.pyplot as plt
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
# KMeans
# 导入数据
data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第二节\footballTeams.txt', sep='\t')
data.head()
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

# 数据清洗
data.drop(['Unnamed: 0', 'Unnamed: 5'], axis=1, inplace=True)
data.set_index('国家', inplace=True)
# 由于聚类需要计算距离,所以必须提前把数据规范化
data = pd.DataFrame(MinMaxScaler().fit_transform(data.values), columns=data.columns, index=data.index)
data.head()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
# 观察一下数据情况
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
sns.pairplot(data)
plt.show()
  • 1
  • 2
  • 3
  • 4
# 用kmeans聚类
kmeans = KMeans(n_clusters=3).fit(data.values)
data['cluster'] = kmeans.labels_
data.head()
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

如何使用标签?

用户 user 对商品 item 打标签 tag,这样,我们的一条数据是 ( u s e r , i t e m , t a g ) (user, item, tag) (user,item,tag)

如何根据这些标签数据,给用户推荐商品?一个自然的想法是,用户u给商品i打分,从没有购买过的商品中,选择分值最高的商品作为推荐。

根据打分函数的不同,我们可以分为SimpleTagBased算法、NormTagBased算法和TFIDF-TagBased算法

1. SimpleTagBased算法

记打分函数为 p ( u , i ) = ∑ t u s e r _ t a g s [ u , t ] ⋅ t a g _ i t e m s [ t , i ] p(u, i)=\sum_tuser\_tags[u, t]\cdot tag\_items[t, i] p(u,i)=tuser_tags[u,t]tag_items[t,i]

其中, u s e r _ t a g s [ u , t ] user\_tags[u, t] user_tags[u,t]表示用户u打过标签t的次数, t a g _ i t e m s [ t , i ] tag\_items[t, i] tag_items[t,i]表示标签t下物品i的次数。

2. NormTagBased算法

上面的打分函数对于热门物品打分会很高,而对于长尾物品,则可能忽略,因此,我么可以考虑将其正则化,即NormTagBased算法,
p ( u , i ) = ∑ t u s e r _ t a g s [ u , t ] ∑ t u s e r _ t a g s [ u , t ] ⋅ t a g _ i t e m s [ t , i ] ∑ i t a g _ i t e m s [ t , i ] p(u, i)=\sum_t\frac{user\_tags[u, t]}{\sum_tuser\_tags[u, t]}\cdot \frac{tag\_items[t, i]}{\sum_itag\_items[t, i]} p(u,i)=ttuser_tags[u,t]user_tags[u,t]itag_items[t,i]tag_items[t,i]

3. TfIdf-TagBased算法

上面的两种算法里面,对于热门标签下的热门物品,依旧会给较大的打分,为了改善这种情况,我们需要找到 独属于用户user的标签,这意味着

  • 用户user使用这个标签很多次
  • 这个标签总体上使用较少,也就是说,其他人使用这个标签较少

因此,我们将原来的 u s e r _ t a g s [ u , t ] user\_tags[u, t] user_tags[u,t] 改成 u s e r _ t a g s [ u , t ] l o g ( 1 + ∑ u t a g _ u s e r s [ t , u ] ) \frac{user\_tags[u, t]}{log(1+\sum_utag\_users[t, u])} log(1+utag_users[t,u])user_tags[u,t],其中, t a g _ u s e r s [ t , u ] tag\_users[t, u] tag_users[t,u]表示使用标签t被用户u使用的次数。

4. 简单实战

下面,我们通过movielens的tags.csv,使用TfIdf-TagBased算法,做出topN推荐。

movielens数据集已经上传,各位免费下载。

大致思路是这样的,

  • 导入数据
  • 由于tag是字符串,所以提前用labelencoder编码
  • 创建四个辅助数据结构
  • 定义打分函数
  • 对用户没有购买过的产品进行打分,返回前n个
# 第三方库
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
  • 1
  • 2
  • 3
  • 4
# 导入数据
data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第二节\movielens\tags.csv')
data.head()
  • 1
  • 2
  • 3

在这里插入图片描述

# 数据预处理
# 去掉无用的timestamp列
data.drop('timestamp', axis=1, inplace=True)
  • 1
  • 2
  • 3
# 数据预处理
# 去掉无用的timestamp列
data.drop('timestamp', axis=1, inplace=True)
  • 1
  • 2
  • 3
# 数据预处理
# 对tag做LabelEncoder
le = LabelEncoder()
data['tag'] = le.fit_transform(data['tag'].values.tolist())
  • 1
  • 2
  • 3
  • 4
# 创建四个字典 
# user_tags: 用户u用过的标签t的次数
# user_items: 用户u购买过的商品i的次数
# tag_users: 标签t下用户u的次数
# tag_items: 标签t下物品i的次数
user_tags, user_items, tag_users, tag_items = {}, {}, {}, {}

# 遍历数据集,生成列表 
for user, item, tag in data.values:
    user_tags.setdefault(user, {})
    user_items.setdefault(user, {})
    tag_users.setdefault(tag, {})
    tag_items.setdefault(tag, {})
    
    user_tags[user].setdefault(tag, 0)
    user_tags[user][tag] += 1
    
    user_items[user].setdefault(item, 0)
    user_items[user][item] += 1
    
    tag_users[tag].setdefault(user, 0)
    tag_users[tag][user] += 1
    
    tag_items[tag].setdefault(item, 0)
    tag_items[tag][item] += 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
# 用tag_sums记录每个标签总共被人用过多少次
tag_sums = {}
for tag in tag_users.keys():
    tag_sums[tag] = 0
    
    for user in tag_users[tag].keys():
        tag_sums[tag] += tag_users[tag][user]
    
# 给出打分函数,计算公式为tfidf-tagBased算法
def p_ui(u, i):
    score = 0
    
    for tag in user_tags[u].keys():
        temp1 = user_tags[u][tag] / np.log(1 + tag_sums[tag])
        
        if i in tag_items[tag].keys():
            score += temp1 * tag_items[tag][i]
    
    return score
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
# 物品集合
total_items = data['movieId'].unique()

# 定义topN函数
def topN(u, N=4):
    # 用过的物品
    used_items = list(user_items[u].keys())
    # 商品-分数字典
    scores = {}
    # 遍历物品集合,给每个没有购买过的物品打分
    for item in total_items:
        if item not in used_items:
            scores[item] = p_ui(u, item)
    
    # 对分数字典进行排序并返回
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)[:N]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
# 测试
# 给第一个用户id推荐4个电影id
topN(18) 
  • 1
  • 2
  • 3
# 推荐结果
# 电影id,得分score
[(7451, 0.8340647828484926),
 (58105, 0.8340647828484926),
 (1648, 0.4170323914242463),
 (6593, 0.4170323914242463)]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/129019
推荐阅读
相关标签
  

闽ICP备14008679号