php用不了推荐算法吗-PHP问题

资源魔 34 0

php用没有了保举算法吗?

保举算法长短常陈旧的,正在机械学习尚未衰亡的时分就有需要以及使用了。

协同过滤(Collaborative Filtering)作为保举算法中最经典的类型,包罗正在线的协同以及离线的过滤两局部。所谓正在线协同,就是经过正在线数据找到用户可能喜爱的物品,而离线过滤,则是过滤掉一些没有值患上保举的数据,比比方保举值评分低的数据,或许尽管保举值高然而用户曾经采办的数据。

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

要完成协同过滤保举算法,起首就要了解算法的外围思维以及流程。该算法的外围思维能够归纳综合为:若a,b喜爱同一系列的物品(临时称b是a的街坊吧),则a极可能喜爱b喜爱的其余物品。算法的完成流程能够简略归纳综合为:1.确定a有哪些街坊 2.经过街坊来预测a可能会喜爱哪一种物品 3.将a可能喜爱的物品保举给a。

算法外围的公式以下:

1.余弦类似度(求街坊):

1.jpg

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

2.png

仅从这两个公式咱们就能够看出,仅仅是依照这两个公式进行较量争论,就需求进行年夜量的轮回与判别,并且还触及到排序的成绩,就触及到排序算法的抉择与应用,这里选快排。

起首建表:

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);

3.jpg

这里只对最初一行的Leo进行保举,看看f,g,h哪一个能够保举给他。

用php+mysql,流程图以下:

4.jpg

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

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/>";
}

这一步失去的后果:

5.jpg

将求好的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/>";

这一步失去的后果:

7.jpg这是一个二维数组,数组第一层的下标为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相干常识,请拜访PHP中文网!

以上就是php用没有了保举算法吗的具体内容,更多请存眷资源魔其它相干文章!

标签: php php教程 php故障解决 php使用问题 推荐算法

抱歉,评论功能暂时关闭!