侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

php用不了推荐算法吗

php  /  管理员 发布于 7年前   197

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];}//计算分母2if($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可以写前端吗
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 用Time Warden监控PHP中的代码处理时间(0个评论)
    • 在PHP中使用array_pop + yield实现读取超大型目录功能示例(0个评论)
    • Property Hooks RFC在PHP 8.4中越来越接近现实(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-11
    • 2017-12
    • 2018-01
    • 2018-02
    • 2018-03
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-09
    • 2021-02
    • 2021-03
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-09
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客