1. 程式人生 > >《集體智慧編中文版》讀書筆記——第二章:協作型過濾

《集體智慧編中文版》讀書筆記——第二章:協作型過濾

前言

一本比較老的書,偏實用,正好打算入手python機器學習,實現一遍程式碼。

關於協作型過濾

介紹他的一個引用場景:已有使用者對自己感興趣的電影評分的情況下,怎麼合理的為使用者推薦新電影?或者一個新使用者在瀏覽電影時,推薦其他相關的電影?
協作性過濾 的思想處理上述問題的邏輯是這樣的:

  • 兩個使用者對共同感興趣的電影評分都相近,顯然可以互相推薦對方未看過的電影。
  • 如果兩部電影使用者對它們的評分很接近,顯然這兩部電影就更值得同時出現。

具體來說:

  1. 相關性指標:計算兩個使用者對共同感興趣的電影的評分相關係數來衡量兩個使用者之間的相關程度,可以用皮爾遜相關係數,距離倒數等。
  2. 相關係數加權:為A推薦未看過的電影d時,如果B和C同時對電影d打過分,則以B、C與A的評分相關係數來加權各自對電影d的打分,作為A喜歡電影d的程度的預測。
  3. 基於物品的過濾:推薦與使用者喜歡的電影d相關程度高的電影,意義在於不用計算該使用者與所有其他使用者的評分相關程度。

資料集

使用者電影評分資料 MovieLens
zip壓縮包
——movies.csv:電影資訊表,主要是電影id和電影標題
——ratings.csv:打分表,主要使用者id,電影id和評分

程式碼:

__author__ = "xqx"
"""
    新建recommendations.py,下載資料集解壓到本地
"""
import recommendations as rd import json # 匯入使用者電影評分資料 prefs = rd.loadMovieLens(path = r'E:\桌面space\space\學習ing\python學習\集體智慧程式設計\提供推薦\data\ml-latest-small') if input("是否重新開始計算物品")=='y': #計算物品相似度矩陣並儲存 print("開始計算物品相似度字典.....") itemMatch = rd.calculateSimilarItems(prefs,10) print("計算完成!"
) with open('itemMatch.json','w') as outfile: json.dump(itemMatch,outfile,ensure_ascii=False) outfile.write('\n') else: #匯入物品相似度矩陣 f=open("itemMatch.json","r") for line in f: itemMatch=json.loads(line) f.close() userid = '87' print( "為使用者%s推薦的電影如下:"%userid ) recommends = rd.getRecommendedItems(prefs,itemMatch,userid) for i in range(len(recommends)): print('%.3f\t%s'%(recommends[i][0],recommends[i][1]))

結果

是否重新開始計算物品n
為使用者87推薦的電影如下:
5.000 xXx (2002)
5.000 loudQUIETloud: A Film About the Pixies (2006)
5.000 Zombieland (2009)
5.000 Zodiac (2007)
5.000 Zenon: Z3 (2004)
5.000 Zenon: The Zequel (2001)
5.000 Zenon: Girl of the 21st Century (1999)
5.000 Young People Fucking (a.k.a. YPF) (2007)
5.000 Yossi & Jagger (2002)
5.000 Wrong Cops (2013)
5.000 Wrong (2012)
5.000 Winnebago Man (2009)
5.000 Willie & Phil (1980)
5.000 Wild at Heart (1990)
5.000 Wild Zero (2000)
5.000 Where’s Marlowe? (1998)
5.000 What Happened Was… (1994)
4.667 Zulu (1964)

附件

recommendations.py

"""
資料集:姓名:電影:評分
"""
critics={'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5,
 'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 
 'The Night Listener': 3.0},
'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 
 'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 
 'You, Me and Dupree': 3.5}, 
'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0,
 'Superman Returns': 3.5, 'The Night Listener': 4.0},
'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0,
 'The Night Listener': 4.5, 'Superman Returns': 4.0, 
 'You, Me and Dupree': 2.5},
'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
 'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0,
 'You, Me and Dupree': 2.0}, 
'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0,
 'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5},
'Toby': {'Snakes on a Plane':4.5,'You, Me and Dupree':1.0,'Superman Returns':4.0}}



from math import sqrt
"""
    通過兩個人對同一物品的評分來定義兩人的相似度
      內在邏輯是:兩個相似的人喜歡同一個東西,對電影的評分應該相似             
"""
# 返回兩個人基於距離的相似度評價
def sim_distance(prefs,person1,person2):
    """
    距離的倒數來定義形似度
    """
    # 得到共有屬性的列表
    si = {}

    # 計算所有差值的平方和
    sum_of_squres = 0

    for item in prefs[person1]:
        if item in prefs[person2]:
            si[item]=1
            sum_of_squres += pow(prefs[person1][item] - prefs[person2][item], 2)

    # 如果兩者沒有共同之處,則返回0
    if len(si)==0:return 0

    return 1/(1+sqrt(sum_of_squres))

# 返回p1和p2的皮爾遜相關係數
def sim_pearson(prefs, p1, p2):
    """
    相關係數             
    """
    # 得到雙方都曾評價過的物品列表
    si = {}
    for item in prefs[p1]:
        if item in prefs[p2]: si[item] = 1

    # 得到列表元素的個數
    n = len(si)

    # 如果沒有共同之處,返回1
    if n==0: return 0;

    # 對所有偏好求和
    sum1 = sum([prefs[p1][it] for it in si])
    sum2 = sum([prefs[p2][it] for it in si])

    # 求平方和
    sum1sq = sum([pow(prefs[p1][it],2) for it in si])
    sum2sq = sum([pow(prefs[p2][it],2) for it in si])

    # 求乘積之和
    psum = sum([prefs[p2][it]*prefs[p1][it] for it in si])

    # 計算皮爾遜相關係數
    num = psum-sum1*sum2/n
    den = sqrt((sum1sq - pow(sum1,2)/n)*(sum2sq - pow(sum2,2)/n))
    if den==0 :return 0

    return num/den

# 從反映偏好的字典中返回最匹配者
# 返回結果的個數和相似度函式均可最為可選引數
# 預設返回前5個,計算皮爾遜相關係數
def topMatches(prefs,person,n=5,similarity=sim_pearson):
    """
    返回與指定客戶的相似性最高的前n位
    """
    scores = [(similarity(prefs, person, other),other)
                  for other in prefs if other!=person]

    # 對列表進行排序
    scores.sort()
    scores.reverse()
    return scores[:n]

# 相似係數加權的影片打分值
def getRecommendations(prefs, person ,similarity=sim_pearson):
    """
    對客戶未看過的影片,通過相似度加權評分,然後返回評分高的
    """
    totals = {}
    simSums = {}
    for other in prefs:
        # 不要和自己比較
        if other==person: continue
        sim = similarity(prefs,person, other)

        # 忽略評價值為零或小於零的情況
        if sim<=0: continue
        for item in prefs[other]:
            # 只對自己還未看過的影片進行評價
            if item not in prefs[person] or prefs[person][item]==0:
                # 相似度 * 評價值
                totals.setdefault(item,0)
                totals[item] += prefs[other][item]*sim
                # 相似度只和
                simSums.setdefault(item,0)
                simSums[item]+=sim

    # 建立一個歸一化的列表
    rankings = [(total/simSums[item],item) for item,total in totals.items()]

    # 返回經過排序的列表
    rankings.sort()
    rankings.reverse()
    return rankings

def transforPrefs(prefs):
    result = {}
    for person in prefs:
        for item in prefs[person]:
            result.setdefault(item, {})

            # 將人和物品對調
            result[item][person] = prefs[person][item]
    return result


###匯入本地的MovieLens資料集

def loadMovieLens(path='/data/ml-latest-small'):

    # 獲取影片標題
    movies = {}
    file = open(path + '/movies.csv')
    file.readline()

    for line in file:
        (ids, title)=line.split(',')[:2]
        movies[ids] = title

    file.close()

    # 載入資料
    prefs = {}
    file = open(path + '/ratings.csv')
    file.readline()
    for line in file:
        (user,movieid,rating,ts)=line.split(',')
        prefs.setdefault(user,{})
        prefs[user][movies[movieid]]=float(rating)

    file.close()
    return prefs


def calculateSimilarItems(prefs,n = 10):
    # 建立字典,以給出與這些物品最為相似的所有其他物品
    result = {}

    # 以物品為中心對偏好矩陣實施倒置處理
    itemPrefs = transforPrefs(prefs)
    c = 0
    for item in itemPrefs:
        # 針對大資料更新狀態變數
        c += 1
        # 顯示進度
        if c%100==0:print("%d / %d"%(c,len(itemPrefs)))
        # 尋找最為相似的物品
        scores = topMatches(itemPrefs, item, n=n,similarity=sim_distance)
        result[item] = scores

    return result

def getRecommendedItems(prefs,itemMatch,user):
    userRatins = prefs[user]
    scores={}
    totalSim={}

    # 迴圈遍歷由當前使用者評分的物品
    for (item,rating) in userRatins.items():

        # 迴圈遍歷與當前物品相近的物品
        for (similarity,item2) in itemMatch[item]:

            # 如果該使用者已經對當前物品做過評價,則將其忽略
            if item2 in userRatins:continue;

            # 評價值與相似度的加權之和
            scores.setdefault(item2,0)
            scores[item2] += similarity * rating

            # 全部相似度之和
            totalSim.setdefault(item2, 0)
            totalSim[item2] += similarity

    # 相似度加權平均   
    rankings = [(score/totalSim[item],item) for item,score in scores.items()]

    # 按最高值到最低值的順序,返回評價結果
    rankings.sort()
    rankings.reverse()
    return rankings

相關推薦

集體智慧中文版讀書筆記——第二協作過濾

前言 一本比較老的書,偏實用,正好打算入手python機器學習,實現一遍程式碼。 關於協作型過濾 介紹他的一個引用場景:已有使用者對自己感興趣的電影評分的情況下,怎麼合理的為使用者推薦新電影?或者一個新使用者在瀏覽電影時,推薦其他相關的電影? 協作性

深度學習讀書筆記 第二線性代數

2.1 標量、向量、矩陣和張量 標量:scalar,是一個單獨的數 向量:vector,是一列有序的數.方括號包圍的縱列,每個元素有一個索引。 矩陣:matrix,二維陣列,每個元素由兩個索引組成。Aij處於i行j列。 張量:tensor,超過二維的陣列。 標量和矩陣的運算:

程式碼整潔之道讀書筆記——第二有意義的命名

第二章 有意義的命名 2.1 介紹 在軟體開發中,我們各種命名,不斷的命名,有這麼多的命名,一定要做好它! 2.2 名副其實 選個好名字要花很多時間,而且對於我們中國的程式設計師來說,選一個好的英文名字更要精挑細選,但是省下來的時間遠比花掉的多,一個名稱基本就答

《lua程式設計》讀書筆記 第二型別與值

lua是一種動態型別的語言。 在lua中有8中基礎型別:nil(空)、boolen、number、string、userdata(自定義型別)、function、thread、table。函式type可根據一個值返回其型別名稱,其返回值為string。

集體智慧程》代碼勘誤第六

close app alt fontsize 第六章 ng- ble 信息 to do 一:勘誤 classifier類中: def fprob(self, f, cat): if self.catcount(cat) == 0: return 0

《C++ Primer》讀書筆記-第二 變數和基本型別

   第一篇文章寫完後收到了很多同學的後臺留言,有鼓勵的,也有提出建議的,還有說錯別字的,每一條都一一回復了,當然提出建議的大都是說排版問題,現在已經換到MarkDown編輯器了,大家湊合著看就行了,肯定不影響閱讀了,至於錯別字的,哈哈,你懂就行。   &nbs

《多處理器程式設計的藝術》讀書筆記——第二 互斥

臨界區:某個時刻僅能被一個執行緒執行的程式碼段。 良構的執行緒: 1.一個臨界區只和一個唯一的Lock物件相關聯 2.執行緒準備進入臨界區時呼叫該物件的lock()方法 3.當執行緒離開臨界區時呼叫unlock()方法 一個好的鎖演算法應該滿足哪些特性: 互斥:不同執行緒的臨界區之間沒有重疊

java程式設計的邏輯讀書筆記——第二

1.整數的二進位制表示 1)原碼:可以直接通過計算得出的最直觀的形式。 2)補碼:原碼取反加1。對負數的補碼錶示做補碼運算就可以得到器對應正數的原始碼。 3)負數的表示就是對應的正數的補碼。 4)計算機其實只能做加法運算,用負數的補碼形式進行運算。 2.十六進

[讀書筆記][第二] 深入理解C# -- C# in depth

ch2 C#1所搭建的核心基礎 委託 宣告委託 方法執行程式碼:相容的方法簽名 建立委託例項 呼叫例項:Invoke() 或簡化呼叫 加減委託 呼叫列表,Combine() + , Remove() - 事件 事件是委託型別,是屬性,封裝了publish

《計算廣告》讀書筆記——第二 計算廣告基礎

千次展示期望收入(expected Cost Per Mille, eCPM)是計算廣告中最為核心的量化指標之一。 eCPM又可以分解為點選率和點選價值的乘積。 **廣告的資訊接收過程:**分為選擇(selection)、解釋(interpretation)與

深度學習(花書)讀書筆記——第二-線性代數

第二章-線性代數2.1 標量、向量、矩陣和張量標量(scalar):一個標量就是一個單獨的數,它不同於線性代數中研究的其他大部分物件(通常是多個數的陣列)。向量(vector):一個向量是一列數。這些數是有序排列的。                             

(周志華)讀書筆記 -- 第二 模型評估與選擇

隨手記下所學知識,很多圖表來自原書,僅供學習使用! 2.1  經驗誤差與過擬合 通常,我們使用"錯誤率"來表示分類中錯誤的樣本佔總樣本的比例.如果m個樣本中有a個錯誤樣本則錯誤率E=a/m ,對應的,

App 研發錄、架構設計、Crash分析和競品技術分析------讀書筆記(第二)

網路底層框架設計 1、不要自己定義網路請求框架,網路層不要使用AsyncTask 2、在網路返回資料Response的應該有一個規範的格式 { "isError":true, "errorType":1, "errorMessa

《消費者行為學》讀書筆記 第二 知覺

第二篇作為個體的消費者 在本篇中,將研究消費者購買的內在動力。 營銷和市場研究關注的物件可界定為三種角色:購買者、消費者和生活者。購買者研究是消費者研究中的一小部分。三者分別對應短期關注、中期關注和長期關注。 第二章知覺 知覺的過程包括三個階段,在知覺過程中原始的刺激

AI 讀書筆記:第二:追逐和閃躲 關於視線追逐

    今天上午研究了書中第二章,關於追逐和閃躲的技術.  頭一個比較好懂, 既基本的追逐演算法,就是NPC的座標值和target的座標值做比較,如果是追逐的話,那麼就向著靠近target的方向移動就可以了.   實現程式碼如下:     if (predatorX >

《學會提問》讀書筆記——第二

第2章 論題和結論是什麼 “是什麼”問題和“應不應該”問題 論題和結論是什麼? 論題就是引起對話或討論的問題抑或爭議。它是後續所有討論的驅動力。 描述性論題是指對過去、

《深入理解計算機系統》讀書筆記 —— 第二 資訊的表示和處理

> 本章主要研究了計算機中無符號數,補碼,浮點數的編碼方式,通過研究數字的實際編碼方式,我們能夠了解計算機中不同型別的資料可表示的值的範圍,不同算術運算的屬性,可以知道計算機是如何處理資料溢位的。瞭解計算機的編碼方式,對於我們寫出可以跨越不同機器,不同作業系統和編譯器組合的程式碼具有重要的幫助。 > @[T

《數據庫設計入門經典》讀書筆記——第一數據庫建模的過去與現在

port 混合 如果 執行 很好 創建表 規則 什麽 增長 《數據庫設計入門經典》,現在學習的是這本書,雖然以前就看過類似的書,可能由於之前經驗不足,書中說的某些東西只消化了一部分,現在重溫一邊好懂多了。所以說讀第一遍讀不懂不要緊,過個一年半載的再來讀,還是會讀不懂的,哈哈

《高效能MySQL》讀書筆記---第一MySQL架構與歷史

本章描述了MySQL的伺服器架構、各種儲存引擎之間的主要區別,以及這些區別的重要性   1.1 MySQL邏輯架構 MySQL的邏輯架構如下圖所示: 第一層:該層的服務並不是MySQL獨有的,大多數基於網路的客戶端/伺服器的工具或者伺服器都有類似的架構。如連線處理、授權認證、安全等

程式碼整潔之道讀書筆記——第一整潔程式碼

軟體質量,不僅僅依賴於專案架構和專案管理,同樣重要的是程式碼質量!!! 序 神在細節之中,其實幹什麼事都一樣,從小到大,一直明白一個道理:細節決定成敗! 軟體架構在開發中佔據重要地位。其次,巨集達建築的最細小的部分,比如關不緊的門、有點沒鋪平的地板,甚至是凌亂的桌