赞
踩
协同过滤:Collaborative Filtering【CF】
基于近邻的协同过滤
基于模型的协同过滤
用户用标签来描述对物品的看法,所以用户生成标签(UGC)是联系用户和物品的纽带,是反映用户兴趣的重要数据源
一个用户标签行为的数据集一般由一个三元组(用户,物品,标签)的集合表示,其中一条记录(u,i,b)表示用户u给物品i打上了标签b
一个最简单的算法:
对于一个用户,首先找到他常用的标签,然后找到具有这些标签的最热门的商品,推荐给他
计算公式如下:
p
(
u
,
i
)
=
∑
b
n
u
,
b
n
b
,
i
p(u,i)=\sum_bn_{u,b}n_{b,i}
p(u,i)=b∑nu,bnb,i
其中,
n
u
,
b
n_{u,b}
nu,b是用户u打过标签b的次数,
n
b
,
i
n_{b,i}
nb,i是物品i被打过标签b的次数。
存在的问题:
解决方案:
TF-IDF算法
应用上述的思想对算法作出改进:
在简单的算法基础之上,直接加入对热门标签和热门物品的惩罚项
公式如下:
p
(
u
,
i
)
=
∑
b
n
u
,
b
/
l
o
g
(
1
+
n
b
(
u
)
)
∗
n
b
,
i
/
l
o
g
(
1
+
n
i
(
u
)
)
p(u,i)=\sum_bn_{u,b}/log(1+n_b^{(u)})*n_{b,i}/log(1+n_i^{(u)})
p(u,i)=b∑nu,b/log(1+nb(u))∗nb,i/log(1+ni(u))
其中,
n
b
(
u
)
n_b^{(u)}
nb(u)记录了标签b被多少不同的用户使用过,
n
i
(
u
)
n_i^{(u)}
ni(u)记录了物品i被多少不同的用户打过标签
# TF-IDF算法示例 import numpy as np import pandas as pd import math # 1. 定义数据和预处理 docA = "The cat sat on my bad" docB = "The dog sat on my knees" bowA = docA.split(" ") bowB = docB.split(" ") # 构建词库 wordSet = set(bowA).union(set(bowB)) # 2. 进行词数统计 # 用统计词典来保存词出现的次数 wordDictA = dict.fromkeys(wordSet,0) wordDictB = dict.fromkeys(wordSet,0) # 遍历文档,统计词数 for word in bowA: wordDictA[word] += 1 for word in bowB: wordDictB[word] += 1 # 3. 计算词频TF def computeTF(wordDict, bow): # 用一个字典对象记录TF,把所有的词对应在bow文档里的TF都算出来 tfDict = {} nbowCount = len(bow) for word, count in wordDict.items(): tfDict[word] = count / nbowCount return tfDict tfA = computeTF(wordDictA,bowA) tfB = computeTF(wordDictB,bowB) # 4. 计算逆文档频率IDF def computeIDF(wordDictList): # 用一个字典对象保存IDF,每个词作为key,初始值为0 idfDict = dict.fromkeys(wordDictList[0], 0) N = len(wordDictList) for wordDict in wordDictList: # 遍历字典中的每个词 for word, count in wordDict.items(): if count > 0: idfDict[word] += 1 return idfDict idfs = computeIDF([wordDictA,wordDictB]) # 5. 计算TF-IDF def computeTDIDF(tf, idfs): tfidf = {} for word, tfval in tf.items(): tfidf[word] = tfval * idfs[word] return tfidf tfidfA = computeTDIDF(tfA,idfs) tfidfB = computeTDIDF(tfB,idfs)
# LFM梯度下降算法实现 import numpy as np import pandas as pd # 1. 数据准备 # 评分矩阵 6个用户 5种商品 R = np.array([[4,0,2,0,1], [0,2,3,0,0], [1,0,2,4,0], [5,0,0,3,1], [0,0,1,5,1], [0,3,2,4,1]]) # 2. 算法实现 K = 2 max_iter = 10000 alpha = 0.0002 lamda = 0.004 def LFM_grad_desc(R, K, max_iter, alpha, lamda): # 基本维度参数定义 M = len(R) N = len(R[0]) # P Q 初始值,随机生成 P = np.random.rand(M, K) Q = np.random.rand(N, K) Q = Q.T # 开始迭代 for step in range(max_iter): # 对所有的用户u,物品i做遍历,对应的特征向量Pu,Qi梯度下降 for u in range(M): for i in range(N): # 对于每一个大于0的评分,求出预测评分误差 if R[u][i] > 0: eui = np.dot(P[u, :], Q[:, i]) - R[u][i] # 代入公式,按照梯度下降算法更新当前的Pu,Qi for k in range(K): P[u][k] = P[u][k] - alpha * (2 * eui * Q[k][i] + 2 * lamda * P[u][k]) Q[k][i] = Q[k][i] - alpha * (2 * eui * P[u][k] + 2 * lamda * Q[k][i]) # u,i遍历完成,所有特征向量更新完成,可以得到P,Q,那么就可以计算预测评分矩阵 predR = np.dot(P, Q) # 计算当前损失函数 cost = 0 for u in range(M): for i in range(N): if R[u][i] > 0: cost += (np.dot(P[u, :], Q[:, i]) - R[u][i]) ** 2 # 加上正则化项 for k in range(K): cost += lamda * (P[u][k] ** 2 + Q[k][i] ** 2) if(cost < 0.0001): break; print(cost) return P, Q.T, cost # 3. 测试 P, Q, cost= LFM_grad_desc(R, K, max_iter, alpha, lamda) predR = P.dot(Q.T)
优点:
存在的问题:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。