機器學習Python實現 SVD 分解


這篇文章主要是結合機器學習實戰將推薦算法和SVD進行對應的結合

不論什么一個矩陣都能夠分解為SVD的形式

事實上SVD意義就是利用特征空間的轉換進行數據的映射,后面將專門介紹SVD的基礎概念。先給出python,這里先給出一個簡單的矩陣。表示用戶和物品之間的關系

這里我自己有個疑惑?

對這樣一個DATA = U(Z)Vt 

這里的U和V真正的幾何含義  :  書上的含義是U將物品映射到了新的特征空間, V的轉置  將 用戶映射到了新的特征空間


以下是代碼實現。同一時候SVD還能夠用於降維,降維的操作就是通過保留值比較的神秘值

# -*- coding: cp936 -*-
'''
Created on Mar 8, 2011

@author: Peter
'''
from numpy import *
from numpy import linalg as la #用到別名

#這里主要結合推薦系統介紹SVD,所以這里的數據都能夠看成是用戶對物品的一個打分
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 ecludSim(inA,inB):
    return 1.0/(1.0 + la.norm(inA - inB))  #計算向量的第二范式,相當於直接計算了歐式距離

def pearsSim(inA,inB):
    if len(inA) < 3 : return 1.0
    return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1] #corrcoef直接計算皮爾遜相關系數

def cosSim(inA,inB):
    num = float(inA.T*inB)
    denom = la.norm(inA)*la.norm(inB)
    return 0.5+0.5*(num/denom)  #計算余弦類似度

#協同過濾算法
#dataMat 用戶數據 user 用戶 simMeas 類似度計算方式 item 物品
def standEst(dataMat, user, simMeas, item): 
    n = shape(dataMat)[1] #計算列的數量,物品的數量
    simTotal = 0.0; ratSimTotal = 0.0 
    for j in range(n):
        userRating = dataMat[user,j]
        print(dataMat[user,j])
        if userRating == 0: continue  #假設用戶u沒有對物品j進行打分。那么這個推斷就能夠跳過了
        overLap = nonzero(logical_and(dataMat[:,item].A>0, \
                                      dataMat[:,j].A>0))[0]    #找到對物品 j 和item都打過分的用戶
        if len(overLap) == 0: similarity = 0
        else: similarity = simMeas(dataMat[overLap,item], dataMat[overLap,j])     #利用類似度計算兩個物品之間的類似度
                                   
        print 'the %d and %d similarity is: %f' % (item, j, similarity)
        simTotal += similarity
        ratSimTotal += similarity * userRating  #待推薦物品與用戶打過分的物品之間的類似度*用戶對物品的打分
    if simTotal == 0: return 0
    else: return ratSimTotal/simTotal


#利用SVD進行分解,可是這里是直接用的庫里面的函數
    #假設自己實現一個SVD分解。我想就是和矩陣論里面的求解知識是一樣的吧,可是可能在求特征值的過程中會比較痛苦
def svdEst(dataMat, user, simMeas, item):
    n = shape(dataMat)[1]
    simTotal = 0.0; ratSimTotal = 0.0
    U,Sigma,VT = la.svd(dataMat) #直接進行分解
    Sig4 = mat(eye(4)*Sigma[:4]) #arrange Sig4 into a diagonal matrix
    xformedItems = dataMat.T * U[:,:4] * Sig4.I  #create transformed items
    for j in range(n):
        userRating = dataMat[user,j]
        if userRating == 0 or j==item: continue
        similarity = simMeas(xformedItems[item,:].T,\
                             xformedItems[j,:].T)
        print 'the %d and %d similarity is: %f' % (item, j, similarity)
        simTotal += similarity
        ratSimTotal += similarity * userRating
    if simTotal == 0: return 0
    else: return ratSimTotal/simTotal

#真正的推薦函數,后面兩個函數就是採用的類似度的計算方法和推薦用的方法
def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=standEst):
    unratedItems = nonzero(dataMat[user,:].A==0)[1]  #find unrated items  nonzero()[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]


#擴展的樣例。利用SVD進行圖像的壓縮
#將圖像打印出來
def printMat(inMat, thresh=0.8):
    for i in range(32):
        for k in range(32):
            if float(inMat[i,k]) > thresh:
                print 1,
            else: print 0,
        print ''



#最后發現重構出來的數據圖是差點兒相同的
def imgCompress(numSV=3, thresh=0.8):
    myl = []
    for line in open('0_5.txt').readlines():
        newRow = []
        for i in range(32):
            newRow.append(int(line[i]))
        myl.append(newRow)
    myMat = mat(myl)   #將數據讀入了myMat其中
    
    print "****original matrix******"
    printMat(myMat, thresh)
    U,Sigma,VT = la.svd(myMat)
    SigRecon = mat(zeros((numSV, numSV)))   #構建一個3*3的空矩陣
    for k in range(numSV):#construct diagonal matrix from vector
        SigRecon[k,k] = Sigma[k]
    reconMat = U[:,:numSV]*SigRecon*VT[:numSV,:]
    print "****reconstructed matrix using %d singular values******" % numSV
    printMat(reconMat, thresh)

通過結果能夠看到,降維前和降維后的圖片基本都是相似的



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM