基于矩阵分解的推荐系统

基于矩阵分解的推荐算法

1、概述

   基于用户和基于项的协同过滤推荐算法,难以实现大数据量下的实时推荐。这时我们可以使用基于模型的协同过滤算法,矩阵分解(Matrix Factorization,MF)就是其中一种。
   矩阵分解:将一个矩阵分解为两个或多个矩阵的乘积。mxn—>mxk X kxn
   非负矩阵分解:一般的矩阵分解,分解的矩阵有正有负。很多实际应用中,负数没有意义,如文本等等。NMF中要求原矩阵和分解后矩阵都为非负矩阵,这个分解存在唯一。
   基于模型的协同过滤算法:(1)建立模型;(2)利用训练好的模型进行推荐。
   基于矩阵分解的推荐算法:(1)对用户商品矩阵分解;(2)利用分解后的矩阵预测原始矩阵中的未打分项。

2、基于矩阵分解的推荐算法

   损失函数:将原始评分矩阵Rmxn分解后得到两个矩阵的乘积,这两个矩阵的乘积构建了新的评分矩阵,将非“-”元素,在原始和新的之间的误差的平方作为损失,我们需要求解所有非“-”项的损失之和的最小值。通常会加入正则化项。
   损失函数求解:可使用梯度下降方法,求损失函数的负梯度,根据负梯度的方向更新变量(也就是分解后的各个矩阵的对应位置的元素)。目的是求得分解后的矩阵。
   预测:得到分解的矩阵后,模型便建立好了。要为指定的用户i推荐其未打分的项,若要计算用户i对商品j的打分,k为分解矩阵的维度,。求得多个商品的打分后,进行降序排序。
在这里插入图片描述

3、利用矩阵分解进行推荐

   首先导入数据并矩阵化;
   然后利用梯度下降对矩阵分解得到模型(需要设置分解矩阵的维度k,学习率alpha,正则化参数beta,最大迭代次数maxCycles),输出分解后的矩阵p和q。
   预测时,利用得到的分解矩阵p和q和前面的公式,可得到某用户user所有未打分商品的打分,然后排序输出。

# coding:UTF-8
import numpy as np

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))
        data.append(arr)
    f.close()
    return np.mat(data)

def gradAscent(dataMat, k, alpha, beta, maxCycles):#利用梯度下降法对矩阵进行分解
    m, n = np.shape(dataMat)
    # 1、初始化p和q
    p = np.mat(np.random.random((m, k)))
    q = np.mat(np.random.random((k, n)))
    for step in range(maxCycles):
        for i in range(m):
            for j in range(n):
                if dataMat[i, j] > 0:
                    error = dataMat[i, j]
                    for r in range(k):
                        error = error - p[i, r] * q[r, j]
                    for r in range(k):
                        p[i, r] = p[i, r] + alpha * (2 * error * q[r, j] - beta * p[i, r])
                        q[r, j] = q[r, j] + alpha * (2 * error * p[i, r] - beta * q[r, j])
        loss = 0.0
        for i in range(m):
            for j in range(n):
                if dataMat[i, j] > 0:
                    error = 0.0
                    for r in range(k):
                        error = error + p[i, r] * q[r, j]
                    loss = (dataMat[i, j] - error) * (dataMat[i, j] - error)
                    for r in range(k):
                        loss = loss + beta * (p[i, r] * p[i, r] + q[r, j] * q[r, j]) / 2
        if loss < 0.001:
            break
        if step % 1000 == 0:
            print("\titer: ", step, " loss: ", loss)
    return p, q


def save_file(file_name, source):#保存结果
    f = open(file_name, "w")
    m, n = np.shape(source)
    for i in range(m):
        tmp = []
        for j in range(n):
            tmp.append(str(source[i, j]))
        f.write("\t".join(tmp) + "\n")
    f.close()

def prediction(dataMatrix, p, q, user):#为用户user未互动的项打分
    n = np.shape(dataMatrix)[1]
    predict = {}
    for j in range(n):
        if dataMatrix[user, j] == 0:
            predict[j] = (p[user,] * q[:, j])[0, 0]
    return sorted(predict.items(), key=lambda d: d[1], reverse=True)


def top_k(predict, k):#为用户推荐前k个商品
    top_recom = []
    len_result = len(predict)
    if k >= len_result:
        top_recom = predict
    else:
        for i in range(k):
            top_recom.append(predict[i])
    return top_recom


if __name__ == "__main__":
    # 1、导入用户商品矩阵
    print("----------- 1、load data -----------")
    dataMatrix = load_data("data.txt")
    # 2、利用梯度下降法对矩阵进行分解
    print("----------- 2、training -----------")
    p, q = gradAscent(dataMatrix, 5, 0.0002, 0.02, 5000)
    # 3、保存分解后的结果
    print("----------- 3、save decompose -----------")
    save_file("p", p)
    save_file("q", q)
    # 4、预测
    print("----------- 4、prediction -----------")
    predict = prediction(dataMatrix, p, q, 0)
    # 进行Top-K推荐
    print("----------- 5、top_k recommendation ------------")
    top_recom = top_k(predict, 2)
    print(top_recom)
    print(p * q)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值