天天看點

基于使用者的協同過濾推薦算法研究

摘要:近年來,随着線上可供選擇的增加,推薦系統變得越來越不可或缺。推薦系統通過發掘使用者的行為,找到使用者的個性化需求,進而将長尾物品準确推薦給需要它的使用者,幫助使用者找到他們感興趣但很難發現的物品。本文采用基于使用者的協同過濾算法實作電影的推薦,并針對該方法存在的稀疏性,冷啟動和擴充性問題進行了分析,結果表示此算法可以得到不錯的推薦效果。

關鍵詞:協同過濾;使用者;皮爾遜系數;相似度

Abstract:In recent years, with the increase of online choices, recommendation system becomes more and more indispensable. Recommendation system finds users’ personalized needs by exploring users’ behavior, and accurately recommending long tail items to users who need them which could helps users to find items they are interested in but difficult to find. In this paper, user-based collaborative filtering algorithm is used to implement movie recommendation, and the sparsity, cold start and expansibility of this method are analyzed. The results show that this algorithm can get good recommendation effect.

Key words: collaborative filtering; users; Pearson coefficient; similarity

一.推薦系統介紹

随着電子商務和網絡通訊的興起,網際網路成為人們擷取資訊以及購物的重要工具,導緻了資料的爆炸式增長,也就是資訊過載。使用者要從網際網路上的茫茫資訊海洋中找到自己需要的資訊十分困難,是以,推薦系統應運而生。推薦系統的目标是幫助使用者從大量的物品中篩選出最适合其偏好的個性化物品,除此之外,許多商業公司将推薦系統運用到了實際中,通過推按物品來确定他們的目标使用者。多年來,用于推薦系統的不同算法已得到了發展。高品質的推薦系統會使使用者對系統産生依賴,是以,推薦系統不僅能為使用者提供個性化服務,還能與使用者建立長期穩定的關系,提高使用者忠誠度,防止使用者流失。通用的推薦系統模型流程為

a)推薦系統通過使用者行為,建立使用者模型;

b)通過物品的資訊,建立推薦對象模型;

c)通過使用者興趣比對物品的特征資訊,再經過推薦算法計算篩選,找到使用者可能感興趣的推薦對象,然後推薦給使用者。

使用者行為資料在網站上最簡單的存在形式就是日志,日志中記錄了使用者的各種行為,比如網頁浏覽、點選、購買、評論、評分等等。使用者行為在個性化推薦系統中一般分為顯性回報行為和隐性回報行為。顯性回報行為包括使用者明确表示對物品的喜好的行為,比如給物品評分,而隐性回報行為是指那些不能明确反應使用者喜好的行為,比如頁面浏覽行為。隐性回報資料比顯性回報不明确,但其資料量更龐大。

二.資料預處理

2.1 相似度計算

相似度計算主要有三個經典算法:餘弦定理相似性度量、歐氏距離相似度度量和皮爾遜相關系數法

(1)餘弦定理相似性度量

通過測量兩個向量内積空間的夾角的餘弦值來度量它們之間的相似性。0度角的餘弦值是1,而其他任何角度的餘弦值都不大于1;并且其最小值是-1。進而兩個向量之間的角度的餘弦值确定兩個向量是否大緻指向相同的方向。兩個向量有相同的指向時,餘弦相似度的值為1;兩個向量夾角為90°時,餘弦相似度的值為0;兩個向量指向完全相反的方向時,餘弦相似度的值為-1。在比較過程中,向量的規模大小不予考慮,僅僅考慮到向量的指向方向。餘弦相似度通常用于兩個向量的夾角小于90°之内,是以餘弦相似度的值為0到1之間。

基于使用者的協同過濾推薦算法研究

(2)歐氏距離相似性度量

與餘弦定理通過方向度量相似度不同,歐氏距離是通過計算樣本實際距離在度量相似度的。二維平面上兩點a(x1,y1)與b(x2,y2)間的歐氏距離

基于使用者的協同過濾推薦算法研究

(3)皮爾遜相關系數

兩個變量之間的相關系數越高,從一個變量去預測另一個變量的精确度就越高,這是因為相關系數越高,就意味着這兩個變量的共變部分越多,是以從其中一個變量的變化就可越多地獲知另一個變量的變化。如果兩個變量之間的相關系數為1或-1,那麼你完全可由變量X去獲知變量Y的值。

當相關系數為0時,X和Y兩變量無關系;當相關系數在0.00與1.00之間,X、Y正相關關系;當相關系數在-1.00與0.00之間,X、Y負相關關系。由此可知,相關系數的絕對值越大,相關性越強,相關系數越接近于1和-1,相關度越強,相關系數越接近于0,相關度越弱。

2.2 抽樣

抽樣是資料挖掘從大資料集中選擇相關子資料集的主要技術,用于資料預處理和最後的解釋步驟中。抽樣的原因是處理全部資料集的計算開銷太大,同時可以被用來創造訓練和測試資料集。其中,訓練集被用于分析階段學習參數或配置算法,測試及用于評估訓練階段獲得的樣本或模型,確定将來在未知資料上運作良好。

抽樣的關鍵是發現具有整個原始資料及代表性的子集。最簡單的抽樣技術是随機抽樣。抽樣可能導緻過特殊化劃分的訓練集和測試集,是以訓練的過程可以重複好幾次。在分離訓練集和測試集是最常用的是使用80/20的訓練集和測試集比例,并使用無替代的标準随機抽樣。

在推薦系統中常用的方法是從使用者中抽取可能的回報以使用者評分的方式來劃分訓練和測試。交叉驗證的方法也很常見。在一般案例中可接受标準随機抽樣,但在其他場景中需要用不同的方法定向調整抽樣出來的測試集。

2.3 降維

推薦系統中不僅有定義高維空間的資料集,而且在空間中的資訊非常稀疏。例如,每個對象隻有幾個有限的特征有值。密度以及點之間的距離,這些對于聚類和孤立點檢測非常重要,但在高維空間中的意義并不大,這就是著名的次元災難。降維技術通過把原始高維空間轉化成低維有助于克服這類問題。

推薦系統中最常用的降維算法有:主成分分析(PCA)和奇異值分解(SVD)。主成分分析(PCA)是一種經典統計方法,主成分分析可以獲得一組有序的成分清單,根據其最小平方誤差計算出變化最大的值。清單中第一個成分所代表的變化量要比第二個成分所代表的變化量大,以此類推,我們可以通過忽略這些對變化貢獻較小的成分來降低次元。

2.4 去燥

資料挖掘中采集的資料可能有各種噪聲,如缺失資料,或者是異常資料。去燥是非常重要的預處理步驟,其目的是在最大化資訊量時去除不必要的影響。一般意義上,我們把噪聲定義為在資料收集階段收集到的一些可能影響資料分析和解釋結果的僞造資料。 在推薦系統環境中,我們區分自然的和惡意的噪聲。前者是使用者在選擇偏好回報時無意識産生的,後者是為了偏離結果在系統中故意引用的。為了解決這個問題,我們可以設計去燥的方法,能夠通過要求使用者重新評價一些物品來提高精确度。我們推斷通過預處理步驟來提高精确度能夠比複雜的優化算法優化效果好得多。

三.協同過濾算法

3.1 基于使用者的協同過濾(user-based)

這種算法給使用者推薦和他興趣相似的其他使用者喜歡的物品。算法步驟:(1) 找到和目标使用者興趣相似的使用者集合;(2) 找到這個集合中的使用者喜歡的,且目标使用者沒有聽說過的物品,推薦給目标使用者。算法的關鍵是計算兩個使用者的興趣相似度。協同過濾計算使用者興趣相似度是利用使用者行為的相似度。

3.2 基于物品的協同過濾(item-based)

這種算法給使用者推薦和他之前喜歡的物品相似的物品。該算法是目前業界應用最多的算法,如亞馬遜、Netflix、YouTube,都是以該算法為基礎。算法步驟:(1) 根據使用者的曆史行為,計算物品之間的相似度;(2) 根據物品的相似度和使用者的曆史行為給使用者生成推薦清單。兩個物品産生相似度,是因為它們共同被很多使用者喜歡,也就是說,每個使用者都可以通過它們的曆史興趣清單給物品“貢獻”相似度。

3.3 關聯算法

3.3.1 關鍵名額

一般我們可以通過找出使用者購買的所有物品資料裡頻繁出現的項集活序列,來做頻繁集挖掘,找到滿足支援度門檻值的關聯物品的頻繁N項集或者序列。如果使用者購買了頻繁N項集或者序列裡的部分物品,那麼我們可以将頻繁項集或序列裡的其他物品按一定的評分準則推薦給使用者,這個評分準則包括支援度,置信度和提升度等。常用的關聯推薦算法有Apriori,FP Tree和PrefixSpan。下面簡要介紹三個關鍵名額。

支援度就是幾個關聯的資料在資料集中出現的次數占總資料集的比重。或者說幾個資料關聯出現的機率。如果我們有兩個想分析關聯性的資料X和Y,則對應的支援度為:

基于使用者的協同過濾推薦算法研究

置信度展現了一個資料出現後,另一個資料出現的機率,或者說資料的條件機率。如果我們有兩個想分析關聯性的資料X和Y,X對Y的置信度為

基于使用者的協同過濾推薦算法研究

提升度表示含有Y的條件下,同時含有X的機率,與X總體發生的機率之比,即:

基于使用者的協同過濾推薦算法研究

提升度體先了X和Y之間的關聯關系, 提升度大于1則X⇐YX⇐Y是有效的強關聯規則,提升度小于等于1則X⇐YX⇐Y是無效的強關聯規則。

3.3.2 算法簡介

Apriori算法是常用的用于挖掘出資料關聯規則的算法,它用來找出資料值中頻繁出現的資料集合,以此輔助人們做出決策。一般來說,要選擇一個資料集合中的頻繁資料集,則需要自定義評估标準。最常用的評估标準是用自定義的支援度,或者是自定義支援度和置信度的一個組合。對于Apriori算法,我們使用支援度來作為我們判斷頻繁項集的标準。而Apriori算法的目标是找到最大的K項頻繁集。這要求我們要找到符合支援度标準的頻繁集,并且要找到最大個數的頻繁集,主要方法是疊代。由于它需要多次掃描資料,I/O成為很大的瓶頸,為了解決這個問題,FP Tree算法(也稱FP Growth算法)進行了優化。通過引入項表頭,FP Tree和節點連結清單三個資料結構,使得隻需要掃描兩次資料集,是以提高了算法運作的效率。

3.4 分類算法

根據使用者評分的高低,将分數分段就可以把問題變成分類問題。目前使用最廣泛的是邏輯回歸,其廣泛應用于大型公司,由于我們可以對每個物品是否推薦給出一個明确的機率,是以可以對資料的特征做工程化,進而調優。常見的分類推薦算法有邏輯回歸和樸素貝葉斯。邏輯回歸由線性回歸發展來,對于線性回歸模型,可以得到輸出特征向量Y和輸入樣本矩陣X之間的線性關系,利用函數将Y轉化為g(Y)(常用sigmoid函數),可以得到隻有兩種結果的邏輯回歸,進而達到分類的效果。在所有的機器學習分類算法中,樸素貝葉斯和其他絕大多數的分類算法都不同。對于大多數的分類算法,都是直接學習出特征輸出Y和特征X之間的關系,比如決策樹,KNN,邏輯回歸,支援向量機等都是判别方法。但是樸素貝葉斯通過直接找出特征輸出Y和特征X的聯合分布P(X,Y)的一種生成方法。

四.代碼實作與結果展示

本文實作基于使用者的協同過濾推薦算法。用到的資料結構有數組和矩陣。利用皮爾遜相關系數來計算使用者間相似度,通過設定合适的min_periods參數值實作較為準确地電影推薦。

4.1 資料規整

使用的資料分析包為pandas,Numpy和matplotlib,資料集為經典資料集ml-100k。首先将評分資料從ratings.dat中讀出到一個DataFrame 裡,然後 取出user_id、movie_id 和 rating的數值放到一個以 user 為行,movie 為列,rating 為值的data表裡。

基于使用者的協同過濾推薦算法研究

可以看到這個表相當得稀疏,填充率大約隻有 5%,接下來要實作推薦的第一步是計算 user 之間的相關系數。

4.2相關度測算

DataFrame計算使用者相似度可通過.corr(method=‘pearson’, min_periods=1) 方法,對所有列互相計算相關系數。其中method預設為皮爾遜相關系數,min_periods參數的作用是設定計算相關系數時的最小樣本量,低于此值的一對列将不進行運算。這個值的取舍關系到相關系數計算的準确性,是以接下來确定具體的參數值。

4.3 min_periods 參數測定

統計在 min_periods 取不同值時,相關系數的标準內插補點(越小越好)但同時需要考慮到樣本空間稀疏的問題,min_periods 定得太高會導緻濾除後的資料太小,是以需要標明一個折中的值。

這裡我們測定評分系統标準差的方法為:在data中挑選一對重疊評分最多的使用者,用他們之間的相關系數的标準差去對整體标準差做點估計。在此前提下對這一對使用者在不同樣本量下的相關系數進行統計,觀察其标準差變化。

首先,要找出重疊評分最多的一對使用者。計算出其相似度為0.37左右。

基于使用者的協同過濾推薦算法研究

對這兩個使用者的相關系數統計,我們分别随機抽取 5,10,15,20,30 個樣本值,各抽 20 次。并統計結果:

基于使用者的協同過濾推薦算法研究

觀察stu一行,我們需要得到較低的方差,但參數值不能設定太高(以防濾除後的資料量過少),是以我們取參數為10。

4.3 min_periods 參數檢驗

通過算法檢驗,進一步判斷min_periods 參數的設定是否合理。随機抽取300個使用者,每人随機提取一個評價另存到一個數組裡,并在資料表中删除這個評價。然後基于閹割過的資料表計算被提取出的評分的期望值,最後與真實評價數組進行相關性比較,看結果如何。接下來對與使用者相關系數大于 0.1 的其他使用者評分進行權重平均,權值為相關系數。

基于使用者的協同過濾推薦算法研究

我們可以看到,當參數設定為10時,在随機抽取的300個使用者中,依然有119個被濾除,但同時得到了0.57的相關系數。證明參數設定為10比較合理。

4.5 實作推薦

基于使用者的協同過濾推薦算法研究

五.面臨問題

盡管協同過濾技術自被提出以來,得到了推廣和應用,也取得了很大的成功,但是由于自身的算法特性以及應用場景不可回避的一些問題,該方法也面臨着一系列挑戰,主要表現在:

5.1 稀疏性問題(Sparsity)

在沒有任何刺激和鼓勵評分的優惠措施下,使用者自願給出評價的很少,更不用說不同使用者在同一項目上的共同評價了。傳統協同過濾推薦算法在評價資料稀疏的情況下,使用者間、項目間的相似性計算不準确,導緻推薦精度受到極大的影響。

5.2 冷啟動問題(Cold-start)

推薦系統需要根據使用者的曆史評價資料預測使用者未來的興趣,當一個新使用者或一個新項目進入系統,亦或是一個全新的系統剛啟動,都會面臨冷啟動問題。

5.3 擴充性問題(Scalability)

正常的商業網站都會存在數以萬計的使用者和項目,推薦算法在最近鄰居計算時的搜尋時間和空間将會非常龐大。可想而知,在如此巨大的資料量面前,協同過濾推薦方法很難保證算法的實時性。

六.解決方案

6.1稀疏性

解決資料稀疏性的問題,主要有兩種思路:其一,基于資料填充的方法,借助其他有用資訊建立有效的項目特征模型和使用者興趣模型并以此彌補評價資料的稀疏問題,這類資訊可以是項目的内容資訊[1]、使用者對項目的标簽資訊[2]、使用者對項目的隐式回報資料[3]等等。其二,在原有評分資料的基礎上,通過矩陣劃分、聚類、矩陣分解等機器學習方法進行評分資料的預處理。

針對評價資料的稀疏性問題,文獻[4]基于降低次元的思想,将參與相似度計算的兩個使用者投影到一個低維空間上,增加評價資料的稠密度,進而提高了協同過濾算法的效率。文獻[5]提出了基于Bayesian模型的多準則推薦算法,該方法從多方面建立使用者偏好資料,并通過隐主題将使用者和項目映射到各自群體,實驗證明貝葉斯模型在多準則評價推薦系統中是有效的,同時可以緩解冷啟動問題。文獻[6]為了降低資料的稀疏度,對原有評分矩陣進行劃分,盡可能縮小近鄰搜尋的範圍和需要預測的資源數目,實驗結果表明該方法在算法性能上優于傳統協同過濾算法。

6.2冷啟動

目前針對冷啟動問題提出了一些解決方法,如随機推薦法(對于新使用者,系統從包括新項目在内的所有項目中随機選取進行推薦,然後根據使用者的評價回報,了解新使用者的興趣偏好同時得到接受新項目的使用者群體)、平均值法(将項目的評分均值作為目标使用者對未評價項目的預測值)、衆數法(将使用者曾經使用過最多的評價值作為對未評價項目的預測值)。另一類方法是,在計算相似性時融入使用者的人口統計學資訊[7]、背景知識(社交網絡[8])、信任關系[9],綜合考慮項目的内容資訊[10]等。不同的算法具有各自的優缺點,具有一定的适用場景。

6.3擴充性

協同過濾推薦算法的時間複雜度為O(n2m),當推薦系統面臨數以百萬甚至千萬級别的使用者和項目時,計算開銷非常龐大,算法的實時性将很難保證,相應的推薦系統将面臨算法的擴充性問題。一類方法是采用并行技術,以提高算法的運作效率[11]。比如,文獻[12]提出了一種基于擴充向量的并行協同過濾推薦模型,為了解決冷啟動問題和向目标使用者提供更準确的推薦結果,文中對項目向量進行了擴充,并運用并行計算架構對系統進行了進一步的優化。與傳統的協同過濾推薦方法相比,該方法不僅克服了冷啟動問題,提高了一倍的推薦精度,而且在理想環境下可以提高170倍運作速度。

另一類方法是采用降維、聚類、分類等政策對評分樣本資料進行離線學習,建立可以用來推薦的模型,一定程度上解決了算法的擴充性問題。例如,SVD等降維技術通過壓縮矩陣,降低算法的時間複雜度,同時確定推薦結果的準确性。

七.參考文獻

[1]孫金剛,艾麗蓉.基于項目屬性和雲填充的協同過濾推薦算法[J].計算機應用,2012,32(3):658-660.

[2]郭彩雲,王會進.改進的基于标簽的協同過濾算法[J].計算機工程與應用,2016,52(8):56-61.

[3]Cui H,Zhu M.Collaboration filtering recommendation optimization with user implicit feedback[J].Journal of Computational Information Systems,2014,10(14):5855-5862.

[4]Sarwar B,Karypis G,Konstan J,et al.Application of dimensionality reduction in recommender systems—A case study[C]//Proc of the WebKDD 2000 Workshop at the ACM-SIGKDD Conf on Knowledge Discovery in Databases(KDD 2000),2000:1-12.

[5]Samatthiyadikun P,Takasu A,Maneeroj S.Multicriteria collaborative filtering by Bayesian model-based user profiling[J].Information Reuse and Integration(IRI),2012,59(5):124-131.

[6]高風榮,杜小勇,王珊.一種基于稀疏矩陣劃分的個性化推薦算法[J].微電子學與計算機,2004,21(2):58-62.

[7]Pereira A L V,Hruschka E R.Simultaneous co-clustering and learning to address the cold start problem in recommender systems[J].Knowledge-Based Systems,2015,82:11-19.

[8]He J,Chu W,A Social Network-based Recommender System(SNSR)[M].[S.l.]:Springer US,2010:47-74.

[9]Shambour Q,Lu J.An effective recommender system by unifying user and item trust information for B2B applications[J].Journal of Computer and System Sciences,2015,81(7):1110-1126.

[10]Balabanovic M,Shoham Y,Fab:content-based collaborative recommendation[J].Communications of the ACM,1997,40(3):66-72.

[11]田保軍,胡培培,杜曉娟,等.Hadoop下基于聚類協同過濾推薦算法優化的研究[J].計算機工程與科學,2016,38(8):1615-1624.

[12]Su H,Zhu Y,Wang C,et al.Parallel collaborative filtering recommendation model based on expand-vector[C]//Proceedings of the IEEE Second International Conference on Cognitive Systems and Information Processing,Beijing,China,2014:102-113.

八.代碼

import numpy as np
import pandas as pd
from pandas import Series,DataFrame

##以下為找出兩個相似度最大的使用者
rnames = ['user_id','movie_id','rating','timestamp']
ratings = pd.read_csv('./u1.test',sep='\t',header=None,names=rnames)
data = ratings.pivot(index='user_id',columns='movie_id',values='rating')
print(data[:10])
foo = DataFrame(np.empty((len(data.index),len(data.index)),dtype=int),
                index=data.index, columns=data.index)
#print(len(data.index))
'''
for i in foo.index:
    for j in foo.columns:
        foo.loc[i, j] = data.loc[i][data.loc[j].notnull()].dropna().count()
#print(foo.loc[i,j])
for i in foo.index:
    foo.loc[i, i] = 0
ser = Series(np.zeros(len(foo.index)))
for i in foo.index:
    ser[i] = foo[i].max()
'''
#print(ser.idxmax())  # 傳回ser的最大值所在的行号
#print(ser[416])     # 取得最大值
#print(foo[foo == 58][416].dropna())    # 取得另一個 user_id
#print(data.loc[13].corr(data.loc[276]))    #計算兩個使用者的相關度


##把兩個使用者評分情況放到test表裡,并随機抽取兩使用者的樣本值來估計min_periods參數值
test = data.reindex([13, 276], columns=data.loc[13][data.loc[276].notnull()].dropna().index)
#print(test)
#test.loc[276].value_counts(sort=False).plot(kind='bar')
periods_test = DataFrame(np.zeros((20,5)),columns=[5,10,15,20,30])
for i in periods_test.index:
    for j in periods_test.columns:
        sample = test.reindex(columns=np.random.permutation(test.columns)[:j])
        periods_test.loc[i,j] = sample.iloc[0].corr(sample.iloc[1])
#print(periods_test[:10])
#print(periods_test.describe())



##算法檢驗,判斷min_periods參數值取得是否合适
#在評價數大于5的使用者中随機抽取300位使用者,每人随機提取一個評價另存到一個數組裡,并在資料表中删除這個評價.
# 然後基于閹割過的資料表計算被提取出的 300 個評分的期望值,最後與真實評價數組進行相關性比較,看結果如何。
check_size = 300
check = {}
check_data = data.copy()  # 複制一份 data 用于檢驗,以免篡改原資料
check_data = check_data.loc[check_data.count(axis=1) > 10]  # 濾除評價數小于5的使用者,axis=1表示沿每一行索引下去
#print(len(check_data))   #check_data=428
for user in np.random.permutation(check_data.index):
    movie = np.random.permutation(check_data.loc[user].dropna().index)[0]
    check[(user, movie)] = check_data.loc[user, movie]
    check_data.loc[user, movie] = np.nan
    check_size -= 1
    if not check_size:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
        break

corr = check_data.T.corr(min_periods=10)
corr_clean = corr.dropna(how='all')
corr_clean = corr_clean.dropna(axis=1, how='all')  # 删除全空的行和列
check_ser = Series(check)  # 這裡是被提取出來的 300 個真實評分
#print(check_ser)
result = Series(np.nan, index=check_ser.index)
for user, movie in result.index:  # 這個循環看着很亂,實際内容就是權重平均而已
    prediction = []
    if user in corr_clean.index:
        corr_set = corr_clean[user][corr_clean[user] > 0.1].dropna()  # 僅限大于 0.1 的使用者
    else:
        continue
    for other in corr_set.index:
        if not np.isnan(data.loc[other, movie]) and other != user:  # 注意bool(np.nan)==True
            prediction.append((data.loc[other, movie], corr_set[other]))
        if prediction:
         result[(user, movie)] = sum([value * weight for value, weight in prediction]) / sum(
            [pair[1] for pair in prediction])

result.dropna(inplace=True)
#print(len(result))  # 随機抽取的 300 個使用者中也有被 min_periods=10 刷掉的,刷掉132個
#print(result.corr(check_ser.reindex(result.index)))
#print((result-check_ser.reindex(result.index)).abs().describe())

def user_based_cf():
    rnames = ['user_id', 'movie_id', 'rating', 'timestamp']
    ratings = pd.read_csv('./u1.test', sep='\t', header=None, names=rnames)
    data = ratings.pivot(index='user_id', columns='movie_id', values='rating')
    corr = data.T.corr(min_periods=5)
        #print(corr)

    corr_clean = corr.dropna(how='all')
        #print(corr_clean)

    corr_clean = corr_clean.dropna(axis=1, how='all')
    lucky = np.random.permutation(corr_clean.index)[0]

    gift = data.loc[lucky]
    gift = gift[gift.isnull()]
    corr_lucky = corr_clean[lucky].drop(lucky)  # lucky 與其他使用者的相關系數 Series,不包含 lucky 自身
    corr_lucky = corr_lucky[corr_lucky > 0.1].dropna()  # 篩選相關系數大于 0.1 的使用者
    for movie in gift.index:  # 周遊所有lucky沒看過的電影
        prediction = []
        for other in corr_lucky.index:  # 周遊所有與lucky 相關系數大于 0.1 的使用者
            if not np.isnan(data.loc[other, movie]):

                prediction.append((data.loc[other, movie], corr_clean[lucky][other]))
        if prediction:
            gift[movie] = sum([value * weight for value, weight in prediction]) / sum([pair[1] for pair in prediction])
    return gift.dropna().sort_values(ascending=False)

def main():
    list = user_based_cf()
    print(list)


if __name__ == "__main__":
    main()
           

繼續閱讀