鱼C论坛

 找回密码
 立即注册
查看: 1693|回复: 1

[技术交流] Python实现SVD

[复制链接]
发表于 2020-11-19 21:18:34 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
参考书籍:《机器学习实战》

import numpy as np
from numpy import linalg as la

def loadExData():
    return[[0, 0, 0, 2, 2],
           [0, 0, 0, 3, 3],
           [0, 0, 0, 1, 1],
           [1, 1, 1, 0, 0],
           [2, 2, 2, 0, 0],
           [5, 5, 5, 0, 0],
           [1, 1, 1, 0, 0]]
    
def loadExData2():
    return[[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],
           [0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
           [0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
           [3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
           [5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
           [0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
           [4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
           [0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
           [0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2],
           [0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0],
           [1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]]

def eulidSim(inA, inB): #欧式距离
    return 1 / (1 + la.norm(inA - inB))

def pearsSim(inA, inB):
    if len(inA) < 3:
        return 1#??
    return 1 / (1 + la.norm(inA - inB))

def cosSim(inA, inB):
    num = float(inA.T * inB)
    denom = la.norm(inA) * la.norm(inB)
    return 0.5 + 0.5*(num / denom)

#基于物品相似度的推荐系统
def standEst(dataMat, user, simMeas, item):
    n = np.shape(dataMat)[1]
    simTotal = 0
    ratSimTotal = 0
    for j in range(n):
        userRating = dataMat[user, j]
        if userRating == 0 or j==item:
            continue
        #https://blog.csdn.net/jningwei/article/details/78651535
        overLap = np.nonzero(np.logical_and(dataMat[:, item] > 0, 
                                         dataMat[:, j] > 0))[0]#必须都有评分记录
        if len(overLap) == 0:
            similarity = 0
        else:
            similarity = simMeas(dataMat[overLap, item],
                                 dataMat[overLap, j])
            simTotal += similarity
            ratSimTotal += similarity * userRating
    if simTotal == 0:
        return 0
    return ratSimTotal / simTotal

def svdEst(dataMat, user, simMeas, item):
    n = np.shape(dataMat)[1]
    simTotal = 0.0; ratSimTotal = 0.0
    U,Sigma,VT = la.svd(dataMat)
    Sig4 = np.mat(np.eye(4)*Sigma[:4]) 
    xformedItems = dataMat.T * U[:,:4] * Sig4.I 
    for j in range(n):
        userRating = dataMat[user,j]
        if userRating == 0 or j==item: 
            continue
        similarity = simMeas(xformedItems[item,:].T,\
                             xformedItems[j,:].T)
        simTotal += similarity
        ratSimTotal += similarity * userRating
    if simTotal == 0: 
        return 0
    return ratSimTotal/simTotal
    
    
def recommend(dataMat, user, N = 3, simMeas = cosSim, estMethod = standEst):
    unratedItems = np.nonzero(dataMat[user,:] == 0)[1]
    if len(unratedItems) == 0: 
        return 'you rated everything'
    itemScores = []
    for item in unratedItems:
        estimatedScore = estMethod(dataMat, user, simMeas, item)
        itemScores.append((item, estimatedScore))
    return sorted(itemScores, key = lambda jj: jj[1], reverse = True)[:N]
 

if __name__ == '__main__':
       myMat = np.mat(loadExData())
       myMat[0, 1] = myMat[0, 0] = myMat[1, 0] = myMat[2, 0] = 4
       myMat[3, 3] = 2
       res1 = recommend(myMat, 2)
       res2 =recommend(myMat, 2, estMethod = svdEst)

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-11-19 21:19:12 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 15:25

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表