欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法詳解

 更新時(shí)間:2017年12月06日 14:48:25   作者:PHPChina-春陽(yáng)  
這篇文章主要介紹了PHP實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法,結(jié)合實(shí)例形式詳細(xì)分析了樸素貝葉斯算法的概念、原理及php實(shí)現(xiàn)技巧,需要的朋友可以參考下

本文實(shí)例講述了PHP實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法。分享給大家供大家參考,具體如下:

機(jī)器學(xué)習(xí)已經(jīng)在我們的生活中變得隨處可見了。比如從你在家的時(shí)候溫控器開始工作到智能汽車以及我們口袋中的智能手機(jī)。機(jī)器學(xué)習(xí)看上去已經(jīng)無(wú)處不在并且是一個(gè)非常值得探索的領(lǐng)域。但是什么是機(jī)器學(xué)習(xí)呢?通常來(lái)說(shuō),機(jī)器學(xué)習(xí)就是讓系統(tǒng)不斷的學(xué)習(xí)并且對(duì)新的問(wèn)題進(jìn)行預(yù)測(cè)。從簡(jiǎn)單的預(yù)測(cè)購(gòu)物商品到復(fù)雜的數(shù)字助理預(yù)測(cè)。

在這篇文章我將會(huì)使用樸素貝葉斯算法Clasifier作為一個(gè)類來(lái)介紹。這是一個(gè)簡(jiǎn)單易于實(shí)施的算法,并且可給出滿意的結(jié)果。但是這個(gè)算法是需要一點(diǎn)統(tǒng)計(jì)學(xué)的知識(shí)去理解的。在文章的最后部分你可以看到一些實(shí)例代碼,甚至自己去嘗試著自己做一下你的機(jī)器學(xué)習(xí)。

起步

那么,這個(gè)Classifier是要用來(lái)實(shí)現(xiàn)什么功能呢?其實(shí)它主要是用來(lái)判斷給定的語(yǔ)句是積極地還是消極的。比如,“Symfony is the best”是一個(gè)積極的語(yǔ)句,“No Symfony is bad”是一個(gè)消極的語(yǔ)句。所以在給定了一個(gè)語(yǔ)句之后,我想讓這個(gè)Classifier在我不給定一個(gè)新的規(guī)則的情況就返回一個(gè)語(yǔ)句類型。

我給Classifier命名了一個(gè)相同名稱的類,并且包含一個(gè)guess方法。這個(gè)方法接受一個(gè)語(yǔ)句的輸入,并且會(huì)返回這個(gè)語(yǔ)句是積極的還是消極的。這個(gè)類就像下面這樣:

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

我更喜歡使用枚舉類型的類而不是字符串作為我的返回值。我將這個(gè)枚舉類型的類命名為Type,并且包含兩個(gè)常量:一個(gè)POSITIVE,一個(gè)NEGATIVE。這兩個(gè)常量將會(huì)當(dāng)做guess方法的返回值。

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

初始化工作已經(jīng)完成,接下來(lái)就是要編寫我們的算法進(jìn)行預(yù)測(cè)了。

樸素貝葉斯

樸素貝葉斯算法是基于一個(gè)訓(xùn)練集合工作的,根據(jù)這個(gè)訓(xùn)練集從而做出相應(yīng)的預(yù)測(cè)。這個(gè)算法運(yùn)用了簡(jiǎn)單的統(tǒng)計(jì)學(xué)以及一點(diǎn)數(shù)學(xué)去進(jìn)行結(jié)果的計(jì)算。比如像下面四個(gè)文本組成的訓(xùn)練集合:

語(yǔ)句 類型
Symfony is the best Positive
PhpStorm is great Positive
Iltar complains a lot Negative
No Symfony is bad Negative


如果給定語(yǔ)句是“Symfony is the best”,那么你可以說(shuō)這個(gè)語(yǔ)句是積極地。你平常也會(huì)根據(jù)之前學(xué)習(xí)到的相應(yīng)知識(shí)做出對(duì)應(yīng)的決定,樸素貝葉斯算法也是同樣的道理:它根據(jù)之前的訓(xùn)練集來(lái)決定哪一個(gè)類型更加相近。

學(xué)習(xí)

在這個(gè)算法正式工作之前,它需要大量的歷史信息作為訓(xùn)練集。它需要知道兩件事:每一個(gè)類型對(duì)應(yīng)的詞產(chǎn)生了多少次和每一個(gè)語(yǔ)句對(duì)應(yīng)的類型是什么。我們?cè)趯?shí)施的時(shí)候會(huì)將這兩種信息存儲(chǔ)在兩個(gè)數(shù)組當(dāng)中。一個(gè)數(shù)組包含每一類型的詞語(yǔ)統(tǒng)計(jì),另一個(gè)數(shù)組包含每一個(gè)類型的語(yǔ)句統(tǒng)計(jì)。所有的其他信息都可以從這兩個(gè)數(shù)組中聚合。代碼就像下面的一樣:

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]++; // 增加類型的詞語(yǔ)統(tǒng)計(jì)
 }
 $this->documents[$type]++; // 增加類型的語(yǔ)句統(tǒng)計(jì)
}

有了這個(gè)集合以后,現(xiàn)在這個(gè)算法就可以根據(jù)歷史數(shù)據(jù)接受預(yù)測(cè)訓(xùn)練了。

定義

為了解釋這個(gè)算法是如何工作的,幾個(gè)定義是必要的。首先,讓我們定義一下輸入的語(yǔ)句是給定類型中的一個(gè)的概率。這個(gè)將會(huì)表示為P(Type)。它是以已知類型的數(shù)據(jù)的類型作為分子,還有整個(gè)訓(xùn)練集的數(shù)據(jù)數(shù)量作為分母來(lái)得出的。一個(gè)數(shù)據(jù)就是整個(gè)訓(xùn)練集中的一個(gè)。到現(xiàn)在為止,這個(gè)方法可以將會(huì)命名為totalP,像下面這樣:

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

請(qǐng)注意,在這里分子和分母都加了1。這是為了避免分子和分母都為0的情況。

根據(jù)上面的訓(xùn)練集的例子,積極和消極的類型都會(huì)得出0.6的概率。每中類型的數(shù)據(jù)都是2個(gè),一共是4個(gè)數(shù)據(jù)所以就是(2+1)/(4+1)。

第二個(gè)要定義的是對(duì)于給定的一個(gè)詞是屬于哪個(gè)確定類型的概率。這個(gè)我們定義成P(word,Type)。首先我們要得到一個(gè)詞在訓(xùn)練集中給出確定類型出現(xiàn)的次數(shù),然后用這個(gè)結(jié)果來(lái)除以整個(gè)給定類型數(shù)據(jù)的詞數(shù)。這個(gè)方法我們定義為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);
}

在本次的訓(xùn)練集中,“is”的是積極類型的概率為0.375。這個(gè)詞在整個(gè)積極的數(shù)據(jù)中的7個(gè)詞中占了兩次,所以結(jié)果就是(2+1)/(7+1)。

最后,這個(gè)算法應(yīng)該只關(guān)心關(guān)鍵詞而忽略其他的因素。一個(gè)簡(jiǎn)單的方法就是將給定的字符串中的單詞分離出來(lái):

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

準(zhǔn)備工作都做好了,開始真正實(shí)施我們的計(jì)劃吧!

預(yù)測(cè)

為了預(yù)測(cè)語(yǔ)句的類型,這個(gè)算法應(yīng)該計(jì)算所給定語(yǔ)句的兩個(gè)類型的概率。像上面一樣,我們定義一個(gè)P(Type,sentence)。得出概率高的類型將會(huì)是Classifier類中算法返回的結(jié)果。

為了計(jì)算P(Type,sentence),算法當(dāng)中將用到貝葉斯定理。算法像這樣被定義:P(Type,sentence)= P(Type)* P(sentence,Type)/ P(sentence)。這意味著給定語(yǔ)句的類型概率和給定類型語(yǔ)句概率除以語(yǔ)句的概率的結(jié)果是相同的。

那么算法在計(jì)算每一個(gè)相同語(yǔ)句的P(Tyoe,sentence),P(sentence)是保持一樣的。這意味著算法就可以省略其他因素,我們只需要關(guān)心最高的概率而不是實(shí)際的值。計(jì)算就像這樣:P(Type,sentence) = P(Type)* P(sentence,Type)。

最后,為了計(jì)算P(sentence,Type),我們可以為語(yǔ)句中的每個(gè)詞添加一條鏈?zhǔn)揭?guī)則。所以在一條語(yǔ)句中如果有n個(gè)詞的話,它將會(huì)和P(word_1,Type)* P(word_2,Type)* P(word_3,Type)* .....*P(word_n,Type)是一樣的。每一個(gè)詞計(jì)算結(jié)果的概率使用了我們前面看到的定義。

好了,所有的都說(shuō)完了,是時(shí)候在php中實(shí)際操作一下了:

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

這就是所有的工作,現(xiàn)在算法可以預(yù)測(cè)語(yǔ)句的類型了。你要做的就是讓你的算法開始學(xué)習(xí):

$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"

所有的代碼我已經(jīng)上傳到了GIT上,https://github.com/yannickl88/blog-articles/blob/master/src/machine-learning-naive-bayes/Classifier.php

github上完整php代碼如下:

<?php
class Type
{
 const POSITIVE = 'positive';
 const NEGATIVE = 'negative';
}
class Classifier
{
 private $types = [Type::POSITIVE, Type::NEGATIVE];
 private $words = [Type::POSITIVE => [], 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"

結(jié)束語(yǔ)

盡管我們只進(jìn)行了很少的訓(xùn)練,但是算法還是應(yīng)該能給出相對(duì)精確的結(jié)果。在真實(shí)環(huán)境,你可以讓機(jī)器學(xué)習(xí)成百上千的記錄,這樣就可以給出更精準(zhǔn)的結(jié)果。你可以下載查看這篇文章(英文):樸素貝葉斯已經(jīng)被證明可以給出情緒統(tǒng)計(jì)的結(jié)果

而且,樸素貝葉斯不僅僅可以運(yùn)用到文本類的應(yīng)用。希望通過(guò)這篇文章可以拉近你和機(jī)器學(xué)習(xí)的一點(diǎn)點(diǎn)距離。

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

更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP數(shù)據(jù)結(jié)構(gòu)與算法教程》、《php程序設(shè)計(jì)算法總結(jié)》、《php字符串(string)用法總結(jié)》、《PHP數(shù)組(Array)操作技巧大全》、《PHP常用遍歷算法與技巧總結(jié)》及《PHP數(shù)學(xué)運(yùn)算技巧總結(jié)

希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • php strrpos()與strripos()函數(shù)

    php strrpos()與strripos()函數(shù)

    以下是對(duì)php中的strrpos函數(shù)與strripos函數(shù)的用法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • PHP中isset、empty的用法與區(qū)別示例詳解

    PHP中isset、empty的用法與區(qū)別示例詳解

    這篇文章主要給大家介紹了關(guān)于PHP中isset、empty的用法與區(qū)別的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • php7 參數(shù)、整形及字符串處理機(jī)制修改實(shí)例分析

    php7 參數(shù)、整形及字符串處理機(jī)制修改實(shí)例分析

    這篇文章主要介紹了php7 參數(shù)、整形及字符串處理機(jī)制修改,結(jié)合實(shí)例形式分析了php7 參數(shù)、整形及字符串處理機(jī)制較舊版本的區(qū)別及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2020-05-05
  • 詳解PHP Swoole與TCP三次握手

    詳解PHP Swoole與TCP三次握手

    TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接(連接導(dǎo)向)的、可靠的、 基于IP的傳輸層協(xié)議。TCP在IP報(bào)文的協(xié)議號(hào)是6。TCP是一個(gè)超級(jí)麻煩的協(xié)議,而它又是互聯(lián)網(wǎng)的基礎(chǔ),也是每個(gè)程序員必備的基本功。本文將詳細(xì)介紹PHP Swoole與TCP三次握手。
    2021-05-05
  • 關(guān)于Laravel Service Provider開發(fā)設(shè)置延遲加載時(shí)遇到的問(wèn)題詳解

    關(guān)于Laravel Service Provider開發(fā)設(shè)置延遲加載時(shí)遇到的問(wèn)題詳解

    這篇文章主要給大家介紹了關(guān)于Laravel Service Provider開發(fā)設(shè)置延遲加載時(shí)遇到的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。
    2018-01-01
  • php之readdir函數(shù)用法實(shí)例

    php之readdir函數(shù)用法實(shí)例

    這篇文章主要介紹了php中readdir函數(shù)用法,以實(shí)例講述了readdir函數(shù)操作目錄的具體用法與相關(guān)的注意事項(xiàng),非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-11-11
  • 一個(gè)數(shù)據(jù)采集類

    一個(gè)數(shù)據(jù)采集類

    一個(gè)數(shù)據(jù)采集類...
    2007-02-02
  • php實(shí)現(xiàn)按照權(quán)重隨機(jī)排序數(shù)據(jù)的方法

    php實(shí)現(xiàn)按照權(quán)重隨機(jī)排序數(shù)據(jù)的方法

    這篇文章主要介紹了php實(shí)現(xiàn)按照權(quán)重隨機(jī)排序數(shù)據(jù)的方法,是php數(shù)據(jù)排序中一個(gè)比較典型的應(yīng)用技巧,需要的朋友可以參考下
    2015-01-01
  • php ftp文件上傳函數(shù)(基礎(chǔ)版)

    php ftp文件上傳函數(shù)(基礎(chǔ)版)

    很多時(shí)間我們不會(huì)用于php ftp函數(shù)文件上傳,但有在使用比較高級(jí)的WEB應(yīng)用時(shí)就會(huì)用到關(guān)于ftp功能,如我現(xiàn)在要把上傳的圖片傳B服務(wù)器,數(shù)據(jù)保存到A服務(wù)器,普通的php文件上傳實(shí)現(xiàn)不了,但用ftp功能就可以方便的使用了。
    2010-06-06
  • php 靜態(tài)變量的初始化

    php 靜態(tài)變量的初始化

    php的成員變量可以在聲明的同時(shí)進(jìn)行初始化,但是只能用標(biāo)量進(jìn)行初始化。
    2009-11-11

最新評(píng)論