機器學習第一篇(上)
提供推薦(電影,音樂,書籍,交友,購物,網站,部落格服務,文章,幽默笑話等):
這是我在看《集體智慧程式設計》這本書時所做的筆記,一是為了以後忘記的時候能再翻回來看一看,二是將自己所記錄的東西能夠與大家分享,三是保持我對人工智慧的激情與動力。
協作性過濾:對一大群人進行搜尋,並從中找出與我們品味相近的一小群人。演算法會對這些人所偏好的其他內容進行考察,並將它們組合起來構造一個經過排名的推薦列表
第一步:蒐集偏好
不管偏好是如何表達的,我們需要一種方法來將它們對應到數字,資料可存放於資料庫中
第二步:尋找相近的使用者
確定人們在品味方面的相似程度。可以將每個人與所有其他人進行對比,並計算他們的相似度評價值 。歐幾里得距離
歐幾里得距離:
兩人在“偏好空間”中的距離越近,他們的興趣偏好就越相似,因為這張圖是二維的,所以在同一時間內你只能看到兩項評分,第三這一規則對於更多數量的評分項而言也是同樣適用的。但當評價結果中,評價者的評價相對於平均水平偏離很大的時候歐幾里德距離不能很好的揭示出真實的相似度。
import math def sim_distance(prefs, person1, person2): si = {} for item in prefs[person1]: if item in prefs[person2]: si[item] = 1 if len(si) == 0: return 0 sum_of_squares = sum( [pow(prefs[person1][item] - prefs[person2][item], 2) for item in prefs[person1] if item in prefs[person2]]) #**************************************** return 1 / (1 + math.sqrt(sum_of_squares))
*皮爾遜相關度:判斷兩組資料與某一直線擬合程度的一種度量。它在資料不是很規範(normalized)的時候(比如,影評者對影片的評價總是相對於平均水平偏離很大時),會傾向於給出更好的結果,即修正“誇大分值”的情況。
這裡會涉及概率統計中的隨機變數的數字特徵一章,原諒我還沒有細看。。。公式在此!
def sim_person(prefs, p1, p2): si = {} for item in prefs[p1]: if item in prefs[p2]: si[item] = 1 if len(si) == 0: return 0 n = len(si) # 對所有共同偏好求和 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[p1][it] * prefs[p2][it] for it in si]) # 求皮爾遜評價值 num = pSum - (sum1 * sum2 / n) den = math.sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n)) if den == 0: return 0 r = num / den return r
該函式將返回一個介於-1與1之間的數值,值為1表明兩個人對每一樣物品均有一致的評價。
第三步:為評論者打分
def topMatches(prefs, person, n=5, similarity=sim_person):
scores = [(similarity(prefs, person, other), other)
for other in prefs if other != person]
scores.sort()
scores.reverse()
return scores[0:n]
第四步:推薦物品
找到一位趣味相投的影評者並閱讀他所撰寫的評論固然不錯,但現在我們真正想要的不是這些,而是一份影片的推薦。當然,我們也可以查詢與自己最為相近的人,並從他所喜歡的影片中找出一部自己還未看過的影片,不過這樣太permissive了,有時,這種方法可能會有問題:評論者還未對某些影片做過評論,而這些影片也許就是我們所喜歡的。為了更謹慎,須要通過一個經過加權的評價值來為影片打分。
def getRecommendations(prefs, person, similarity=sim_person):
totals = {}
simSums = {}
for other in prefs:
# don't compare me to myself
if other == person: continue
sim = similarity(prefs, person, other)
# ignore scores of zero or lower
if sim <= 0: continue
for item in prefs[other]:
# only score movies I haven't seen yet
if item not in prefs[person] or prefs[person][item] == 0:
# Similarity * Score
totals.setdefault(item, 0)
totals[item] += prefs[other][item] * sim
# Sum of similarities
simSums.setdefault(item, 0)
simSums[item] += sim
# Create the normalized list
rankings = [(total / simSums[item], item) for item, total in totals.items()]
# Return the sorted list
rankings.sort()
rankings.reverse()
return rankings
針對每一次迴圈,它會計算由person引數指定的人員與這些人的相似度,然後它會迴圈遍歷所有打過分的項。每一項的最終評價值的計算方法——用每一項的評價值乘以相似度,並將所得乘積累加起來,最後,將每個總計值除以相似度之和,藉此對評價值經行歸一化處理,然後返回一個經過排序的結果。