矩阵分解在打分预估系统中得到了成熟的发展和应用,为了方便以后复习,先总结如下。
打分矩阵R(n,m)是n行和m列,n表示user个数,m行表示item个数,例如R(5,6)
item1item2 item3item4item5item6
user1 5443 50
user2 04 5 031
user354 0 130
user404 531 5
user510 3 505
其中,为了表示方便0表示没有打分,根据目前的矩阵R(5,6)如何得到分值为0的用户的打分值?
矩阵分解的思想可以解决这个问题,其实这种思想可以看作是有监督的机器学习问题
具体的:
R(n,m)~=P(n,K)*Q(K,m)
其中 ~=表示约等于(由于编辑器使用的不熟悉),矩阵P(n,K)表示n个user和K个特征之间的关系矩阵,这K个特征是一个中间变量,矩阵Q(K,m)的转置是矩阵Q(m,K),矩阵Q(m,K)表示m个item和K个特征之间的关系矩阵,这里的K值是自己控制的,可以使用交叉验证的方法获得最佳的K值。为了得到近似的R(n,m),必须求出矩阵P和Q,怎么求它们呢?
令
如果R(i,j)已知,则R(i,j)的误差平方和为
为了防止过拟合,增加正则化项:
使用梯度下降法获得修正的p和q分量:
纠错:中间等式前面的alph前面应该是负号,代表负梯度方向
纠错:中间等式前面的alph前面应该是负号,代表负梯度方向
不停的迭代直到sum(e^2) <=阈值,
K=2 得到结果是
item1 item2 item4 item5item6 item7
user1 [[ 5.25600533 4.30482789 4.76151949 2.04197028 3.77745497 1.59709987]
user5 [ 0.94314043 2.66249238 3.23566396 4.36964834 -0.91695287 5.33276304]]
K=3 得到结果是
item1 item2 item4 item5item6 item7
user1 [[ 5.35081468 4.21628989 3.92966236 2.8616707 4.42764467 3.67424467]
user2 [ 3.65150782 4.00536042 4.98203391 -0.24263616 2.84660098 1.11289902]
user3 [ 4.55129228 3.73496981 3.86823535 1.11434568 3.71657794 2.03034916]
user4 [ 1.57844524 3.97142414 5.03277248 3.35320963 1.08371548 4.62480722]
user5 [ 0.93799194 2.70958606 2.97752303 4.67356409 0.67601902 5.28834503]]
python 源代码如下:
import numpy def matrix_factorization(R, P, Q, K, steps=5000, alpha=0.0002, beta=0.02): Q = Q.T for step in xrange(steps): for i in xrange(len(R)): for j in xrange(len(R[i])): if R[i][j] > 0: eij = R[i][j] - numpy.dot(P[i,:],Q[:,j]) for k in xrange(K): P[i][k] = P[i][k] + alpha * (2 * eij * Q[k][j] - beta * P[i][k]) Q[k][j] = Q[k][j] + alpha * (2 * eij * P[i][k] - beta * Q[k][j]) eR = numpy.dot(P,Q) e = 0 for i in xrange(len(R)): for j in xrange(len(R[i])): if R[i][j] > 0: e = e + pow(R[i][j] - numpy.dot(P[i,:],Q[:,j]), 2) for k in xrange(K): e = e + (beta/2) * ( pow(P[i][k],2) + pow(Q[k][j],2) ) if e < 0.001: break return P, Q.T ############################################################################### if __name__ == "__main__": R = [ [5,4,4,3,5,0], [0,4,5,0,3,1], [5,4,0,1,3,0], [0,4,5,3,1,5], [1,0,3,5,0,5], ] R = numpy.array(R) N = len(R) M = len(R[0]) K = 2 P = numpy.random.rand(N,K) Q = numpy.random.rand(M,K) nP, nQ = matrix_factorization(R, P, Q, K) print R T = numpy.dot(nP,nQ.T) print T
参考文章:http://www.quuxlabs.com/blog/2010/09/matrix-factorization-a-simple-tutorial-and-implementation-in-python/#source-code
adding biases
然而,上面仅仅考虑了q和p直接相互影响,而没有考虑user和item项目本身的属性,比如,总体的平均分是all_mean,
user是一位严厉的顾客,那么打分自然要低于打分的平均分,一个item比其他item更流行,其得分高于打分的
平均分,则:r_exp(u,i) = u + b(i) + b(u) + q(i)p(u)
其中 u是所有打过分的打分item的打分的平均值,b(i)为item比平均值的偏差,b(u)表示个人打分习惯和
平均打分的偏差
优化目标函数是:
min ∑ (r(u,i) - all_mean - b(u) - b(i) - p(u)q(i))^2 + lamda*(||p(u)||^2 + ||q(i)||^2 + (b(u))^2 + (b(i))^2)
参考文章:matrix factorization techniques for recommender systems
该源代码在我的github,https://github.com/zhangqianjin/recommender-system/ ,欢迎大家交流学习