基于矩阵分解的推荐系统算法

作者 zhan-bin 日期 2018-10-14
基于矩阵分解的推荐系统算法

基于矩阵分解的推荐系统算法

概述

 基于矩阵分解的推荐系统是属于隐语义分析模型的其中一种,矩阵分解的推荐系统的原理是将原始的矩阵进行分解,再使用分解之后的两个矩阵填充原始矩阵的没有值的部分。
 我们这里将原始矩阵分解成(假设原始矩阵为Rm*n)可以将其分解成两个矩阵Pm*k、Qk*n的乘积:Rm*n≈Pm*k*Qk*n

矩阵分解

这里使用机器学习的梯度下降来进行系数矩阵的分解

构建损失函数

  • 我们使用原始评分矩阵和生成的矩阵的误差的平方作为损失函数即:
    f1

  • 再加入正则项:
    f2

  • 求解函数的负梯度:
    f3

  • 迭代更新变量:
    f4

  • 最后是预测,基于误差范围内求出来的两个分解出来的矩阵对原始矩阵进行还原
    f5

Python实现

 我们这里举个简单的例子:假如有如下的一个用户对商品评分的矩阵

V1 V2 V3 V4
Uesr1 5 3 - 1
Uesr2 4 - - 1
Uesr3 1 1 - 5
Uesr4 1 - - 4
Uesr5 - 1 5 4
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from numpy import *

def load_data(path):
f = open(path)
data = []
for line in f.readlines():
arr = []
lines = line.strip().split("\t")
for x in lines:
if x != "-":
arr.append(float(x))
else:
arr.append(float(0))
#print arr
data.append(arr)
#print data
return data

def gradAscent(data, K):
dataMat = mat(data)
print (dataMat)
m, n = shape(dataMat)
p = mat(random.random((m, K)))
q = mat(random.random((K, n)))

alpha = 0.0002
beta = 0.02
maxCycles = 10000

for step in range(maxCycles):
for i in range(m):
for j in range(n):
if dataMat[i,j] > 0:
#print dataMat[i,j]
error = dataMat[i,j]
for k in range(K):
error = error - p[i,k]*q[k,j]
for k in range(K):
p[i,k] = p[i,k] + alpha * (2 * error * q[k,j] - beta * p[i,k])
q[k,j] = q[k,j] + alpha * (2 * error * p[i,k] - beta * q[k,j])

loss = 0.0
for i in range(m):
for j in range(n):
if dataMat[i,j] > 0:
error = 0.0
for k in range(K):
error = error + p[i,k]*q[k,j]
loss = (dataMat[i,j] - error) * (dataMat[i,j] - error)
for k in range(K):
loss = loss + beta * (p[i,k] * p[i,k] + q[k,j] * q[k,j]) / 2

if loss < 0.001:
break
#print step
if step % 1000 == 0:
print (loss)

return p, q


if __name__ == "__main__":
dataMatrix = load_data("F:/input.txt")

p, q = gradAscent(dataMatrix, 5)
'''
p = mat(ones((4,10)))
print p
q = mat(ones((10,5)))
'''
result = p * q
#print p
#print q

print (result)

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[[5. 3. 0. 1.]
[4. 0. 0. 1.]
[1. 1. 0. 5.]
[1. 0. 0. 4.]
[0. 1. 5. 4.]]
8.742933118715158
0.2989495531365295
0.12694735634549725
0.0958637440582054
0.09099080849799192
0.08993263642716288
0.08955828202437822
0.08933543010584674
0.08915629239987193
0.08899474524490007
[[4.97695113 2.98341579 3.58483937 1.00231939]
[3.98113924 1.87797282 3.1003623 1.0004422 ]
[1.00360559 0.99132198 5.32185081 4.97024019]
[0.9982741 0.69295102 4.30688594 3.9832334 ]
[2.05423192 1.00865589 4.98318823 3.99242423]]

Process finished with exit code 0