PHPで機械学習を使用してツイートのトーンを分析する方法

すべての人に良い一日を!



さて、約束したとおり、 PHPコースの準備で学習した別の資料を共有しています。 私たちはあなたにとってそれが興味深く有用なものになることを願っています。



エントリー



最近、誰もが機械学習について話しているようです。 ソーシャルメディアフィードには、ML、Python、TensorFlow、Spark、Scala、Goなどに関する投稿が詰まっています。 そして、あなたと私に共通点があるなら、PHPについてはどうですか?



はい、機械学習とPHPはどうですか? 幸いなことに、誰かがこの質問をするだけでなく、次のプロジェクトで使用できる汎用機械学習ライブラリを開発するのに夢中になりました。 この投稿では、 PHPの機械学習ライブラリであるPHP-MLを見て、後で独自のチャットまたはツイートボットに使用できる調性分析クラスを作成します。 この投稿の主な目的は次のとおりです。









機械学習とは何ですか?



機械学習は、人工知能研究の分野のサブセットであり、「コンピューターに正確にプログラミングされなくても学習する機会」を提供することに焦点を当てています。 これは、特定のデータセットから「学習」できる一般的なアルゴリズムを使用して実現されます。



たとえば、機械学習を使用する一般的な方法の1つは分類です。 分類アルゴリズムは、異なるグループまたはカテゴリにデータを配置するために使用されます。 分類アプリケーションの例:





機械学習は、さまざまなタスク用の多くの汎用アルゴリズムを含む一般的な用語です。 アルゴリズムには、学習方法で分類された2つの主要なタイプがあります。教師との学習と教師なしの学習です。



教員養成



教師との指導では、入力オブジェクト(ベクトル)の形式のトレーニングデータと目的の出力値を使用してアルゴリズムをトレーニングします。 アルゴリズムはトレーニングデータを分析し、いわゆる目的関数を作成します。これは、新しいマークのないデータセットに適用できます。



この投稿の残りの部分では、より視覚的で関係を確認しやすいという理由だけで、教師との授業に焦点を当てます。 両方のアルゴリズムが同様に重要で興味深いことに注意してください。 他の人は、教師なしで学習することは、トレーニングデータの必要性を排除するため、より有用であると主張します。



教師なし学習



対照的に、このタイプのトレーニングは、最初からトレーニングデータがなくても機能します。 データセットの望ましい結果値がわからないため、アルゴリズムがサンプルからのみ結論を引き出すことを許可します。 教師なしで学習することは、データの隠れたパターンを明らかにするのに特に便利です。



PHP-ML



PHPでの機械学習への新しいアプローチであると主張するライブラリであるPHP-MLを紹介します。 このライブラリは、アルゴリズム、ニューラルネットワーク、およびデータの前処理、相互検証、特徴抽出のためのツールを実装しています。



言語の長所は機械学習の実装にはあまり適していないため、PHPは機械学習にとって珍しい選択であることに最初に気付くでしょう。 ただし、すべての機械学習アプリケーションがペタバイトのデータを処理して大規模な計算を行う必要があるわけではありません-単純なアプリケーションの場合、十分なPHPとPHP-MLが必要です



私が今このライブラリで想像できる最良のユースケースは、スパムフィルタのようなものであれ、テキストの調性の分析であれ、分類器を実装することです。 プロジェクトでPHP-MLを使用する方法を見つけるために、分類の問題を特定し、段階的に解決策を考えていきます。



挑戦する



PHP-MLの実装プロセスを説明し、アプリケーションに機械学習を追加するために、解決すべき興味深い問題を見つけたいと思っていました。分類子を実証する最良の方法は、ツイートトーン分析クラスを作成することです。



機械学習プロジェクトを成功させるために必要な重要な要件の1つは、信頼できるソースデータセットです。 データセットは、すでに分類された例で分類器をトレーニングできるため、重要です。 最近、航空会社を取り巻くメディアで大きな話題が出ているので、航空会社の顧客からのツイートよりも良いものはないでしょうか?



幸いなことに、 Kaggle.ioのおかげで、一連のツイートとしてのデータをすでに利用できます。 このリンクを使用して、ウェブサイトからUS Airline Sentiment twitterデータベースをダウンロードできます。



解決策



作業中のデータセットを調べることから始めましょう。 生データセットには次の列があります。







そして、 例のように見えます:





このファイルには14,640個のツイートが含まれています-これは十分なデータセットです。 これで、非常に多くの列を使用できるようになり、例に必要なデータよりも多くのデータが得られました。 実用的な目的のために、私たちは次の列にのみ興味があります。







text



はプロパティで、 airline_sentiment



はターゲットです。 残りの列は演習に使用されないため、削除できます。 プロジェクトを作成し、次のファイルを使用してコレクターを初期化することから始めます。



 { "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" }
      
      





composer install







Composerの概要が必要な場合は、 こちらをご覧ください



すべてを正しくインストールしたことを確認するために、 Tweets.csv



データ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); }
      
      





次に、 reviewDataset.php



スクリプトを実行して、結果を確認します。



 Array( [0] => 569587371693355008 ) Array( [0] => 569587242672398336 ) Array( [0] => 569587188687634433 ) Array( [0] => 569587140490866689 )
      
      





今のところ便利に見えませんか? 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ファイルを2つの内部配列(サンプルとターゲット)に分割していることがわかります。 サンプルにはファイルによって提供されるすべての関数が含まれ、ターゲットには既知の値(負、正、または中立)が含まれます。



上記に基づいて、CSVファイルの形式は次のとおりであることがわかります。



 | feature_1 | feature_2 | feature_n | target |
      
      





作業を継続する必要がある列のみを使用して、クリーンなデータセットを作成する必要があります。 このスクリプトを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); }
      
      





仕事をするのに十分な複雑さはありません。 phpgenerateCleanDataset.php



実行してみましょう。



それでは、次に進み、reviewDataset.phpスクリプトをクリーンなデータセットに向けます。



 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 )
      
      





バム! これが私たちが扱うことができるデータです! これまで、データを管理するための簡単なスクリプトを作成しました。 次に、 src/class/SentimentAnalysis.php



新しいクラスを作成します。



 <?php namespace PhpmlExercise\Classification; /** * Class SentimentAnalysis * @package PhpmlExercise\Classification */ class SentimentAnalysis { public function train() {} public function predict() {} }
      
      





Sentimentクラスには、調性分析クラスの2つの関数が必要です。





プロジェクトのルートで、 classifyTweets.php



スクリプトを作成します。 これを使用して、主要な分析クラスを作成およびテストします。 使用するテンプレートは次のとおりです。



 <?php namespace PhpmlExercise; use PhpmlExercise\Classification\SentimentAnalysis; require __DIR__ . '/vendor/autoload.php'; // Step 1: Load the Dataset // Step 2: Prepare the Dataset // Step 3: Generate the training/testing Dataset // Step 4: Train the classifier // Step 5: Test the classifier accuracy
      
      





ステップ1.データセットをダウンロードする



前の例からCSVをデータオブジェクトにロードするために使用できる基本的なコードは既に用意されています。 いくつかの小さな変更を加えて同じコードを使用します。



 <?php ... use Phpml\Dataset\CsvDataset; ... $dataset = new CsvDataset('datasets/clean_tweets.csv',1); $samples = []; foreach ($dataset->getSamples() as $sample) { $samples[] = $sample[0]; }
      
      





これにより、プロパティのみを含む配列が作成されます。この場合、分類子のトレーニングに使用するツイートテキストです。



ステップ2:データセットの準備



ツイートは互いに大きく異なるため、生のテキストを分類子に渡すと、利益と正確さが失われます。 幸いなことに、分類アルゴリズムまたは機械学習アルゴリズムを適用しようとするときにテキストを操作する方法があります。 この例では、次の2つのクラスを使用します。





テキストベクトライザーから始めましょう:



 <?php ... use Phpml\FeatureExtraction\TokenCountVectorizer; use Phpml\Tokenization\WordTokenizer; ... $vectorizer = new TokenCountVectorizer(new WordTokenizer()); $vectorizer->fit($samples); $vectorizer->transform($samples);
      
      





次に、Tf-idfトランスフォーマーを適用します。



 <?php ... use Phpml\FeatureExtraction\TfIdfTransformer; ... $tfIdfTransformer = new TfIdfTransformer(); $tfIdfTransformer->fit($samples); $tfIdfTransformer->transform($samples);
      
      





サンプルの配列は、分類器が理解できる形式になりました。 まだ終了していません。適切なムードで各サンプルをマークする必要があります。



ステップ3.トレーニングキットを作成する



幸いなことに、PHP-MLは既にこれを行う方法を知っており、コードは非常に単純です。



 <?php ... use Phpml\Dataset\ArrayDataset; ... $dataset = new ArrayDataset($samples, $dataset->getTargets());
      
      





このデータセットを使用して、分類器をトレーニングできます。 ただし、テストとして使用するのに十分なテストデータセットがないため、初期データセットを「測定」して2つに分割します:トレーニング資料のセットと、モデルの精度を検証するために使用されるはるかに小さなデータセットです。



 <?php ... use Phpml\CrossValidation\StratifiedRandomSplit; ... $randomSplit = new StratifiedRandomSplit($dataset, 0.1); $trainingSamples = $randomSplit->getTrainSamples(); $trainingLabels = $randomSplit->getTrainLabels(); $testSamples = $randomSplit->getTestSamples(); $testLabels = $randomSplit->getTestLabels();
      
      





このアプローチは、相互検証と呼ばれます。 この用語は統計に基づいており、次のように定義できます。



相互検証(相互検証、ローリング制御、英語の相互検証)-独立したデータでの分析モデルとその動作を評価する方法。 モデルを評価するとき、利用可能なデータはk個の部分に分割されます。 次に、データのk-1部分でモデルトレーニングが実行され、残りのデータがテストに使用されます。 手順はk回繰り返されます。 最終的に、k個のデータのそれぞれがテストに使用されます。 その結果、選択したモデルの有効性が評価され、利用可能なデータが最も均一に使用されます。
-Wikipedia.com



ステップ4:分類器のトレーニング



最後に、SentimentAnalysisクラスに戻って実装する準備が整いました。 気づいていない場合、機械学習の大部分はデータの収集と処理に関連しています。 機械学習モデルの実際の実装は、それほど複雑ではない傾向があります。



ムード分析クラスを実装する3つの分類アルゴリズムがあります。







この演習では、最も単純なNaiveBayes分類子を使用します。そのため、学習機能を実装するためにクラスを継続して変更します。



 <?php namespace PhpmlExercise\Classification; use Phpml\Classification\NaiveBayes; class SentimentAnalysis { protected $classifier; public function __construct() { $this->classifier = new NaiveBayes(); } public function train($samples, $labels) { $this->classifier->train($samples, $labels); } }
      
      





ご覧のとおり、PHP-MLにすべてのハードワークを任せます。 私たちは私たちのプロジェクトのために少し抽象化するだけです。 しかし、分類器が本当に訓練されて機能するかどうかをどのようにして知るのでしょうか? testSamples



testLabels



を使用する時間。



ステップ5:分類器の精度の検証



分類子のテストを続行する前に、予測メソッドを実装する必要があります。



 <?php ... class SentimentAnalysis { ... public function predict($samples) { return $this->classifier->predict($samples); } }
      
      





また、PHP-MLが役立ちます。 classifyTweetsクラスを次のように変更しましょう。



 <?php ... $predictedLabels = $classifier->predict($testSamples);
      
      





最後に、訓練されたモデルの精度をテストする方法が必要です。 幸いなことに、PHP-MLもこれをカバーしており、いくつかのメトリッククラスがあります。 この場合、モデルの精度に関心があります。 コードを見てみましょう:



 <?php ... use Phpml\Metric\Accuracy; ... echo 'Accuracy: '.Accuracy::score($testLabels, $predictedLabels);
      
      





次のようなものが表示されるはずです。



 Accuracy: 0.73651877133106%
      
      





おわりに



この記事は大きすぎることがわかったので、学んだことを繰り返しましょう。





この投稿は、PHP-MLライブラリの紹介でもあり、ライブラリができることと、ライブラリをプロジェクトに統合する方法についてのアイデアを提供してくれることを願っています。



最後に、この投稿は決して包括的なものではなく、学び、改善し、実験する多くの機会があります。 方向性の開発方法について話し始めるためのアイデアをいくつか紹介します。





終わり



いつものように、私たちはあなたのコメントや意見を待っています。



All Articles