機器學習 推薦系統_推薦系統

來源:互聯網
上載者:User

一.推薦系統的總體架構


1.1選取使用者偏好


二.開源的推薦系統

2.1協同過濾及其演算法

(1)資料預先處理與UI矩陣:分組為"查看"和"購買",對資料進行一定的預先處理,減噪和歸一化

(2)推薦模型:User CF和Item CF:基於物品的協同過濾(Amason,Netfix,Hulu,YouTube等採用)這裡使用kNN近鄰演算法。

(1)User CF

# -*- coding: utf-8 -*-from numpy import *import numpy as npfrom Recommand_Lib import kNNdataMat=mat([[0.238,0,0.1905,0.1905,0.1905,0.1905],[0,0.177,0,0.294,0.235,0.294],[0.2,0.16,0.12,0.12,0.2,0.2]])testSet = [0.2174,0.2174,0.1304,0,0.2174,0.2174]classLabel = np.array(['B','C','D'])print kNN(testSet,dataMat,classLabel,3)
(1) Item  CF

# -*- coding: utf-8 -*-from numpy import *import numpy as npfrom Recommand_Lib import kNNdataMat=mat([[0.417,0.0,0.25,0.333],[0.3,0.4,0.0,0.3],[0.0,0.0,0.625,0.375],[0.278,0.222,0.222,0.278],[0.263,0.211,0.263,0.263]])testSet = [0.334,0.333,0.0,0.333]classLabel = np.array(['B','C','D','E','F'])print kNN(testSet,dataMat,classLabel,3)

運行結果一樣:



(3)KMeans (Scikit-Learn庫中)聚類演算法計算相似性:縮減計算量的方法,最優的選擇就是對資料進行聚類。演算法簡單實現代碼如下:

# -*- coding: utf-8 -*-# Filename : 02kMeans1.pyimport timeimport numpy as npfrom Recommand_Lib import *from sklearn.cluster import KMeansimport matplotlib.pyplot as plt k = 4dataSet = file2matrix("testData/4k2_far.txt","\t")  dataMat = mat(dataSet[:,1:]) # 轉換為矩陣形式kmeans = KMeans(init='k-means++', n_clusters=4)kmeans.fit(dataMat)# 輸出產生的ClustDist:對應的聚類中心(列1),到聚類中心的距離(列2),行與dataSet一一對應drawScatter(plt,dataMat,size=20,color='b',mrkr='.')# 繪製聚類中心drawScatter(plt,kmeans.cluster_centers_,size=60,color='red',mrkr='D')plt.show() 
運行結果如下:


聚類的演算法改進:二分KMeans 演算法:

# -*- coding: utf-8 -*-# Filename : 02kMeans1.pyfrom numpy import *import numpy as npfrom Recommand_Lib import *import matplotlib.pyplot as plt # 從檔案構建的資料集    dataMat = file2matrix("testData/4k2_far.txt","\t")  dataSet = mat(dataMat[:,1:]) # 轉換為矩陣形式 k = 4 # 分類數m = shape(dataSet)[0]# 初始化第一個聚類中心: 每一列的均值centroid0 = mean(dataSet, axis=0).tolist()[0] centList =[centroid0] # 把均值聚類中心加入中心表中# 初始化聚類距離表,距離方差: ClustDist = mat(zeros((m,2)))for j in range(m):ClustDist[j,1] = distEclud(centroid0,dataSet[j,:])**2 # 依次產生k個聚類中心while (len(centList) < k):    lowestSSE = inf # 初始化最小誤差平方和。核心參數,這個值越小就說明聚類的效果越好。    # 遍曆cenList的每個向量    #----1. 使用ClustDist計算lowestSSE,以此確定:bestCentToSplit、bestNewCents、bestClustAss----#    for i in xrange(len(centList)):        ptsInCurrCluster = dataSet[nonzero(ClustDist[:,0].A==i)[0],:]        # 應用標準kMeans演算法(k=2),將ptsInCurrCluster劃分出兩個聚類中心,以及對應的聚類距離表        centroidMat,splitClustAss = kMeans(ptsInCurrCluster, 2)        # 計算splitClustAss的距離平方和        sseSplit = sum(splitClustAss[:,1])        # 計算ClustDist[ClustDist第1列!=i的距離平方和        sseNotSplit = sum(ClustDist[nonzero(ClustDist[:,0].A!=i)[0],1])        if (sseSplit + sseNotSplit) < lowestSSE: # 演算法公式: lowestSSE = sseSplit + sseNotSplit            bestCentToSplit = i                 # 確定聚類中心的最優分隔點             bestNewCents = centroidMat          # 用新的聚類中心更新最優聚類中心            bestClustAss = splitClustAss.copy() # 深拷貝聚類距離表為最優聚類距離表            lowestSSE = sseSplit + sseNotSplit  # 更新lowestSSE           # 回到外迴圈    #----2. 計算新的ClustDist----#    # 計算bestClustAss 分了兩部分:    # 第一部分為bestClustAss[bIndx0,0]賦值為聚類中心的索引         bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList)    # 第二部分 用最優分隔點的指定聚類中心索引      bestClustAss[nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit    # 以上為計算bestClustAss    # 更新ClustDist對應最優分隔點下標的距離,使距離值等於最優聚類距離對應的值    #以上為計算ClustDist        #----3. 用最優分隔點來重構聚類中心----#    # 覆蓋: bestNewCents[0,:].tolist()[0]附加到原有聚類中心的bestCentToSplit位置    # 增加: 聚類中心增加一個新的bestNewCents[1,:].tolist()[0]向量    centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]    centList.append(bestNewCents[1,:].tolist()[0])     ClustDist[nonzero(ClustDist[:,0].A == bestCentToSplit)[0],:]= bestClustAss     # 以上為計算centListcolor_cluster(ClustDist[:,0:1],dataSet,plt)print "cenList:",mat(centList)# print "ClustDist:", ClustDist# 繪製聚類中心圖形drawScatter(plt,mat(centList),size=60,color='red',mrkr='D')plt.show()# -*- coding: utf-8 -*-# Filename : 02kMeans1.pyfrom numpy import *import numpy as npfrom Recommand_Lib import *import matplotlib.pyplot as plt # 從檔案構建的資料集    dataMat = file2matrix("testData/4k2_far.txt","\t")  dataSet = mat(dataMat[:,1:]) # 轉換為矩陣形式 k = 4 # 分類數m = shape(dataSet)[0]# 初始化第一個聚類中心: 每一列的均值centroid0 = mean(dataSet, axis=0).tolist()[0] centList =[centroid0] # 把均值聚類中心加入中心表中# 初始化聚類距離表,距離方差: ClustDist = mat(zeros((m,2)))for j in range(m):ClustDist[j,1] = distEclud(centroid0,dataSet[j,:])**2 # 依次產生k個聚類中心while (len(centList) < k):    lowestSSE = inf # 初始化最小誤差平方和。核心參數,這個值越小就說明聚類的效果越好。    # 遍曆cenList的每個向量    #----1. 使用ClustDist計算lowestSSE,以此確定:bestCentToSplit、bestNewCents、bestClustAss----#    for i in xrange(len(centList)):        ptsInCurrCluster = dataSet[nonzero(ClustDist[:,0].A==i)[0],:]        # 應用標準kMeans演算法(k=2),將ptsInCurrCluster劃分出兩個聚類中心,以及對應的聚類距離表        centroidMat,splitClustAss = kMeans(ptsInCurrCluster, 2)        # 計算splitClustAss的距離平方和        sseSplit = sum(splitClustAss[:,1])        # 計算ClustDist[ClustDist第1列!=i的距離平方和        sseNotSplit = sum(ClustDist[nonzero(ClustDist[:,0].A!=i)[0],1])        if (sseSplit + sseNotSplit) < lowestSSE: # 演算法公式: lowestSSE = sseSplit + sseNotSplit            bestCentToSplit = i                 # 確定聚類中心的最優分隔點             bestNewCents = centroidMat          # 用新的聚類中心更新最優聚類中心            bestClustAss = splitClustAss.copy() # 深拷貝聚類距離表為最優聚類距離表            lowestSSE = sseSplit + sseNotSplit  # 更新lowestSSE           # 回到外迴圈    #----2. 計算新的ClustDist----#    # 計算bestClustAss 分了兩部分:    # 第一部分為bestClustAss[bIndx0,0]賦值為聚類中心的索引         bestClustAss[nonzero(bestClustAss[:,0].A == 1)[0],0] = len(centList)    # 第二部分 用最優分隔點的指定聚類中心索引      bestClustAss[nonzero(bestClustAss[:,0].A == 0)[0],0] = bestCentToSplit    # 以上為計算bestClustAss    # 更新ClustDist對應最優分隔點下標的距離,使距離值等於最優聚類距離對應的值    #以上為計算ClustDist        #----3. 用最優分隔點來重構聚類中心----#    # 覆蓋: bestNewCents[0,:].tolist()[0]附加到原有聚類中心的bestCentToSplit位置    # 增加: 聚類中心增加一個新的bestNewCents[1,:].tolist()[0]向量    centList[bestCentToSplit] = bestNewCents[0,:].tolist()[0]    centList.append(bestNewCents[1,:].tolist()[0])     ClustDist[nonzero(ClustDist[:,0].A == bestCentToSplit)[0],:]= bestClustAss     # 以上為計算centListcolor_cluster(ClustDist[:,0:1],dataSet,plt)print "cenList:",mat(centList)# print "ClustDist:", ClustDist# 繪製聚類中心圖形drawScatter(plt,mat(centList),size=60,color='red',mrkr='D')plt.show()
演算法運行結果:



(4)SVD (隱語義模型:奇異值分解)計算相似性

# -*- coding: utf-8 -*-# Filename : svdRec2.py'''Created on Mar 8, 2011@author: Peter'''from numpy import *from numpy import linalg as ladef 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 loadReData():    return[[4, 4, 0, 2, 2],           [4, 0, 0, 3, 3],           [4, 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]]# 歐氏距離:# 二維空間的歐氏距離公式:sqrt((x1-x2)^2+(y1-y2)^2)def ecludSim(inA,inB):    return 1.0/(1.0 + la.norm(inA - inB))# 皮爾遜相似性:corrcoef相關係數:衡量X與Y線性相關程度,其絕對值越大,則表明X與Y相關度越高。# E((X-EX)(Y-EY))/sqrt(D(X)D(Y))def pearsSim(inA,inB):    if len(inA) < 3 : return 1.0    return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1]# 夾角餘弦:計算空間內兩點之間的夾角餘弦# 兩個n維樣本點a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夾角餘弦# cos(theta) = a*b/(|a|*|b|)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 = shape(dataMat)[1] # 列數    simTotal = 0.0; ratSimTotal = 0.0    for j in range(n):        userRating = dataMat[user,j] # 資料集第user行第j列的元素值        if userRating == 0: continue # 跳過未評估項目        # logical_and:矩陣逐個元素運行邏輯與,傳回值為每個元素的True,False        # dataMat[:,item].A>0: 第item列中大於0的元素        # dataMat[:,j].A: 第j列中大於0的元素        # overLap: dataMat[:,item],dataMat[:,j]中同時都大於0的那個元素的行下標        overLap = nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]        # 計算相似性        if len(overLap) == 0: similarity = 0        else: similarity = simMeas(dataMat[overLap,item],dataMat[overLap,j]) # 計算overLap矩陣的相似性        # print "第%d列和第%d列的相似性是: %f" %(item, j, similarity)                # 累計總相似性         simTotal += similarity        # ratSimTotal = 相似性*元素值        ratSimTotal += similarity * userRating    if simTotal == 0: return 0 # 如果總相似性為0,返回0    # 返回相似性*元素值/總相似性    else:         # print "ratSimTotal:",ratSimTotal        # print "simTotal:",simTotal        return ratSimTotal/simTotal#使用svd進行估計    def svdEst(dataMat, user, simMeas, item):    n = shape(dataMat)[1]    simTotal = 0.0; ratSimTotal = 0.0    # svd相似性計算的核心    U,Sigma,VT = la.svd(dataMat) # 計算矩陣的奇異值分解    # Sig4 = mat(eye(4)*Sigma[:4]) # 取Svd特徵值的前4個構成對角陣    # xformedItems = dataMat.T * U[:,:4] * Sig4.I  # 建立變換後的項目矩陣create transformed items    V = VT.T # V是dataMat的相似矩陣    xformedItems = V[:,:4]    # print "xformedItems:",xformedItems    # 逐列遍曆資料集    for j in range(n):        userRating = dataMat[user,j] # 未評級使用者為0,因此不會計算。其他的均有值        # print "userRating:",userRating        # 跳過未評級的項目        if userRating == 0 or j==item: continue        # 使用指定的計算公式計算向量間的相似性        similarity = simMeas(xformedItems[item,:].T,xformedItems[j,:].T) # 相似性計算公式        # print "待評估%d列和第%d列的相似性是: %f" % (item, j, similarity)        simTotal += similarity # 計算累計總相似性         ratSimTotal += similarity * userRating # ratSim = 相似性*項目評估值    if simTotal == 0: return 0    else: return ratSimTotal/simTotal    # 產生推薦結果的主方法# simMeas取值:cosSim, pearsSim, ecludSim# estMethod取值:standEst,svdEst# user 使用者項目矩陣中進行評估的行下標# N=3返回前3項def recommend(dataMat, user, N=3, simMeas=cosSim, estMethod=svdEst):    unratedItems = nonzero(dataMat[user,:].A==0)[1] # 尋找未評級的項目--即使用者--項目矩陣中user行對應的零值    # print "unratedItems:",unratedItems    # unratedItems: 未評估的項目--項目矩陣中user行對應零值的列下標    if len(unratedItems) == 0: return "已經對所有項目評級"    # 初始化項目積分資料類型,是一個二維矩陣    # 元素1:item;元素2:評分值    itemScores = []     # 迴圈進行評估:將每個未評估項目於已評估比較,計算相似性    # 本例中未評估項目取值1,2    for item in unratedItems:        estimatedScore = estMethod(dataMat, user, simMeas, item) # 使用評估方法對資料評估,返回評估積分        itemScores.append((item, estimatedScore)) # 並在項目積分內加入項目和對應的評估積分    # 返回排好序的項目和積分,N=3返回前3項    return sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N] # 輸出矩陣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,flag=True):    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)    print "****original matrix******"    printMat(myMat, thresh)    U,Sigma,VT = la.svd(myMat)    print "U 行列數:",shape(U)[0],",",shape(U)[1]    print "Sigma:",Sigma    print "VT 行列數:",shape(VT)[0],",",shape(VT)[1]    if flag:    SigRecon = mat(zeros((numSV, numSV)))    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)

# -*- coding: utf-8 -*-# Filename : testRecomm01.pyfrom numpy import *import numpy as np import operatorfrom svdRec import *import matplotlib.pyplot as plt eps = 1.0e-6# 載入修正後資料A = mat([[5, 5, 3, 0, 5, 5],[5, 0, 4, 0, 4, 4],[0, 3, 0, 5, 4, 5],[5, 4, 3, 3, 5, 5]])# 手工分解求矩陣的svdU = A*A.Tlamda,hU = linalg.eig(U) # hU:U特徵向量VT = A.T*AeV,hVT = linalg.eig(VT)  # hVT:VT特徵向量hV = hVT.T# print "hU:",hU# print "hV:",hVsigma = sqrt(lamda)         # 特徵值print "sigma:",sigmaprint"svd:驗證結果:"Sigma = np.zeros([shape(A)[0], shape(A)[1]])U,S,VT = linalg.svd(A)# Sigma[:shape(A)[0], :shape(A)[0]] = np.diag(S)# print Uprint S# print VT# print U*Sigma*VT

運行結果如下:


本章主要介紹了KMeans無監督聚類演算法及其python的實現,另外一個講解了推薦系統最核心的演算法-SVD演算法,最後用Numpy的庫函數實現了SVD演算法.


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.