概述:
因為最近對算法這塊進行了學習,所以最近對類似淘寶商品推薦的協同推薦算法進行了整理總結,本文將用php語言進行實現,文章將從以下幾點進行終結:
(1)什么是協同推薦算法?有什么用?
(2)依據什么數學方法公式,為什么要用它?
(3)實現流程是怎樣的?
(4)具體實現步驟。
首先,第一點,我們要實現一個算法必須要知道它有什么用,核心思想是什么?顧名思義,它的用途就是用來給我們做一些相似性推薦,推薦你喜歡的恭喜,根據你的好友等預測你喜歡的然后再推薦給你;我們舉個例子來概括一下算法的核心思想:該算法的核心思想可以概括為:若a,b喜歡同一系列的物品(暫時稱b是a的鄰居吧),則a很可能喜歡b喜歡的其他物品。算法的實現流程可以簡單概括為:1.確定a有哪些鄰居 2.通過鄰居來預測a可能會喜歡哪種物品 3.將a可能喜歡的物品推薦給a。
現在我們了解了這個核心思想以后,我們知道算法的核心是數學邏輯,我們必須理解其數學思想,然后再轉化為編程思想達到我們的目標:
我們先回憶一下余弦定理:
可見cosA的夾角越小cosA的值越大,則邊c和邊b的長度越相近,因此我們利用余弦定理的向量方式類推出如下公式:
1.余弦相似度(求鄰居):
2.預測公式(預測a可能會喜歡哪種物品):
接下來我們介紹一下實現流程:
現在我們具體看看怎樣用php實現這個算法:
(1)數據准備:在這里我們直接定義一組數據
$userarray= [ ['name'=>'A','a'=>3,'b'=>2,'c'=>1,'d'=>5,'e'=>null,'f'=>null,'g'=>null], ['name'=>'B','a'=>1,'b'=>6,'c'=>6,'d'=>5,'e'=>2,'f'=>3,'g'=>5], ['name'=>'C','a'=>3,'b'=>5,'c'=>null,'d'=>4,'e'=>3,'f'=>3,'g'=>6], ['name'=>'D','a'=>4,'b'=>1,'c'=>1,'d'=>5,'e'=>3,'f'=>3,'g'=>3], ['name'=>'E','a'=>5,'b'=>1,'c'=>null,'d'=>4,'e'=>5,'f'=>1,'g'=>5], ['name'=>'F','a'=>1,'b'=>3,'c'=>2,'d'=>5,'e'=>6,'f'=>null,'g'=>4], ['name'=>'G','a'=>1,'b'=>5,'c'=>2,'d'=>5,'e'=>2,'f'=>3ll,'g'=>5] ];
(2)我們以A用戶為對象分別計算出他們的余弦相似度,然后將其存入數組$cos中:
/* * 以下示例只求A的推薦 */ $denominator_left = 0;//分母左邊初始值 //開始計算cos //計算分母左邊 for($i=1;$i<8;$i++){ if($userarray[0][$i] != null){//$userarray[0]代表A $denominator_left += $userarray[0][$i] * $userarray[0][$i]; } } $denominator_left = sqrt($denominator_left);//取算數平方根的值 for($i=1;$i<6;$i++){ $numerator = 0;//分子初始值 $denominator_right = 0;//分母右邊初始值 for($j=1;$j<8;$j++){ //計算分子 if($userarray[0][$j] != null && $userarray[$i][$j] != null){ $numerator += $userarray[0][$j] * $userarray[$i][$j]; } //計算分母右邊 if($userarray[$i][$j] != null){ $denominator_right += $userarray[$i][$j] * $userarray[$i][$j]; } } $denominator_right = sqrt($denominator_right );
$cos[$i]['cos'] = $numerator /$denominator_left /$denominator_right ;//存儲當前用戶的cos近似值
$cos[$i]['name'] = $userarray[$i]['name'];//存儲當前用戶的名字
$cos[$i]['e'] = $userarray[$i]['e'];//存儲當前用戶的e物品評分
$cos[$i]['f'] = $userarray[$i]['f'];//存儲當前用戶的f物品評分
$cos[$i]['g'] = $userarray[$i]['g'];//存儲當前用戶的g物品評分
}
(3)我們對余弦近似值進行由大到小的排序,抽取前三個用戶作為A用戶的鄰居,我們使用冒泡排序法對其進行排序
// 第一層可以理解為從數組中鍵為0開始循環到最后一個 for ($i = 0; $i < count($cos) ; $i++) { // 第二層為從$i+1的地方循環到數組最后 for ($j = $i+1; $j < count($cos); $j++) { // 比較數組中兩個相鄰值的大小 if ($cos[$i]['cos'] < $cos[$j]['cos']) { $tem = $cos[$i]; // 這里臨時變量,存貯$i的值 $cos[$i] = $cos[$j]; // 第一次更換位置 $cos[$j] = $tem; // 完成位置互換 } } }
(4)接下來我們對A用戶可能喜歡的物品進行預測,利用第二個公式,求出product值
//計算A對e的評分 $numerator= 0;//分子初始值 $denominator= 0;//分母初始值 for($i=0;$i<3;$i++){ $numerator+= $cos[$i]['cos'] * $cos[$i]['e']; $denominator+= $cos[$i]['cos']; } $score_e = $numerator/sqrt($denominator); //計算A對f的評分 $numerator= 0;//分子初始值 $denominator= 0;//分母初始值 for($i=0;$i<3;$i++){ $numerator+= $cos[$i]['cos'] * $cos[$i]['f']; $denominator+= $cos[$i]['cos']; } $score_f= $numerator/sqrt($denominator); //計算A對g的評分 $numerator= 0;//分子初始值 $denominator= 0;//分母初始值 for($i=0;$i<3;$i++){ $numerator+= $cos[$i]['cos'] * $cos[$i]['g']; $denominator+= $cos[$i]['cos']; } $score_g= $numerator/sqrt($denominator);
最后我們可以比較這些值,可以選取值最大的物品推薦給用戶A