赞
踩
一般有
但是,面对海量的数据需要打标签时,人工打标签太过昂贵和耗时,一个可行方法是对数据使用聚类,然后将聚类结果作为标签使用。
下面给一个聚类的简单例子(数据集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
# KMeans
# 导入数据
data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第二节\footballTeams.txt', sep='\t')
data.head()
# 数据清洗
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()
# 观察一下数据情况
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
sns.pairplot(data)
plt.show()
# 用kmeans聚类
kmeans = KMeans(n_clusters=3).fit(data.values)
data['cluster'] = kmeans.labels_
data.head()
用户 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算法
记打分函数为 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)=t∑user_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的次数。
上面的打分函数对于热门物品打分会很高,而对于长尾物品,则可能忽略,因此,我么可以考虑将其正则化,即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)=t∑∑tuser_tags[u,t]user_tags[u,t]⋅∑itag_items[t,i]tag_items[t,i]
上面的两种算法里面,对于热门标签下的热门物品,依旧会给较大的打分,为了改善这种情况,我们需要找到 独属于用户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使用的次数。
下面,我们通过movielens的tags.csv,使用TfIdf-TagBased算法,做出topN推荐。
movielens数据集已经上传,各位免费下载。
大致思路是这样的,
# 第三方库
import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder
# 导入数据
data = pd.read_csv(r'D:\myfile\开课吧\推荐系统\第二节\movielens\tags.csv')
data.head()
# 数据预处理
# 去掉无用的timestamp列
data.drop('timestamp', axis=1, inplace=True)
# 数据预处理
# 去掉无用的timestamp列
data.drop('timestamp', axis=1, inplace=True)
# 数据预处理
# 对tag做LabelEncoder
le = LabelEncoder()
data['tag'] = le.fit_transform(data['tag'].values.tolist())
# 创建四个字典 # 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
# 用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
# 物品集合 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]
# 测试
# 给第一个用户id推荐4个电影id
topN(18)
# 推荐结果
# 电影id,得分score
[(7451, 0.8340647828484926),
(58105, 0.8340647828484926),
(1648, 0.4170323914242463),
(6593, 0.4170323914242463)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。