详细的理论解释和Java实现参考: 附上详细的理论解释和Java实现LTA_ALBlack的博客
在多标签学习中,标签矩阵Y,存在标签缺失情况,利用Funk-SVD,将矩阵Y 分解为矩阵U 和V ,使得满足 Y = U * V,即可将确失标签补充。具体步骤如下:
1、随机初始化 U、V。
2、确定包含正则化的损失函数。
3、对损失函数求导,利用梯度下降法,更新U、V。
4、循环步骤3,直到损失函数小于某个值为止。
from math import *
import numpy as np
import matplotlib.pyplot as plt
def matrix_factorization(Y, rank, aplha, beta, steps):
'''
:param Y: label matrix m*n
:param U: 对象向隐含标签的映射 m*k
:param V: 标签向隐含标签的映射 m*k
:param K: 隐向量的维度
:param aplha: 学习率
:param beta: 正则化参数
:param steps:
:return:
'''
print('开始分解原矩阵:\n')
Y = np.array(Y)
# Number of rows of label matrix Y
rows_Y = len(Y)
# Number of columns of label matrix Y
columns_Y = len(Y[0]) # 原矩阵R的列数
# Random initialization matrix. [0 1]
U = np.random.rand(rows_Y, rank)
V = np.random.rand(columns_Y, rank)
# Transpose
V = V . T
result=[]
# update parameters using gradient descent method
print('开始训练: \n')
for step in range(steps):
for i in range(len(Y)):
for j in range(len(Y[0])):
eij=Y[i][j]-np.dot(U[i,:],V[:,j])
for k in range(rank):
if Y[i][j]>0:
# update parameters
U[i][k]=U[i][k]+aplha*(2*eij*V[k][j]-beta*U[i][k])
V[k][j]=V[k][j]+aplha*(2*eij*U[i][k]-beta*V[k][j])
# loss
e=0
for i in range(len(Y)):
for j in range(len(Y[i])):
if Y[i][j] > 0:
e = e + pow(Y[i][j] - np.dot(U[i, :], V[:, j]), 2) # loss
for k in range(rank):
e = e + (beta / 2) * (pow(U[i][k], 2) + pow(V[k][j], 2)) # loss with regularization
result.append(e)
if e < 0.001:
break
print('training Finshed 。。。。')
return U, V.T, result
if __name__ == '__main__': #主函数
Y=[ #原始矩阵
[5,3,0,1],
[4,0,0,1],
[1,1,0,5],
[1,0,0,4],
[0,1,5,4]
]
Y=np.array(Y)
U,V,result=matrix_factorization(Y, 3, aplha=0.0002,beta=0.02,steps=5000)
# show the result
print(result)
print('原矩阵',Y)
Y_MF=np.dot(U,V.T)
print('计算出的矩阵',Y_MF)
# display the results with a chart
plt.plot(range(len(result)),result)
plt.xlabel("time")
plt.ylabel("loss")
plt.show()