本文經Wern Ancheta同行評審。感謝所有SitePoint的同行評審員,使SitePoint的內容達到最佳狀態!
最近,似乎每個人都在談論機器學習。你的社交媒體信息流充斥著關於ML、Python、TensorFlow、Spark、Scala、Go等等的帖子;如果你像我一樣,你可能會想知道,PHP呢?
是的,機器學習和PHP呢?幸運的是,有人瘋狂地不僅提出了這個問題,而且還開發了一個通用的機器學習庫,我們可以在下一個項目中使用它。在這篇文章中,我們將看看PHP-ML——一個用於PHP的機器學習庫——我們將編寫一個情感分析類,稍後可以將其重用於我們自己的聊天機器人或推特機器人。這篇文章的主要目標是:
閱讀更好的PHP開發工具和技術,使你成為更好的開發者! 閱讀此書 閱讀此書!
機器學習是人工智能的一個子集,它專注於賦予“計算機無需明確編程即可學習的能力”。這是通過使用可以從特定數據集“學習”的通用算法來實現的。
例如,機器學習的一個常見用途是分類。分類算法用於將數據分成不同的組或類別。分類應用程序的一些示例包括:
機器學習是一個涵蓋許多不同任務的通用算法的總稱,並且根據學習方式主要分為兩種算法類型——監督學習和無監督學習。
在監督學習中,我們使用標記數據來訓練我們的算法,標記數據採用輸入對象(向量)和所需輸出值的格式;算法分析訓練數據並產生所謂的推斷函數,我們可以將其應用於新的未標記數據集。
在本帖的其餘部分,我們將重點關注監督學習,因為它更容易看到和驗證關係;請記住,這兩種算法同樣重要且有趣;有人可能會認為無監督學習更有用,因為它排除了標記數據的需求。
另一方面,這種類型的學習從一開始就使用未標記的數據。我們不知道數據集的所需輸出值,我們讓算法從數據集中得出推論;無監督學習在進行探索性數據分析以查找數據中的隱藏模式時特別方便。
認識PHP-ML,一個聲稱是PHP機器學習新方法的庫。該庫實現了算法、神經網絡和工具,用於進行數據預處理、交叉驗證和特徵提取。
我首先承認,PHP是機器學習的不尋常選擇,因為該語言的優勢並不太適合機器學習應用程序。也就是說,並非每個機器學習應用程序都需要處理PB級數據並進行大量計算——對於簡單的應用程序,我們應該能夠使用PHP和PHP-ML。
我現在能看到的這個庫最好的用例是分類器的實現,無論是垃圾郵件過濾器還是情感分析。我們將定義一個分類問題,並逐步構建解決方案,以了解如何在我們的項目中使用PHP-ML。
為了舉例說明實現PHP-ML並將一些機器學習添加到我們的應用程序中的過程,我想找到一個有趣的問題來解決,還有什麼比構建一個推特情感分析類更好的方法來展示分類器呢?
構建成功的機器學習項目所需的關鍵要求之一是良好的起始數據集。數據集至關重要,因為它們將允許我們針對已分類的示例訓練我們的分類器。由於媒體最近圍繞航空公司出現了大量噪音,還有什麼比使用客戶對航空公司的推文更好的數據集呢?
幸運的是,由於Kaggle.io,我們已經可以使用推文數據集。可以使用此鏈接從其網站下載Twitter美國航空公司情緒數據庫
讓我們首先看看我們將要處理的數據集。原始數據集包含以下列:
並且看起來像下面的例子(可側向滾動的表格):
tweet_id
airline_sentiment
airline_sentiment_confidence
negativereason
negativereason_confidence
airline
airline_sentiment_gold
name
negativereason_gold
retweet_count
text
tweet_coord
tweet_created
tweet_location
user_timezone
570306133677760513 neutral 1.0 Virgin America cairdin 0 @VirginAmerica What @dhepburn said. 2015-02-24 11:35:52 -0800 Eastern Time (US & Canada) 570301130888122368 positive 0.3486 0.0 Virgin America jnardino 0 @VirginAmerica plus you've added commercials to the experience… tacky. 2015-02-24 11:15:59 -0800 Pacific Time (US & Canada) 570301083672813571 neutral 0.6837 Virgin America yvonnalynn 0 @VirginAmerica I didn't today… Must mean I need to take another trip! 2015-02-24 11:15:48 -0800 Lets Play Central Time (US & Canada) 570301031407624196 negative 1.0 Bad Flight 0.7033 Virgin America jnardino 0 “ @VirginAmerica it's really aggressive to blast obnoxious “”entertainment”” in your guests' faces & they have little recourse” 2015-02-24 11:15:36 -0800 Pacific Time (US & Canada) 570300817074462722 negative 1.0 Can't Tell 1.0 Virgin America jnardino 0 @VirginAmerica and it's a really big bad thing about it 2015-02-24 11:14:45 -0800 Pacific Time (US & Canada) 570300767074181121 negative 1.0 Can't Tell 0.6842 Virgin America jnardino 0 “@VirginAmerica seriously would pay $30 a flight for seats that didn't have this playing. it's really the only bad thing about flying VA” 2015-02-24 11:14:33 -0800 Pacific Time (US & Canada) 570300616901320704 positive 0.6745 0.0 Virgin America cjmcginnis 0 “@VirginAmerica yes nearly every time I fly VX this “ear worm” won't go away :)” 2015-02-24 11:13:57 -0800 San Francisco CA Pacific Time (US & Canada) 570300248553349120 neutral 0.634 Virgin America pilot 0 “@VirginAmerica Really missed a prime opportunity for Men Without Hats parody there. https://www.php.cn/link/76379ed89eafe43c8f6bd64fd09e3852” 2015-02-24 11:12:29 -0800 Los Angeles Pacific Time (US & Canada) 該文件包含14,640條推文,因此對於我們來說是一個不錯的工作數據集。現在,使用我們當前可用的列數,我們擁有比示例所需更多的數據;出於實際目的,我們只關心以下列:
其中text將成為我們的特徵,airline_sentiment將成為我們的目標。其餘列可以丟棄,因為它們不會用於我們的練習。讓我們從創建項目開始,並使用以下文件初始化composer:
<code>{ "name": "amacgregor/phpml-exercise", "description": "Example implementation of a Tweet sentiment analysis with PHP-ML", "type": "project", "require": { "php-ai/php-ml": "^0.4.1" }, "license": "Apache License 2.0", "authors": [ { "name": "Allan MacGregor", "email": "amacgregor@allanmacgregor.com" } ], "autoload": { "psr-4": {"PhpmlExercise\": "src/"} }, "minimum-stability": "dev" }</code>
<code>composer install </code>
如果您需要 Composer 入門介紹,請參見此處。
為了確保我們正確設置,讓我們創建一個快速腳本,它將加載我們的Tweets.csv數據文件並確保它具有我們需要的數據。將以下代碼複製為項目根目錄中的reviewDataset.php:
<?php namespace PhpmlExercise; require __DIR__ . '/vendor/autoload.php'; use Phpml\Dataset\CsvDataset; $dataset = new CsvDataset('datasets/raw/Tweets.csv',1); foreach ($dataset->getSamples() as $sample) { print_r($sample); }
現在,使用php reviewDataset.php運行腳本,讓我們查看輸出:
<code>Array( [0] => 569587371693355008 ) Array( [0] => 569587242672398336 ) Array( [0] => 569587188687634433 ) Array( [0] => 569587140490866689 ) </code>
現在這看起來沒用,不是嗎?讓我們看看CsvDataset類,以便更好地了解內部發生的情況:
<?php public function __construct(string $filepath, int $features, bool $headingRow = true) { if (!file_exists($filepath)) { throw FileException::missingFile(basename($filepath)); } if (false === $handle = fopen($filepath, 'rb')) { throw FileException::cantOpenFile(basename($filepath)); } if ($headingRow) { $data = fgetcsv($handle, 1000, ','); $this->columnNames = array_slice($data, 0, $features); } else { $this->columnNames = range(0, $features - 1); } while (($data = fgetcsv($handle, 1000, ',')) !== false) { $this->samples[] = array_slice($data, 0, $features); $this->targets[] = $data[$features]; } fclose($handle); }
CsvDataset構造函數採用3個參數:
如果我們仔細觀察,我們可以看到該類正在將CSV文件映射到兩個內部數組:samples和targets。 Samples包含文件提供的所有特徵,而targets包含已知值(負、正或中性)。
基於上述內容,我們可以看到我們的CSV文件需要遵循的格式如下:
<code>| feature_1 | feature_2 | feature_n | target | </code>
我們將需要生成一個乾淨的數據集,其中只包含我們需要繼續工作的列。讓我們將此腳本稱為generateCleanDataset.php:
<?php namespace PhpmlExercise; require __DIR__ . '/vendor/autoload.php'; use Phpml\Exception\FileException; $sourceFilepath = __DIR__ . '/datasets/raw/Tweets.csv'; $destinationFilepath = __DIR__ . '/datasets/clean_tweets.csv'; $rows =[]; $rows = getRows($sourceFilepath, $rows); writeRows($destinationFilepath, $rows); /** * @param $filepath * @param $rows * @return array */ function getRows($filepath, $rows) { $handle = checkFilePermissions($filepath); while (($data = fgetcsv($handle, 1000, ',')) !== false) { $rows[] = [$data[10], $data[1]]; } fclose($handle); return $rows; } /** * @param $filepath * @param string $mode * @return bool|resource * @throws FileException */ function checkFilePermissions($filepath, $mode = 'rb') { if (!file_exists($filepath)) { throw FileException::missingFile(basename($filepath)); } if (false === $handle = fopen($filepath, $mode)) { throw FileException::cantOpenFile(basename($filepath)); } return $handle; } /** * @param $filepath * @param $rows * @internal param $list */ function writeRows($filepath, $rows) { $handle = checkFilePermissions($filepath, 'wb'); foreach ($rows as $row) { fputcsv($handle, $row); } fclose($handle); }
沒有什麼太複雜的,只是足以完成這項工作。讓我們用php generateCleanDataset.php執行它。
現在,讓我們將reviewDataset.php腳本指向乾淨的數據集:
<code>Array ( [0] => @AmericanAir That will be the third time I have been called by 800-433-7300 an hung on before anyone speaks. What do I do now??? ) Array ( [0] => @AmericanAir How clueless is AA. Been waiting to hear for 2.5 weeks about a refund from a Cancelled Flightled flight & been on hold now for 1hr 49min )</code>
BAM!這是我們可以使用的數據!到目前為止,我們一直在創建用於操作數據的簡單腳本。接下來,我們將開始在src/classification/SentimentAnalysis.php下創建一個新類。
<?php namespace PhpmlExercise\Classification; /** * Class SentimentAnalysis * @package PhpmlExercise\Classification */ class SentimentAnalysis { public function train() {} public function predict() {} }
我們的情感類將需要在我們的情感分析類中使用兩個函數:
在項目的根目錄中創建一個名為classifyTweets.php的腳本。我們將使用此腳本來實例化和測試我們的情感分析類。這是我們將使用的模板:
<?php namespace PhpmlExercise; use PhpmlExercise\Classification\SentimentAnalysis; require __DIR__ . '/vendor/autoload.php'; // 步骤 1:加载数据集 // 步骤 2:准备数据集 // 步骤 3:生成训练/测试数据集 // 步骤 4:训练分类器 // 步骤 5:测试分类器的准确性
我們已經擁有可以用於將CSV加載到我們早期示例中的數據集對象的代碼。我們將使用相同的代碼並進行一些調整:
<?php ... use Phpml\Dataset\CsvDataset; ... $dataset = new CsvDataset('datasets/clean_tweets.csv',1); $samples = []; foreach ($dataset->getSamples() as $sample) { $samples[] = $sample[0]; }
這將生成一個僅包含特徵(在本例中為推文文本)的扁平數組,我們將使用它來訓練我們的分類器。
現在,擁有原始文本並將該文本傳遞給分類器將不會有用或準確,因為每條推文本質上都是不同的。幸運的是,在嘗試應用分類或機器學習算法時,有一些方法可以處理文本。對於此示例,我們將使用以下兩個類:
讓我們從文本向量化器開始:
<code>{ "name": "amacgregor/phpml-exercise", "description": "Example implementation of a Tweet sentiment analysis with PHP-ML", "type": "project", "require": { "php-ai/php-ml": "^0.4.1" }, "license": "Apache License 2.0", "authors": [ { "name": "Allan MacGregor", "email": "amacgregor@allanmacgregor.com" } ], "autoload": { "psr-4": {"PhpmlExercise\": "src/"} }, "minimum-stability": "dev" }</code>
接下來,應用Tf-idf轉換器:
<code>composer install </code>
我們的samples數組現在採用了一種格式,可以很容易地被我們的分類器理解。我們還沒完成,我們需要用其相應的情緒標記每個樣本。
幸運的是,PHP-ML已經涵蓋了這個需求,代碼非常簡單:
<?php namespace PhpmlExercise; require __DIR__ . '/vendor/autoload.php'; use Phpml\Dataset\CsvDataset; $dataset = new CsvDataset('datasets/raw/Tweets.csv',1); foreach ($dataset->getSamples() as $sample) { print_r($sample); }
我們可以繼續使用此數據集並訓練我們的分類器。但是,我們缺少用作驗證的測試數據集,因此我們將“作弊”一點,並將我們的原始數據集分成兩部分:一個訓練數據集和一個用於測試模型準確性的更小得多的數據集。
<code>Array( [0] => 569587371693355008 ) Array( [0] => 569587242672398336 ) Array( [0] => 569587188687634433 ) Array( [0] => 569587140490866689 ) </code>
這種方法稱為交叉驗證。該術語來自統計學,可以定義如下:
交叉驗證,有時稱為旋轉估計,是一種模型驗證技術,用於評估統計分析的結果將如何推廣到獨立數據集。它主要用於預測的目標設置,並且想要估計預測模型在實踐中的準確性。 — Wikipedia.com
最後,我們準備返回並實現SentimentAnalysis類。如果你現在還沒注意到,機器學習的很大一部分是關於收集和操作數據;機器學習模型的實際實現往往涉及較少的內容。
為了實現我們的情感分析類,我們有三種可用的分類算法:
對於此練習,我們將使用最簡單的一種,即樸素貝葉斯分類器,因此讓我們繼續更新我們的類以實現train方法:
<?php public function __construct(string $filepath, int $features, bool $headingRow = true) { if (!file_exists($filepath)) { throw FileException::missingFile(basename($filepath)); } if (false === $handle = fopen($filepath, 'rb')) { throw FileException::cantOpenFile(basename($filepath)); } if ($headingRow) { $data = fgetcsv($handle, 1000, ','); $this->columnNames = array_slice($data, 0, $features); } else { $this->columnNames = range(0, $features - 1); } while (($data = fgetcsv($handle, 1000, ',')) !== false) { $this->samples[] = array_slice($data, 0, $features); $this->targets[] = $data[$features]; } fclose($handle); }
如你所見,我們讓PHP-ML為我們完成所有繁重的工作。我們只是為我們的項目創建了一個很好的抽象。但是我們如何知道我們的分類器是否真的在訓練和工作呢?是時候使用我們的testSamples和testLabels了。
在我們繼續測試我們的分類器之前,我們確實必須實現預測方法:
<code>{ "name": "amacgregor/phpml-exercise", "description": "Example implementation of a Tweet sentiment analysis with PHP-ML", "type": "project", "require": { "php-ai/php-ml": "^0.4.1" }, "license": "Apache License 2.0", "authors": [ { "name": "Allan MacGregor", "email": "amacgregor@allanmacgregor.com" } ], "autoload": { "psr-4": {"PhpmlExercise\": "src/"} }, "minimum-stability": "dev" }</code>
同樣,PHP-ML為我們提供了幫助,並為我們完成了所有繁重的工作。讓我們相應地更新classifyTweets類:
<code>composer install </code>
最後,我們需要一種方法來測試我們訓練模型的準確性;謝天謝地,PHP-ML也涵蓋了這一點,並且他們有幾個指標類。在我們的例子中,我們對模型的準確性感興趣。讓我們看看代碼:
<?php namespace PhpmlExercise; require __DIR__ . '/vendor/autoload.php'; use Phpml\Dataset\CsvDataset; $dataset = new CsvDataset('datasets/raw/Tweets.csv',1); foreach ($dataset->getSamples() as $sample) { print_r($sample); }
我們應該看到類似以下內容:
<code>Array( [0] => 569587371693355008 ) Array( [0] => 569587242672398336 ) Array( [0] => 569587188687634433 ) Array( [0] => 569587140490866689 ) </code>
這篇文章有點長,所以讓我們回顧一下到目前為止我們學到了什麼:
這篇文章也作為PHP-ML庫的介紹,並希望讓你對該庫的功能以及如何在自己的項目中嵌入它有一個很好的了解。
最後,這篇文章絕非全面,還有很多需要學習、改進和實驗的地方;以下是一些想法,可以幫助你進一步改進:
我希望你發現這篇文章有用。如果你有一些關於PHP-ML的應用程序想法或任何問題,請隨時在下面的評論區中提出!
提高情感分析的準確性涉及多種策略。首先,確保你的訓練數據盡可能乾淨和相關。這意味著刪除任何不相關的數據,例如停用詞、標點符號和URL。其次,考慮使用更複雜的算法。雖然樸素貝葉斯分類器是一個很好的起點,但其他算法(如支持向量機 (SVM) 或深度學習模型)可能會提供更好的結果。最後,考慮使用更大的數據集進行訓練。你的模型可以學習的數據越多,它就越準確。
是的,你可以使用其他編程語言進行情感分析。例如,Python 因其廣泛的機器學習庫(如NLTK、TextBlob和scikit-learn)而成為一種流行的選擇。但是,PHP也可以有效地用於情感分析,特別是如果你已經熟悉該語言或你的項目是基於PHP框架構建的。
處理情感分析中的諷刺和反語是一項具有挑戰性的任務。這些語言特徵通常涉及說某事但意味著相反的意思,這對於機器學習模型來說很難理解。一種方法是使用可以理解上下文的更複雜的模型,例如深度學習模型。另一種方法是使用專門的諷刺檢測模型,該模型可以使用諷刺評論的數據集進行訓練。
情感分析的原理可以應用於任何文本數據,包括來自其他社交媒體平台的帖子。主要區別在於你如何收集數據。每個社交媒體平台都有自己的API用於訪問用戶帖子,因此你需要熟悉你感興趣的平台的API。
是的,情感分析可以用於任何語言。但是,分析的有效性將取決於你的訓練數據的質量。如果你使用的是英語以外的語言,則需要使用該語言的數據集來訓練你的模型。一些機器學習庫也直接支持多種語言。
有很多方法可以可視化情感分析結果。一種常見的方法是使用條形圖來顯示正面、負面和中性推文的數量。另一種方法是使用詞云來可視化數據中最常用的詞。 PHP有幾個用於創建這些可視化的庫,例如pChart和GD。
情感分析有很多實際應用。企業可以使用它來監控客戶對其產品或服務的意見,政治家可以使用它來衡量公眾對政策問題的意見,研究人員可以使用它來研究社會趨勢。可能性是無限的。
表情符號可以攜帶重要的情感信息,因此將它們包含在你的分析中很重要。一種方法是在將數據輸入模型之前,將每個表情符號替換為其文本描述。有一些庫可以幫助你做到這一點,例如PHP的Emojione。
拼寫錯誤在情感分析中可能是一個挑戰。一種方法是在將數據輸入模型之前使用拼寫檢查器來更正錯誤。另一種方法是使用可以處理拼寫錯誤的模型,例如深度學習模型。
保持你的情感分析模型最新涉及定期使用新數據對其進行再訓練。這確保你的模型與語言使用和情感的變化保持同步。你可以通過設置一個重新訓練模型的計劃來自動化此過程。
以上是如何分析PHP機器學習的推文觀點的詳細內容。更多資訊請關注PHP中文網其他相關文章!