概述:

  因为最近对算法这块进行了学习,所以最近对类似淘宝商品推荐的协同推荐算法进行了整理总结,本文将用php语言进行实现,文章将从以下几点进行终结:  

  (1)什么是协同推荐算法?有什么用?

  (2)依据什么数学方法公式,为什么要用它?

  (3)实现流程是怎样的?

  (4)具体实现步骤。

 

该算法的核心思想可以概括为:若a,b喜欢同一系列的物品(暂时称b是a的邻居吧),则a很可能喜欢b喜欢的其他物品。算法的实现流程可以简单概括为:1.确定a有哪些邻居 2.通过邻居来预测a可能会喜欢哪种物品  3.将a可能喜欢的物品推荐给a。

现在我们了解了这个核心思想以后,我们知道算法的核心是数学逻辑,我们必须理解其数学思想,然后再转化为编程思想达到我们的目标:

       我们先回忆一下余弦定理:

 

  

lightgbm推荐算法demo 推荐算法怎么实现_数组

  

  可见cosA的夹角越小cosA的值越大,则边c和边b的长度越相近,因此我们利用余弦定理的向量方式类推出如下公式:

1.余弦相似度(求邻居):

lightgbm推荐算法demo 推荐算法怎么实现_当前用户_02

2.预测公式(预测a可能会喜欢哪种物品):

lightgbm推荐算法demo 推荐算法怎么实现_lightgbm推荐算法demo_03

 

接下来我们介绍一下实现流程:

lightgbm推荐算法demo 推荐算法怎么实现_i++_04

 

 

 

 

现在我们具体看看怎样用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