类别:PHP问题 / 日期:2019-11-26 / 浏览:173 / 评论:0

php用不了引荐算法吗?

引荐算法是异常陈旧的,在机械进修还没有鼓起的时刻就有需乞降应用了。

协同过滤(Collaborative Filtering)作为引荐算法中最典范的范例,包含在线的协同离线的过滤两部分。所谓在线协同,就是经由历程在线数据找到用户能够喜好的物品,而离线过滤,则是过滤掉一些不值得引荐的数据,比比方引荐值评分低的数据,或许虽然引荐值高然则用户已购置的数据。

下面就引见下怎样用PHP+MySQL完成简朴的协同过滤算法。

要完成协同过滤引荐算法,起首就要明白算法的中心头脑和流程。该算法的中心头脑能够归纳综合为:若a,b喜好统一系列的物品(临时称b是a的邻人吧),则a极能够喜好b喜好的其他物品。算法的完成流程能够简朴归纳综合为:1.肯定a有哪些邻人 2.经由历程邻人来展望a能够会喜好哪一种物品 3.将a能够喜好的物品引荐给a。

算法中心的公式以下:

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

2.展望公式(展望a能够会喜好哪一种物品):

仅从这两个公式我们就能够看出,仅仅是根据这两个公式举行盘算,就须要举行大批的轮回与推断,而且还涉及到排序的题目,就涉及到排序算法的挑选与运用,这里选快排。

起首建表:

DROP TABLE IF EXISTS `tb_xttj`;
CREATE TABLE `tb_xttj` (
  `name` varchar(255) NOT NULL,
  `a` int(255) default NULL,
  `b` int(255) default NULL,
  `c` int(255) default NULL,
  `d` int(255) default NULL,
  `e` int(255) default NULL,
  `f` int(255) default NULL,
  `g` int(255) default NULL,
  `h` int(255) default NULL,
  PRIMARY KEY  (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 
INSERT INTO `tb_xttj` VALUES ('John', '4', '4', '5', '4', '3', '2', '1', null);
INSERT INTO `tb_xttj` VALUES ('Mary', '3', '4', '4', '2', '5', '4', '3', null);
INSERT INTO `tb_xttj` VALUES ('Lucy', '2', '3', null, '3', null, '3', '4', '5');
INSERT INTO `tb_xttj` VALUES ('Tom', '3', '4', '5', null, '1', '3', '5', '4');
INSERT INTO `tb_xttj` VALUES ('Bill', '3', '2', '1', '5', '3', '2', '1', '1');
INSERT INTO `tb_xttj` VALUES ('Leo', '3', '4', '5', '2', '4', null, null, null);

这里只对末了一行的Leo举行引荐,看看f,g,h哪一个能够引荐给他。

用php+mysql,流程图以下:

衔接数据库并将其存储为二维数组的代码以下:

header("Content-Type:text/html;charset=utf-8");
 
mysql_connect("localhost","root","admin");
mysql_select_db("geodatabase");
mysql_query("set names 'utf8'");
 
$sql = "SELECT * FROM tb_xttj";
$result = mysql_query($sql);
 
$array = array();
while($row=mysql_fetch_array($result))
{
$array[]=$row;//$array[][]是一个二维数组
}

题目1:这一步完全能够看作是整表查询,这类查询是大忌,关于这类小小的演示体系还能够,然则对大数据的体系,没有效力。

求Leo与其别人的Cos值代码以下:

/*
 * 以下示例只求Leo的引荐,云云给变量定名我也是醉了;首次明白算法,先不斟酌效力和逻辑的题目,主要把历程做出来
 */
 
$cos = array();
$cos[0] = 0;
$fm1 = 0;
//最先盘算cos
//盘算分母1,分母1是第一个公式内里 “*”号左侧的内容,分母二是右侧的内容
for($i=1;$i<9;$i++){
if($array[5][$i] != null){//$array[5]代表Leo
$fm1 += $array[5][$i] * $array[5][$i];
}
}
 
$fm1 = sqrt($fm1);
 
for($i=0;$i<5;$i++){
$fz = 0;
$fm2 = 0;
echo "Cos(".$array[5][0].",".$array[$i][0].")=";
for($j=1;$j<9;$j++){
    //盘算份子
if($array[5][$j] != null && $array[$i][$j] != null){
$fz += $array[5][$j] * $array[$i][$j];
}
//盘算分母2
if($array[$i][$j] != null){
$fm2 += $array[$i][$j] * $array[$i][$j];
}
}
$fm2 = sqrt($fm2);
$cos[$i] = $fz/$fm1/$fm2;
echo $cos[$i]."<br/>";
}

这一步获得的效果:

将求好的Cos值排序,采纳快排代码以下:

//对盘算效果举行排序,凑合用快排吧先
function quicksort($str){
if(count($str)<=1) return $str;//假如个数不大于一,直接返回
$key=$str[0];//取一个值,稍后用来比较;
$left_arr=array();
$right_arr=array();
for($i=1;$i<count($str);$i++){//比$key大的放在右侧,小的放在左侧;
if($str[$i]>=$key)
$left_arr[]=$str[$i];
else
$right_arr[]=$str[$i];
}
$left_arr=quicksort($left_arr);//举行递归;
$right_arr=quicksort($right_arr);
return array_merge($left_arr,array($key),$right_arr);//将左中右的值兼并成一个数组;
}
 
$neighbour = array();//$neighbour只是对cos值举行排序并存储
$neighbour = quicksort($cos);

这里的$neighbour数组仅仅存储了从大到小排序好的Cos值,并没有与人联系起来。这个题目还要处置惩罚。

选出Cos值最高的3个人,作为Leo的邻人:

//$neighbour_set 存储最近邻的人和cos值
$neighbour_set = array();
for($i=0;$i<3;$i++){
for($j=0;$j<5;$j++){
if($neighbour[$i] == $cos[$j]){
$neighbour_set[$i][0] = $j;
$neighbour_set[$i][1] = $cos[$j];
$neighbour_set[$i][2] = $array[$j][6];//邻人对f的评分
$neighbour_set[$i][3] = $array[$j][7];//邻人对g的评分
$neighbour_set[$i][4] = $array[$j][8];//邻人对h的评分
}
}
}
print_r($neighbour_set);
echo "<p><br/>";

这一步获得的效果:

这是一个二维数组,数组第一层的下标为0,1,2,代表3个人。第二层下标0代表邻人在数据表中的递次,比方Jhon是表中的第0个人;下标1代表Leo和邻人的Cos值;下标2,3,4离别代表邻人对f,g,h的评分。

最先举行展望,盘算Predict代码以下:

离别盘算Leo对f,g,h的展望值。在此有一个题目,就是假如有的邻人对f,g,h的评分为空,那末该怎样处置惩罚。比方Jhon和Mary对h的评分就为空。天性的想到用if推断一下,假如为空则跳过这组盘算,不过如许处置惩罚是不是合理,有待斟酌。以下代码并没有写出这个if推断。

//盘算Leo对f的评分
$p_arr = array();
$pfz_f = 0;
$pfm_f = 0;
for($i=0;$i<3;$i++){
$pfz_f += $neighbour_set[$i][1] * $neighbour_set[$i][2];
$pfm_f += $neighbour_set[$i][1];
}
$p_arr[0][0] = 6;
$p_arr[0][1] = $pfz_f/sqrt($pfm_f);
if($p_arr[0][1]>3){
echo "引荐f";
}
 
//盘算Leo对g的评分
$pfz_g = 0;
$pfm_g = 0;
for($i=0;$i<3;$i++){
$pfz_g += $neighbour_set[$i][1] * $neighbour_set[$i][3];
$pfm_g += $neighbour_set[$i][1];
$p_arr[1][0] = 7;
$p_arr[1][1] = $pfz_g/sqrt($pfm_g);
}
if($p_arr[0][1]>3){
echo "引荐g";
}
 
//盘算Leo对h的评分
$pfz_h = 0;
$pfm_h = 0;
for($i=0;$i<3;$i++){
$pfz_h += $neighbour_set[$i][1] * $neighbour_set[$i][4];
$pfm_h += $neighbour_set[$i][1];
$p_arr[2][0] = 8;
$p_arr[2][1] = $pfz_h/sqrt($pfm_h);
}
print_r($p_arr);
if($p_arr[0][1]>3){
echo "引荐h";
}
$p_arr是对Leo的引荐数组,其内容相似以下;
Array ( [0] => Array ( [0] => 6 [1] => 4.2314002228795 ) [1] => Array ( [0] => 7 [1] => 2.6511380196197 ) [2] => Array ( [0] => 8 [1] => 0.45287424581774 ) )

f是第6列,Predict值是4.23,g是第七列,Predict值是2.65........

求完了f,g,h的Predict值后有两种处置惩罚方式:一种是将Predict值大于3的物品引荐给Leo,另一种是将Predict值从大到小排序,将Predict值大的前2个物品引荐给Leo。这段代码没有写。

从上面的示例中能够看出,引荐算法的完成异常贫苦,须要轮回,推断,兼并数组等等。假如处置惩罚不当,反而会成为体系的累坠。在现实处置惩罚中另有以下题目:

1.以上示例我们只对Leo举行引荐,而且我们已晓得Leo没有评价过f,g,h物品。假如放到现实的体系里,关于每个须要举行引荐的用户,都要查询出他没有评价过哪些物品,这又是一部分开支。

2.不应该举行整表查询,在现实体系中能够设定一些规范值。比方:我们求Leo与表中的其别人的Cos值,假如该值大于0.80,则示意能够为邻人。如许,当我找到10个邻人以后,就住手求Cos值,防止整表查询。关于引荐物品也能够恰当采纳此要领,比方,我只引荐10个物品,引荐完后就住手求Predict值。

3.跟着体系的运用,物品也会发生变化,今天是fgh,来日诰日没准就是xyz了,当物品变化时,须要动态的转变数据表。

4.能够恰当引进基于内容的引荐,来完美引荐算法。

5.引荐的准确性题目,这个设置差别的规范值,会影响准确性。

更多PHP相干学问,请接见ki4网!

以上就是php用不了引荐算法吗的细致内容,更多请关注ki4网别的相干文章!

打赏

感谢您的赞助~

打开支付宝扫一扫,即可进行扫码打赏哦~

版权声明 : 本文未使用任何知识共享协议授权,您可以任何形式自由转载或使用。

 可能感兴趣的文章