,为实际值与预测值之间的误差。
按照随机梯度下降算法,我们分别更新,:
通过前面一些列操作后,可以得到分解后的两个子矩阵P,Q,两个子矩阵相乘就可得物品用户评分矩阵,有个这个物品用户评分矩阵就可以给用户推荐评分较高的物品了。
Func-svd矩阵分解算法流程流程如下:
随机生成一个稀疏的物品用户评分矩阵
初始化分解后的子矩阵
计算预测分数与实际分数之差
按照上述参数更新公式同步更新子矩阵中的元素值
迭代重复步骤3,4,直至迭代次数执行完毕。
python代码实现1 import numpy as np 2 import scipy as spy 3 import scipy.sparse 4 import heapq 5 6 # 构造一个稀疏的50 * 100物品用户评分矩阵 7 # 随机生成120个坐标,行坐标取值范围为[0,50),列坐标取值范围为[0,100),生成的非零元素占总数的24%,非零元素取值范围为1,2,3,4,5 8 # 行对应物品,列对应用户 9 row_num = 50 10 col_num = 100 11 nonzero_percent = 0.24 12 nonzero_num = int(row_num * col_num * nonzero_percent) 13 14 row = np.random.randint(0,row_num,size=nonzero_num) 15 col = np.random.randint(0,col_num,size=nonzero_num) 16 data = np.random.randint(1,6,size=nonzero_num) 17 sparse_matrix = spy.sparse.coo_matrix((data, (row,col)), shape=(row_num,col_num)) 18 sparse_matrix = sparse_matrix.toarray() 19 20 # 隐因子特征个数 21 k = 4 22 # 子矩阵 23 item_feature_matrix = np.random.rand(row_num, k) 24 user_feature_matrix = np.random.rand(col_num, k) 25 # 迭代次数 26 step = 100 27 # 学习率 28 alpha = 0.00005 29 # 正则化系数 30 lamda = 0.0001 31 # 迭代学习 32 for s in range(0, step): 33 err_square_sum = 0.0 34 for r in range(0, row_num): 35 for c in range(0, col_num): 36 # 计算预测的分数,(r,c) 37 predict = np.dot(item_feature_matrix[r], user_feature_matrix[c]) 38 # 计算实际值与预测值之差 39 err = float(sparse_matrix[r][c]) - predict 40 err_square_sum = err_square_sum + err*err 41 # 更新物品的隐因子向量, 可以把k个参数的更新合并为向量形式处理 42 item_feature_matrix_tmp = item_feature_matrix[r] + 2 * alpha * (user_feature_matrix[c] * err - lamda * item_feature_matrix[r]) 43 # 更新用户的隐因子向量, 可以把k个参数的更新合并为向量形式处理 44 user_feature_matrix_tmp = user_feature_matrix[c] +2*alpha*(item_feature_matrix[r] * err - lamda * user_feature_matrix[c]) 45 item_feature_matrix[r] = item_feature_matrix_tmp 46 user_feature_matrix[c] = user_feature_matrix_tmp 47 #print(\'step[{}] err_square_sum:{}, err_square_sum_sqrt:{}\'.format(s, err_square_sum, np.sqrt(err_square_sum))) 48 print(\'item_feature_matrix:\n{}\'.format(item_feature_matrix)) 49 print(\'user_feature_matrix:\n{}\'.format(user_feature_matrix)) 50 51 # 两个分解后的子矩阵相乘,得到拟合的物品用户评分矩阵 52 result_matrix = np.dot(item_feature_matrix, user_feature_matrix.T) 53 54 # 得到拟合的物品用户评分矩阵后就可以给用户推荐评分最高的k个物品了 55 topK = 5 56 for col in range(0, col_num): 57 # 每个用户已经有过正面行为的物品索引 58 col_nonzero = list(np.nonzero(sparse_matrix[:,col])[0]) 59 60 # 拟合的物品用户评分矩阵中的用户列,按照分数从大到小给对应的物品索引排序 61 result_col = list(result_matrix[:, col]) 62 result_col_list = list(map(result_col.index, heapq.nlargest(len(result_col), result_col))) 63 result_sorted = list(set(result_col_list) - set(col_nonzero)) 64 65 # 由于set会排序,所以让result_sorted按照result_col_list中元素出现的顺序排序一次 66 result_sorted.sort(key = result_col_list.index) 67 print(\'user[{}] recomm top{} item index{}.\'.format(col, topK, result_sorted[0:topK]))