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

PHP实现机器学习之朴素贝叶斯算法详解

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

本文实例讲述了PHP实现机器学习之朴素贝叶斯算法。分享给大家供大家参考,具体如下:

机器学习已经在我们的生活中变得随处可见了。比如从你在家的时候温控器开始工作到智能汽车以及我们口袋中的智能手机。机器学习看上去已经无处不在并且是一个非常值得探索的领域。但是什么是机器学习呢?通常来说,机器学习就是让系统不断的学习并且对新的问题进行预测。从简单的预测购物商品到复杂的数字助理预测。

在这篇文章我将会使用朴素贝叶斯算法Clasifier作为一个类来介绍。这是一个简单易于实施的算法,并且可给出满意的结果。但是这个算法是需要一点统计学的知识去理解的。在文章的最后部分你可以看到一些实例代码,甚至自己去尝试着自己做一下你的机器学习。

起步

那么,这个Classifier是要用来实现什么功能呢?其实它主要是用来判断给定的语句是积极地还是消极的。比如,“Symfony is the best”是一个积极的语句,“No Symfony is bad”是一个消极的语句。所以在给定了一个语句之后,我想让这个Classifier在我不给定一个新的规则的情况就返回一个语句类型。

我给Classifier命名了一个相同名称的类,并且包含一个guess方法。这个方法接受一个语句的输入,并且会返回这个语句是积极的还是消极的。这个类就像下面这样:

class Classifier{ public function guess($statement) {}}

我更喜欢使用枚举类型的类而不是字符串作为我的返回值。我将这个枚举类型的类命名为Type,并且包含两个常量:一个POSITIVE,一个NEGATIVE。这两个常量将会当做guess方法的返回值。

class Type{ const POSITIVE = 'positive'; const NEGATIVE = 'negative';}

初始化工作已经完成,接下来就是要编写我们的算法进行预测了。

朴素贝叶斯

朴素贝叶斯算法是基于一个训练集合工作的,根据这个训练集从而做出相应的预测。这个算法运用了简单的统计学以及一点数学去进行结果的计算。比如像下面四个文本组成的训练集合:

语句 类型
Symfony is the best Positive
PhpStorm is great Positive
Iltar complains a lot Negative
No Symfony is bad Negative


如果给定语句是“Symfony is the best”,那么你可以说这个语句是积极地。你平常也会根据之前学习到的相应知识做出对应的决定,朴素贝叶斯算法也是同样的道理:它根据之前的训练集来决定哪一个类型更加相近。

学习

在这个算法正式工作之前,它需要大量的历史信息作为训练集。它需要知道两件事:每一个类型对应的词产生了多少次和每一个语句对应的类型是什么。我们在实施的时候会将这两种信息存储在两个数组当中。一个数组包含每一类型的词语统计,另一个数组包含每一个类型的语句统计。所有的其他信息都可以从这两个数组中聚合。代码就像下面的一样:

function learn($statement, $type){ $words = $this->getWords($statement); foreach ($words as $word) { if (!isset($this->words[$type][$word])) {  $this->words[$type][$word] = 0; } $this->words[$type][$word]++; // 增加类型的词语统计 } $this->documents[$type]++; // 增加类型的语句统计}

有了这个集合以后,现在这个算法就可以根据历史数据接受预测训练了。

定义

为了解释这个算法是如何工作的,几个定义是必要的。首先,让我们定义一下输入的语句是给定类型中的一个的概率。这个将会表示为P(Type)。它是以已知类型的数据的类型作为分子,还有整个训练集的数据数量作为分母来得出的。一个数据就是整个训练集中的一个。到现在为止,这个方法可以将会命名为totalP,像下面这样:

function totalP($type){ return ($this->documents[$type] + 1) / (array_sum($this->documents) + 1);}

请注意,在这里分子和分母都加了1。这是为了避免分子和分母都为0的情况。

根据上面的训练集的例子,积极和消极的类型都会得出0.6的概率。每中类型的数据都是2个,一共是4个数据所以就是(2+1)/(4+1)。

第二个要定义的是对于给定的一个词是属于哪个确定类型的概率。这个我们定义成P(word,Type)。首先我们要得到一个词在训练集中给出确定类型出现的次数,然后用这个结果来除以整个给定类型数据的词数。这个方法我们定义为p:

function p($word, $type){ $count = isset($this->words[$type][$word]) ? $this->words[$type][$word] : 0; return ($count + 1) / (array_sum($this->words[$type]) + 1);}

在本次的训练集中,“is”的是积极类型的概率为0.375。这个词在整个积极的数据中的7个词中占了两次,所以结果就是(2+1)/(7+1)。

最后,这个算法应该只关心关键词而忽略其他的因素。一个简单的方法就是将给定的字符串中的单词分离出来:

function getWords($string){ return preg_split('/\s+/', preg_replace('/[^A-Za-z0-9\s]/', '', strtolower($string)));}

准备工作都做好了,开始真正实施我们的计划吧!

预测

为了预测语句的类型,这个算法应该计算所给定语句的两个类型的概率。像上面一样,我们定义一个P(Type,sentence)。得出概率高的类型将会是Classifier类中算法返回的结果。

为了计算P(Type,sentence),算法当中将用到贝叶斯定理。算法像这样被定义:P(Type,sentence)= P(Type)* P(sentence,Type)/ P(sentence)。这意味着给定语句的类型概率和给定类型语句概率除以语句的概率的结果是相同的。

那么算法在计算每一个相同语句的P(Tyoe,sentence),P(sentence)是保持一样的。这意味着算法就可以省略其他因素,我们只需要关心最高的概率而不是实际的值。计算就像这样:P(Type,sentence) = P(Type)* P(sentence,Type)。

最后,为了计算P(sentence,Type),我们可以为语句中的每个词添加一条链式规则。所以在一条语句中如果有n个词的话,它将会和P(word_1,Type)* P(word_2,Type)* P(word_3,Type)* .....*P(word_n,Type)是一样的。每一个词计算结果的概率使用了我们前面看到的定义。

好了,所有的都说完了,是时候在php中实际操作一下了:

function guess($statement){ $words = $this->getWords($statement); // 得到单词 $best_likelihood = 0; $best_type = null; foreach ($this->types as $type) { $likelihood = $this->pTotal($type); //计算 P(Type) foreach ($words as $word) {  $likelihood *= $this->p($word, $type); // 计算 P(word, Type) } if ($likelihood > $best_likelihood) {  $best_likelihood = $likelihood;  $best_type = $type; } } return $best_type;}

这就是所有的工作,现在算法可以预测语句的类型了。你要做的就是让你的算法开始学习:

$classifier = new Classifier();$classifier->learn('Symfony is the best', Type::POSITIVE);$classifier->learn('PhpStorm is great', Type::POSITIVE);$classifier->learn('Iltar complains a lot', Type::NEGATIVE);$classifier->learn('No Symfony is bad', Type::NEGATIVE);var_dump($classifier->guess('Symfony is great')); // string(8) "positive"var_dump($classifier->guess('I complain a lot')); // string(8) "negative"

所有的代码我已经上传到了GIT上,https://github.com/yannickl88/blog-articles/blob/master/src/machine-learning-naive-bayes/Classifier.php

github上完整php代码如下:

 [], Type::NEGATIVE => []]; private $documents = [Type::POSITIVE => 0, Type::NEGATIVE => 0]; public function guess($statement) { $words  = $this->getWords($statement); // get the words $best_likelihood = 0; $best_type = null; foreach ($this->types as $type) {  $likelihood = $this->pTotal($type); // calculate P(Type)  foreach ($words as $word) {  $likelihood *= $this->p($word, $type); // calculate P(word, Type)  }  if ($likelihood > $best_likelihood) {  $best_likelihood = $likelihood;  $best_type = $type;  } } return $best_type; } public function learn($statement, $type) { $words = $this->getWords($statement); foreach ($words as $word) {  if (!isset($this->words[$type][$word])) {  $this->words[$type][$word] = 0;  }  $this->words[$type][$word]++; // increment the word count for the type } $this->documents[$type]++; // increment the document count for the type } public function p($word, $type) { $count = 0; if (isset($this->words[$type][$word])) {  $count = $this->words[$type][$word]; } return ($count + 1) / (array_sum($this->words[$type]) + 1); } public function pTotal($type) { return ($this->documents[$type] + 1) / (array_sum($this->documents) + 1); } public function getWords($string) { return preg_split('/\s+/', preg_replace('/[^A-Za-z0-9\s]/', '', strtolower($string))); }}$classifier = new Classifier();$classifier->learn('Symfony is the best', Type::POSITIVE);$classifier->learn('PhpStorm is great', Type::POSITIVE);$classifier->learn('Iltar complains a lot', Type::NEGATIVE);$classifier->learn('No Symfony is bad', Type::NEGATIVE);var_dump($classifier->guess('Symfony is great')); // string(8) "positive"var_dump($classifier->guess('I complain a lot')); // string(8) "negative"

结束语

尽管我们只进行了很少的训练,但是算法还是应该能给出相对精确的结果。在真实环境,你可以让机器学习成百上千的记录,这样就可以给出更精准的结果。你可以下载查看这篇文章(英文):朴素贝叶斯已经被证明可以给出情绪统计的结果。

而且,朴素贝叶斯不仅仅可以运用到文本类的应用。希望通过这篇文章可以拉近你和机器学习的一点点距离。

原文地址:https://stovepipe.systems/post/machine-learning-naive-bayes

更多关于PHP相关内容感兴趣的读者可查看本站专题:《PHP数据结构与算法教程》、《php程序设计算法总结》、《php字符串(string)用法总结》、《PHP数组(Array)操作技巧大全》、《PHP常用遍历算法与技巧总结》及《PHP数学运算技巧总结》

希望本文所述对大家PHP程序设计有所帮助。

您可能感兴趣的文章:

  • python中文分词教程之前向最大正向匹配算法详解
  • PHP实现的字符串匹配算法示例【sunday算法】
  • 基于PHP实现栈数据结构和括号匹配算法示例
  • php中最简单的字符串匹配算法
  • PHP基于二分法实现数组查找功能示例【循环与递归算法】
  • PHP基于回溯算法解决n皇后问题的方法示例
  • PHP实现找出数组中出现次数超过数组长度一半的数字算法示例
  • php 二维数组快速排序算法的实现代码
  • PHP实现的贪婪算法实例
  • PHP实现的折半查询算法示例
  • PHP实现的最大正向匹配算法示例


  • 上一条:
    PHP实现单链表翻转操作示例
    下一条:
    PHP中利用Telegram的接口实现免费的消息通知功能
  • 昵称:

    邮箱:

    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个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(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个评论)
    • 近期评论
    • 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交流群

    侯体宗的博客