集體智慧 (Collective Intelligence) 並非 Web2.0 時代特有的,只是在 Web2.0 時代,你們在 Web 應用中利用集體智慧構建更加有趣的應用或者獲得更好的用戶體驗。集體智慧是指在大量的人羣的行爲和數據中收集答案,幫助你對整我的羣獲得統計意義上的結論,這些結論是咱們在單個個體上沒法獲得的,它每每是某種趨勢或者人羣中共性的部分。html
Wikipedia 和 Google 是兩個典型的利用集體智慧的 Web 2.0 應用:java
協同過濾是利用集體智慧的一個典型方法。要理解什麼是協同過濾 (Collaborative Filtering, 簡稱 CF),首先想一個簡單的問題,若是你如今想看個電影,但你不知道具體看哪部,你會怎麼作?大部分的人會問問周圍的朋友,看看最近有什麼好看的電影推薦,而咱們通常更傾向於從口味比較相似的朋友那裏獲得推薦。這就是協同過濾的核心思想。算法
協同過濾通常是在海量的用戶中發掘出一小部分和你品位比較相似的,在協同過濾中,這些用戶成爲鄰居,而後根據他們喜歡的其餘東西組織成一個排序的目錄做爲推薦給你。固然其中有一個核心的問題:apache
協同過濾相對於集體智慧而言,它從必定程度上保留了個體的特徵,就是你的品位偏好,因此它更多能夠做爲個性化推薦的算法思想。能夠想象,這種推薦策略在 Web 2.0 的長尾中是很重要的,將大衆流行的東西推薦給長尾中的人怎麼可能獲得好的效果,這也回到推薦系統的一個核心問題:瞭解你的用戶,而後才能給出更好的推薦。網絡
前面做爲背景知識,介紹了集體智慧和協同過濾的基本思想,這一節咱們將深刻分析協同過濾的原理,介紹基於協同過濾思想的多種推薦機制,優缺點和實用場景。框架
首先,要實現協同過濾,須要一下幾個步驟dom
要從用戶的行爲和偏好中發現規律,並基於此給予推薦,如何收集用戶的偏好信息成爲系統推薦效果最基礎的決定因素。用戶有不少方式向系統提供本身的偏好信息,並且不一樣的應用也可能大不相同,下面舉例進行介紹:機器學習
用戶行爲 | 類型 | 特徵 | 做用 |
---|---|---|---|
評分 | 顯式 | 整數量化的偏好,可能的取值是 [0, n];n 通常取值爲 5 或者是 10 | 經過用戶對物品的評分,能夠精確的獲得用戶的偏好 |
投票 | 顯式 | 布爾量化的偏好,取值是 0 或 1 | 經過用戶對物品的投票,能夠較精確的獲得用戶的偏好 |
轉發 | 顯式 | 布爾量化的偏好,取值是 0 或 1 | 經過用戶對物品的投票,能夠精確的獲得用戶的偏好。 若是是站內,同時能夠推理獲得被轉發人的偏好(不精確) |
保存書籤 | 顯示 | 布爾量化的偏好,取值是 0 或 1 | 經過用戶對物品的投票,能夠精確的獲得用戶的偏好。 |
標記標籤 (Tag) |
顯示 | 一些單詞,須要對單詞進行分析,獲得偏好 | 經過分析用戶的標籤,能夠獲得用戶對項目的理解,同時能夠分析出用戶的情感:喜歡仍是討厭 |
評論 | 顯示 | 一段文字,須要進行文本分析,獲得偏好 | 經過分析用戶的評論,能夠獲得用戶的情感:喜歡仍是討厭 |
點擊流 ( 查看 ) |
隱式 | 一組用戶的點擊,用戶對物品感興趣,須要進行分析,獲得偏好 | 用戶的點擊必定程度上反映了用戶的注意力,因此它也能夠從必定程度上反映用戶的喜愛。 |
頁面停留時間 | 隱式 | 一組時間信息,噪音大,須要進行去噪,分析,獲得偏好 | 用戶的頁面停留時間必定程度上反映了用戶的注意力和喜愛,但噪音偏大,很差利用。 |
購買 | 隱式 | 布爾量化的偏好,取值是 0 或 1 | 用戶的購買是很明確的說明這個項目它感興趣。 |
以上列舉的用戶行爲都是比較通用的,推薦引擎設計人員能夠根據本身應用的特色添加特殊的用戶行爲,並用他們表示用戶對物品的喜愛。ide
在通常應用中,咱們提取的用戶行爲通常都多於一種,關於如何組合這些不一樣的用戶行爲,基本上有如下兩種方式:函數
收集了用戶行爲數據,咱們還須要對數據進行必定的預處理,其中最核心的工做就是:減噪和歸一化。
進行的預處理後,根據不一樣應用的行爲分析方法,能夠選擇分組或者加權處理,以後咱們能夠獲得一個用戶偏好的二維矩陣,一維是用戶列表,另外一維是物品列表,值是用戶對物品的偏好,通常是 [0,1] 或者 [-1, 1] 的浮點數值。
當已經對用戶行爲進行分析獲得用戶喜愛後,咱們能夠根據用戶喜愛計算類似用戶和物品,而後基於類似用戶或者物品進行推薦,這就是最典型的 CF 的兩個分支:基於用戶的 CF 和基於物品的 CF。這兩種方法都須要計算類似度,下面咱們先看看最基本的幾種計算類似度的方法。
類似度的計算
關於類似度的計算,現有的幾種基本方法都是基於向量(Vector)的,其實也就是計算兩個向量的距離,距離越近類似度越大。在推薦的場景中,在用戶 - 物品偏好的二維矩陣中,咱們能夠將一個用戶對全部物品的偏好做爲一個向量來計算用戶之間的類似度,或者將全部用戶對某個物品的偏好做爲一個向量來計算物品之間的類似度。下面咱們詳細介紹幾種經常使用的類似度計算方法:
最初用於計算歐幾里德空間中兩個點的距離,假設 x,y 是 n 維空間的兩個點,它們之間的歐幾里德距離是:
能夠看出,當 n=2 時,歐幾里德距離就是平面上兩個點的距離。
當用歐幾里德距離表示類似度,通常採用如下公式進行轉換:距離越小,類似度越大
皮爾遜相關係數通常用於計算兩個定距變量間聯繫的緊密程度,它的取值在 [-1,+1] 之間。
sx, sy是 x 和 y 的樣品標準誤差。
Cosine 類似度被普遍應用於計算文檔數據的類似度:
Tanimoto 係數也稱爲 Jaccard 係數,是 Cosine 類似度的擴展,也多用於計算文檔數據的類似度:
類似鄰居的計算
介紹完類似度的計算方法,下面咱們看看如何根據類似度找到用戶 - 物品的鄰居,經常使用的挑選鄰居的原則能夠分爲兩類:圖 1 給出了二維平面空間上點集的示意圖。
不論鄰居的「遠近」,只取最近的 K 個,做爲其鄰居。如圖 1 中的 A,假設要計算點 1 的 5- 鄰居,那麼根據點之間的距離,咱們取最近的 5 個點,分別是點 2,點 3,點 4,點 7 和點 5。但很明顯咱們能夠看出,這種方法對於孤立點的計算效果很差,由於要取固定個數的鄰居,當它附近沒有足夠多比較類似的點,就被迫取一些不太類似的點做爲鄰居,這樣就影響了鄰居類似的程度,好比圖 1 中,點 1 和點 5 其實並非很類似。
與計算固定數量的鄰居的原則不一樣,基於類似度門檻的鄰居計算是對鄰居的遠近進行最大值的限制,落在以當前點爲中心,距離爲 K 的區域中的全部點都做爲當前點的鄰居,這種方法計算獲得的鄰居個數不肯定,但類似度不會出現較大的偏差。如圖 1 中的 B,從點 1 出發,計算類似度在 K 內的鄰居,獲得點 2,點 3,點 4 和點 7,這種方法計算出的鄰居的類似度程度比前一種優,尤爲是對孤立點的處理。
通過前期的計算已經獲得了相鄰用戶和相鄰物品,下面介紹如何基於這些信息爲用戶進行推薦。本系列的上一篇綜述文章已經簡要介紹過基於協同過濾的推薦算法能夠分爲基於用戶的 CF 和基於物品的 CF,下面咱們深刻這兩種方法的計算方法,使用場景和優缺點。
基於用戶的 CF(User CF)
基於用戶的 CF 的基本思想至關簡單,基於用戶對物品的偏好找到相鄰鄰居用戶,而後將鄰居用戶喜歡的推薦給當前用戶。計算上,就是將一個用戶對全部物品的偏好做爲一個向量來計算用戶之間的類似度,找到 K 鄰居後,根據鄰居的類似度權重以及他們對物品的偏好,預測當前用戶沒有偏好的未涉及物品,計算獲得一個排序的物品列表做爲推薦。圖 2 給出了一個例子,對於用戶 A,根據用戶的歷史偏好,這裏只計算獲得一個鄰居 - 用戶 C,而後將用戶 C 喜歡的物品 D 推薦給用戶 A。
基於物品的 CF(Item CF)
基於物品的 CF 的原理和基於用戶的 CF 相似,只是在計算鄰居時採用物品自己,而不是從用戶的角度,即基於用戶對物品的偏好找到類似的物品,而後根據用戶的歷史偏好,推薦類似的物品給他。從計算的角度看,就是將全部用戶對某個物品的偏好做爲一個向量來計算物品之間的類似度,獲得物品的類似物品後,根據用戶歷史的偏好預測當前用戶尚未表示偏好的物品,計算獲得一個排序的物品列表做爲推薦。圖 3 給出了一個例子,對於物品 A,根據全部用戶的歷史偏好,喜歡物品 A 的用戶都喜歡物品 C,得出物品 A 和物品 C 比較類似,而用戶 C 喜歡物品 A,那麼能夠推斷出用戶 C 可能也喜歡物品 C。
User CF vs. Item CF
前面介紹了 User CF 和 Item CF 的基本原理,下面咱們分幾個不一樣的角度深刻看看它們各自的優缺點和適用場景:
Item CF 和 User CF 是基於協同過濾推薦的兩個最基本的算法,User CF 是很早之前就提出來了,Item CF 是從 Amazon 的論文和專利發表以後(2001 年左右)開始流行,你們都以爲 Item CF 從性能和複雜度上比 User CF 更優,其中的一個主要緣由就是對於一個在線網站,用戶的數量每每大大超過物品的數量,同時物品的數據相對穩定,所以計算物品的類似度不但計算量較小,同時也沒必要頻繁更新。但咱們每每忽略了這種狀況只適應於提供商品的電子商務網站,對於新聞,博客或者微內容的推薦系統,狀況每每是相反的,物品的數量是海量的,同時也是更新頻繁的,因此單從複雜度的角度,這兩個算法在不一樣的系統中各有優點,推薦引擎的設計者須要根據本身應用的特色選擇更加合適的算法。
在非社交網絡的網站中,內容內在的聯繫是很重要的推薦原則,它比基於類似用戶的推薦原則更加有效。好比在購書網站上,當你看一本書的時候,推薦引擎會給你推薦相關的書籍,這個推薦的重要性遠遠超過了網站首頁對該用戶的綜合推薦。能夠看到,在這種狀況下,Item CF 的推薦成爲了引導用戶瀏覽的重要手段。同時 Item CF 便於爲推薦作出解釋,在一個非社交網絡的網站中,給某個用戶推薦一本書,同時給出的解釋是某某和你有類似興趣的人也看了這本書,這很難讓用戶信服,由於用戶可能根本不認識那我的;但若是解釋說是由於這本書和你之前看的某本書類似,用戶可能就以爲合理而採納了此推薦。
相反的,在現今很流行的社交網絡站點中,User CF 是一個更不錯的選擇,User CF 加上社會網絡信息,能夠增長用戶對推薦解釋的信服程度。
研究推薦引擎的學者們在相同的數據集合上分別用 User CF 和 Item CF 計算推薦結果,發現推薦列表中,只有 50% 是同樣的,還有 50% 徹底不一樣。可是這兩個算法確有類似的精度,因此能夠說,這兩個算法是很互補的。
關於推薦的多樣性,有兩種度量方法:
第一種度量方法是從單個用戶的角度度量,就是說給定一個用戶,查看系統給出的推薦列表是否多樣,也就是要比較推薦列表中的物品之間兩兩的類似度,不難想到,對這種度量方法,Item CF 的多樣性顯然不如 User CF 的好,由於 Item CF 的推薦就是和之前看的東西最類似的。
第二種度量方法是考慮系統的多樣性,也被稱爲覆蓋率 (Coverage),它是指一個推薦系統是否可以提供給全部用戶豐富的選擇。在這種指標下,Item CF 的多樣性要遠遠好於 User CF, 由於 User CF 老是傾向於推薦熱門的,從另外一個側面看,也就是說,Item CF 的推薦有很好的新穎性,很擅長推薦長尾裏的物品。因此,儘管大多數狀況,Item CF 的精度略小於 User CF, 但若是考慮多樣性,Item CF 卻比 User CF 好不少。
若是你對推薦的多樣性還心存疑惑,那麼下面咱們再舉個實例看看 User CF 和 Item CF 的多樣性到底有什麼差異。首先,假設每一個用戶興趣愛好都是普遍的,喜歡好幾個領域的東西,不過每一個用戶確定也有一個主要的領域,對這個領域會比其餘領域更加關心。給定一個用戶,假設他喜歡 3 個領域 A,B,C,A 是他喜歡的主要領域,這個時候咱們來看 User CF 和 Item CF 傾向於作出什麼推薦:若是用 User CF, 它會將 A,B,C 三個領域中比較熱門的東西推薦給用戶;而若是用 ItemCF,它會基本上只推薦 A 領域的東西給用戶。因此咱們看到由於 User CF 只推薦熱門的,因此它在推薦長尾裏項目方面的能力不足;而 Item CF 只推薦 A 領域給用戶,這樣他有限的推薦列表中就可能包含了必定數量的不熱門的長尾物品,同時 Item CF 的推薦對這個用戶而言,顯然多樣性不足。可是對整個系統而言,由於不一樣的用戶的主要興趣點不一樣,因此係統的覆蓋率會比較好。
從上面的分析,能夠很清晰的看到,這兩種推薦都有其合理性,但都不是最好的選擇,所以他們的精度也會有損失。其實對這類系統的最好選擇是,若是系統給這個用戶推薦 30 個物品,既不是每一個領域挑選 10 個最熱門的給他,也不是推薦 30 個 A 領域的給他,而是好比推薦 15 個 A 領域的給他,剩下的 15 個從 B,C 中選擇。因此結合 User CF 和 Item CF 是最優的選擇,結合的基本原則就是當採用 Item CF 致使系統對我的推薦的多樣性不足時,咱們經過加入 User CF 增長我的推薦的多樣性,從而提升精度,而當由於採用 User CF 而使系統的總體多樣性不足時,咱們能夠經過加入 Item CF 增長總體的多樣性,一樣一樣能夠提升推薦的精度。
前面咱們大部分都是從推薦引擎的角度考慮哪一個算法更優,但其實咱們更多的應該考慮做爲推薦引擎的最終使用者 -- 應用用戶對推薦算法的適應度。
對於 User CF,推薦的原則是假設用戶會喜歡那些和他有相同喜愛的用戶喜歡的東西,但若是一個用戶沒有相同喜愛的朋友,那 User CF 的算法的效果就會不好,因此一個用戶對的 CF 算法的適應度是和他有多少共同喜愛用戶成正比的。
Item CF 算法也有一個基本假設,就是用戶會喜歡和他之前喜歡的東西類似的東西,那麼咱們能夠計算一個用戶喜歡的物品的自類似度。一個用戶喜歡物品的自類似度大,就說明他喜歡的東西都是比較類似的,也就是說他比較符合 Item CF 方法的基本假設,那麼他對 Item CF 的適應度天然比較好;反之,若是自類似度小,就說明這個用戶的喜愛習慣並不知足 Item CF 方法的基本假設,那麼對於這種用戶,用 Item CF 方法作出好的推薦的可能性很是低。
鄰居模型一般也被稱爲k-最近鄰模型,或者簡稱爲kNN。KNN 模型能夠得到精確的推薦結果併爲結果給出合理的解釋,它們是CF 推薦系統中最先被使用也是直至目前最流行的一類模型。
PS:如下公式和圖片轉自博主本身的CSDN博客。
爲了得到用戶對產品的評分預測值,kNN 模型通常包括如下三步:
1. 計算類似度
這步中計算每對產品之間的類似度(similarity)。一些被普遍使用的類似度
測度包括:
Pearson correlation:
%% 載入訓練數據 load g:\matlab\協同過濾作推薦\dataset\Movielens\u1.base %% 數據預處理 % 提取數據的前三列,即用戶序號、被該用戶評價電影序號、評價分值 [m,n]=size(u1); test=zeros(m,3); for i=1:3 test(:,i)=u1(:,i); end %% 創建評分矩陣 number_user=max(test(:,1)); number_movies=max(test(:,2)); score_matrix=zeros(number_user,number_movies);%評分矩陣943*1682維 for i=1:m score_matrix(test(i,1),test(i,2))=test(i,3); end Sim_matrix=zeros(number_movies,number_movies);%類似度矩陣1642*1642維 tic; %計算評分矩陣 for i=1:number_movies-1 for j=i+1:number_movies Sim_matrix(i,j)=Similarity_ab(score_matrix,i,j); end end toc; %% 創建類似度矩陣 % function Neibor=neibor_select(Sim_matrix,a,n) neibor_num=10;%鄰居的大小 Sim_matrix=Sim_matrix'+Sim_matrix;%求完整的類似度矩陣 %neibor_sim_matrix_temp爲排好序的類似度矩陣 %neibor_matrix_temp各個類似度所對應的電影,也就是咱們要找的鄰居 value_1_index=find(Sim_matrix>=0.9999);%找出Sim_matrix矩陣中全部類似度爲1的值, %由於多是錯誤值,後期選擇鄰居不該考慮。 %爲何不是value_1_index=find(Sim_matrix==1)這樣有部分1不能正確找出,能夠試試看 Sim_matrix(value_1_index)=0;%將全部類似度爲1的值用0代替 % [neibor_sim_matrix_temp,neibor_matrix_temp]=sort(Sim_matrix,2,'descend'); % neibor_sim_matrix=zeros(number_movies,neibor_num); % neibor_matrix=zeros(number_movies,neibor_num); % for i=1:neibor_num % neibor_sim_matrix(:,i)=neibor_sim_matrix_temp(:,i);%每一個鄰居對應的類似度 % neibor_matrix(:,i)=neibor_matrix_temp(:,i);%鄰居 % end %% 載入測試集 load g:\matlab\協同過濾作推薦\dataset\Movielens\u1.test %% 做預測 [m,n]=size(u1); test=zeros(m,3); for i=1:3 test(:,i)=u1(:,i); end Predict_score=zeros(m,1); for j=1:m P_u=find(score_matrix(test(j,1),:)~=0);%找出該用戶評價的電影集合 [~,num]=size(P_u);%計算該用戶評價的電影個數 %%%%%%%%%%%計算鄰居%%%%%%%%%%%% neibor_num=10;%最大爲4 P_u_sim=Sim_matrix(test(j,2),P_u); [temp,index]=sort(P_u_sim,2,'descend'); [~,num1]=size(index); if num1>=neibor_num neibor=(P_u(index(1:neibor_num))); else neibor=(P_u(index)); neibor_num=num1; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sum_score=sum(score_matrix(test(j,1),:),2);%該用戶對全部電影的總評分 aver_score=sum_score/num;%該用戶對電影的平均評分 sum1=0; sum2=0; for i=1:neibor_num sum1=sum1+Sim_matrix(test(j,2),neibor(i))*(score_matrix(test(j,1),neibor(i))-aver_score); sum2=sum2+Sim_matrix(test(j,2),neibor(i)); end if sum2==0 Predict_score(j,1)=round(aver_score);%排除分母爲零的狀況 else Predict_score(j,1)=round(aver_score+sum1/sum2); %確保預測值爲1~5的評分數 if Predict_score(j,1)>5 Predict_score(j,1)=5; elseif Predict_score(j,1)<1 Predict_score(j,1)=1; end end end %% 計算RMSE Eval=zeros(m,3); Eval(:,1)=test(:,3); Eval(:,2)=Predict_score(:,1); Eval(:,3)=abs(test(:,3)-Predict_score(:,1)); RMSE=sqrt(Eval(:,3)'*Eval(:,3)/m);
Similarity_ab()函數的實現(PS:好久以前寫的程序,發現有幾位博友找我要相關代碼看一下,我儘可能找了找,僅供感興趣的同窗參考,不喜勿噴哈,更新時間 2016.07.11晚):
%利用Adjusted Cosine法計算電影a和b的類似度 %這個算法雖然能夠求出類似度矩陣,可是有個問題就是,當共同評價電影a和b的用戶 %只有一個的時候,結果只有兩種可能,即1或者是-1。這就須要在找鄰居時要避免選擇 %這些狀況的類似度電影。 function Sim_ab=Similarity_ab(score_matrix,a,b) %找出全部評價所電影a和b的用戶集合(標號) %function P_ab=Rate_both_ab(score_matrix,a,b) temp=score_matrix(:,a)&score_matrix(:,b); P_ab=find(temp); P_ab=P_ab';%用行向量存儲全部評價電影a和b的用戶 %end %% 利用Adjusted Cosine法計算類似度 if isempty(P_ab) Sim_ab=0; else [~,temp]=size(P_ab);%共同評價電影a和b的用戶的數目 %[~,number_movies]=size(score_matrix); sum1=0; sum2=0; sum3=0; for i=1:temp [~,m]=size(find(score_matrix(P_ab(i),:)~=0));%計算該用戶評價的電影個數 sum_score=sum(score_matrix(P_ab(i),:),2);%用戶對全部電影的總評分 aver_score=sum_score/m; sum1=sum1+(score_matrix(P_ab(i),a)-aver_score)*(score_matrix(P_ab(i),b)-aver_score); sum2=sum2+(score_matrix(P_ab(i),a)-aver_score)^2; sum3=sum3+(score_matrix(P_ab(i),b)-aver_score)^2; end if sum2==0||sum3==0 Sim_ab=0; else Sim_ab=sum1/sqrt(sum2*sum3); end end
Web2.0 的一個核心思想就是「集體智慧」,基於協同過濾的推薦策略的基本思想就是基於大衆行爲,爲每一個用戶提供個性化的推薦,從而使用戶能更快速更準確的發現所須要的信息。從應用角度分析,現今比較成功的推薦引擎,好比 Amazon,豆瓣,噹噹等都採用了協同過濾的方式,它不須要對物品或者用戶進行嚴格的建模,並且不要求物品的描述是機器可理解的,是中領域無關的推薦方法,同時這個方法計算出來的推薦是開放的,能夠共用他人的經驗,很好的支持用戶發現潛在的興趣偏好。基於協同過濾的推薦策略也有不一樣的分支,它們有不一樣的實用場景和推薦效果,用戶能夠根據本身應用的實際狀況選擇合適的方法,異或組合不一樣的方法獲得更好的推薦效果。