這篇文章主要介紹了PHP如何實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
具體如下:
機(jī)器學(xué)習(xí)已經(jīng)在我們的生活中變得隨處可見了。比如從你在家的時候溫控器開始工作到智能汽車以及我們口袋中的智能手機(jī)。機(jī)器學(xué)習(xí)看上去已經(jīng)無處不在并且是一個非常值得探索的領(lǐng)域。但是什么是機(jī)器學(xué)習(xí)呢?通常來說,機(jī)器學(xué)習(xí)就是讓系統(tǒng)不斷的學(xué)習(xí)并且對新的問題進(jìn)行預(yù)測。從簡單的預(yù)測購物商品到復(fù)雜的數(shù)字助理預(yù)測。
在這篇文章我將會使用樸素貝葉斯算法Clasifier作為一個類來介紹。這是一個簡單易于實(shí)施的算法,并且可給出滿意的結(jié)果。但是這個算法是需要一點(diǎn)統(tǒng)計學(xué)的知識去理解的。在文章的最后部分你可以看到一些實(shí)例代碼,甚至自己去嘗試著自己做一下你的機(jī)器學(xué)習(xí)。
起步
那么,這個Classifier是要用來實(shí)現(xiàn)什么功能呢?其實(shí)它主要是用來判斷給定的語句是積極地還是消極的。比如,“Symfony is the best”是一個積極的語句,“No Symfony is bad”是一個消極的語句。所以在給定了一個語句之后,我想讓這個Classifier在我不給定一個新的規(guī)則的情況就返回一個語句類型。
我給Classifier命名了一個相同名稱的類,并且包含一個guess方法。這個方法接受一個語句的輸入,并且會返回這個語句是積極的還是消極的。這個類就像下面這樣:
class Classifier { public function guess($statement) {} }
我更喜歡使用枚舉類型的類而不是字符串作為我的返回值。我將這個枚舉類型的類命名為Type,并且包含兩個常量:一個POSITIVE,一個NEGATIVE。這兩個常量將會當(dāng)做guess方法的返回值。
class Type { const POSITIVE = 'positive'; const NEGATIVE = 'negative'; }
初始化工作已經(jīng)完成,接下來就是要編寫我們的算法進(jìn)行預(yù)測了。
樸素貝葉斯
樸素貝葉斯算法是基于一個訓(xùn)練集合工作的,根據(jù)這個訓(xùn)練集從而做出相應(yīng)的預(yù)測。這個算法運(yùn)用了簡單的統(tǒng)計學(xué)以及一點(diǎn)數(shù)學(xué)去進(jìn)行結(jié)果的計算。比如像下面四個文本組成的訓(xùn)練集合:
語句 | 類型 |
Symfony is the best | Positive |
PhpStorm is great | Positive |
Iltar complains a lot | Negative |
No Symfony is bad | Negative |
如果給定語句是“Symfony is the best”,那么你可以說這個語句是積極地。你平常也會根據(jù)之前學(xué)習(xí)到的相應(yīng)知識做出對應(yīng)的決定,樸素貝葉斯算法也是同樣的道理:它根據(jù)之前的訓(xùn)練集來決定哪一個類型更加相近。
學(xué)習(xí)
在這個算法正式工作之前,它需要大量的歷史信息作為訓(xùn)練集。它需要知道兩件事:每一個類型對應(yīng)的詞產(chǎn)生了多少次和每一個語句對應(yīng)的類型是什么。我們在實(shí)施的時候會將這兩種信息存儲在兩個數(shù)組當(dāng)中。一個數(shù)組包含每一類型的詞語統(tǒng)計,另一個數(shù)組包含每一個類型的語句統(tǒng)計。所有的其他信息都可以從這兩個數(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]++; // 增加類型的詞語統(tǒng)計 } $this->documents[$type]++; // 增加類型的語句統(tǒng)計 }
有了這個集合以后,現(xiàn)在這個算法就可以根據(jù)歷史數(shù)據(jù)接受預(yù)測訓(xùn)練了。
定義
為了解釋這個算法是如何工作的,幾個定義是必要的。首先,讓我們定義一下輸入的語句是給定類型中的一個的概率。這個將會表示為P(Type)。它是以已知類型的數(shù)據(jù)的類型作為分子,還有整個訓(xùn)練集的數(shù)據(jù)數(shù)量作為分母來得出的。一個數(shù)據(jù)就是整個訓(xùn)練集中的一個。到現(xiàn)在為止,這個方法可以將會命名為totalP,像下面這樣:
function totalP($type) { return ($this->documents[$type] + 1) / (array_sum($this->documents) + 1); }
請注意,在這里分子和分母都加了1。這是為了避免分子和分母都為0的情況。
根據(jù)上面的訓(xùn)練集的例子,積極和消極的類型都會得出0.6的概率。每中類型的數(shù)據(jù)都是2個,一共是4個數(shù)據(jù)所以就是(2+1)/(4+1)。
第二個要定義的是對于給定的一個詞是屬于哪個確定類型的概率。這個我們定義成P(word,Type)。首先我們要得到一個詞在訓(xùn)練集中給出確定類型出現(xiàn)的次數(shù),然后用這個結(jié)果來除以整個給定類型數(shù)據(jù)的詞數(shù)。這個方法我們定義為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。這個詞在整個積極的數(shù)據(jù)中的7個詞中占了兩次,所以結(jié)果就是(2+1)/(7+1)。
最后,這個算法應(yīng)該只關(guān)心關(guān)鍵詞而忽略其他的因素。一個簡單的方法就是將給定的字符串中的單詞分離出來:
function getWords($string) { return preg_split('/\s+/', preg_replace('/[^A-Za-z0-9\s]/', '', strtolower($string))); }
準(zhǔn)備工作都做好了,開始真正實(shí)施我們的計劃吧!
預(yù)測
為了預(yù)測語句的類型,這個算法應(yīng)該計算所給定語句的兩個類型的概率。像上面一樣,我們定義一個P(Type,sentence)。得出概率高的類型將會是Classifier類中算法返回的結(jié)果。
為了計算P(Type,sentence),算法當(dāng)中將用到貝葉斯定理。算法像這樣被定義:P(Type,sentence)= P(Type)* P(sentence,Type)/ P(sentence)。這意味著給定語句的類型概率和給定類型語句概率除以語句的概率的結(jié)果是相同的。
那么算法在計算每一個相同語句的P(Tyoe,sentence),P(sentence)是保持一樣的。這意味著算法就可以省略其他因素,我們只需要關(guān)心高的概率而不是實(shí)際的值。計算就像這樣:P(Type,sentence) = P(Type)* P(sentence,Type)。
最后,為了計算P(sentence,Type),我們可以為語句中的每個詞添加一條鏈?zhǔn)揭?guī)則。所以在一條語句中如果有n個詞的話,它將會和P(word_1,Type)* P(word_2,Type)* P(word_3,Type)* .....*P(word_n,Type)是一樣的。每一個詞計算結(jié)果的概率使用了我們前面看到的定義。
好了,所有的都說完了,是時候在php中實(shí)際操作一下了:
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; }
這就是所有的工作,現(xiàn)在算法可以預(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"
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“PHP如何實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司,,關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
本文題目:PHP如何實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法-創(chuàng)新互聯(lián)
文章來源:http://chinadenli.net/article10/dcpogo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、企業(yè)網(wǎng)站制作、自適應(yīng)網(wǎng)站、品牌網(wǎng)站設(shè)計、搜索引擎優(yōu)化、做網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容