目次
サンプル・プログラムの実行例
サンプル・プログラム
BayesClassifier.php | サンプル・プログラム |
pahooTwitterAPI.php | Twitter APIを利用するクラス pahooTwitterAPI。 使い方は「PHPでTwitterに投稿(ツイート)する」などを参照。include_path が通ったディレクトリに配置すること。 |
サンプル・プログラムの流れ
学習処理では TwitterAPI は使わず、テーブル $table_tweets に登録されたツイートを取りだし、形態素解析ツール MeCab を使って単語に分解していく。MeCab については「PHPで MeCabのユーザー辞書を作成する」で紹介している。
準備
登録されたツイートのうち未学習のものをまとめて取り出す
0812: /**
0813: * 登録されたツイートのうち未学習のものをまとめて取り出す
0814: * @param string $userIDユーザーID
0815: * @param int $count取り出す最大件数
0816: * @return array(取り出したツイート, ツイート件数)
0817: */
0818: function takeTweet($userID, $count) {
0819: $sql_select = 'SELECT * FROM ' . $this->table_tweets . ' WHERE user_id=:user_id AND flag<>1';
0820: $sql_update = 'UPDATE ' . $this->table_tweets . ' set flag=:flag WHERE id=:id';
0821:
0822: //DB取得
0823: $stmt = $this->pdo->prepare($sql_select);
0824: $stmt->bindValue(':user_id', $userID, PDO::PARAM_STR);
0825: $ret = $stmt->execute();
0826: $cnt = 0;
0827: $text = '';
0828: while ($row = $stmt->fetch()) {
0829: $text .= $row['description'];
0830: $stmt2 = $this->pdo->prepare($sql_update);
0831: $stmt2->bindValue(':id', $row['id'], PDO::PARAM_STR);
0832: $stmt2->bindValue(':flag', 1, PDO::PARAM_INT);
0833: $ret = $stmt2->execute();
0834: $cnt++;
0835: if ($cnt >= $count) break;
0836: }
0837: $msg = 'Success SQLite: take ' .$cnt . ' tweets.';
0838: $this->putAppLog($msg, 1, __LINE__, __FUNCTION__);
0839:
0840: return array($text, $cnt);
0841: }
取り出したら、flag を立てておく。
テキストを単語ベクトルに変換
0790: /**
0791: * テキストを単語ベクトルに変換
0792: * @param string $textテキスト
0793: * @param array $vectors単語ベクトルを格納する配列
0794: * @return int分解した単語数
0795: */
0796: function text2vector($text, &$vectors) {
0797: $words = array();
0798: $cnt = 0;
0799: $this->getWords($text, $words); //単語分割
0800: foreach ($words as $word) {
0801: if (! $this->isword($word)) continue;
0802: if (isset($vectors[$word[0]])) {
0803: $vectors[$word[0]]++;
0804: } else {
0805: $vectors[$word[0]] = 1;
0806: $cnt++;
0807: }
0808: }
0809: return $cnt;
0810: }
学習する単語か否かは、メソッド isword で判定している。
この部分を変更することで、学習結果が変わってくる。
単語ベクトル情報を更新
0843: /**
0844: * 単語ベクトル情報を更新する
0845: * @param string $userIDユーザーID
0846: * @param array $vectors単語ベクトル情報
0847: * @return bool TRUE/FALSE
0848: */
0849: function updateVectors($userID, $vectors) {
0850: $sql_select = 'SELECT count FROM ' . $this->table_vectors . ' WHERE user_id=:user_id AND word=:word';
0851: $sql_insert = 'INSERT INTO ' . $this->table_vectors . ' (user_id, word, count, dt) VALUES (:user_id, :word, :count, :dt)';
0852: $sql_update = 'UPDATE ' . $this->table_vectors . ' set count=:count, dt=:dt WHERE user_id=:user_id AND word=:word';
0853:
0854: foreach ($vectors as $word=>$count) {
0855: $stmt = $this->pdo->prepare($sql_select);
0856: $stmt->bindValue(':user_id', $userID, PDO::PARAM_STR);
0857: $stmt->bindValue(':word', $word, PDO::PARAM_STR);
0858: $ret = $stmt->execute();
0859: $row = $stmt->fetch();
0860:
0861: //DB追加
0862: if (! isset($row['count'])) {
0863: $stmt2 = $this->pdo->prepare($sql_insert);
0864: $stmt2->bindValue(':user_id', $userID, PDO::PARAM_STR);
0865: $stmt2->bindValue(':word', $word, PDO::PARAM_STR);
0866: $stmt2->bindValue(':count', $count, PDO::PARAM_INT);
0867: $stmt2->bindValue(':dt', date(DATE_W3C, time()), PDO::PARAM_STR);
0868: $ret = $stmt2->execute();
0869: if ($ret < 1) {
0870: $this->error = TRUE;
0871: $this->errmsg = 'Error SQLite: ' . $word . ' -- cannot insert vectors.';
0872: $this->putAppLog($this->errmsg, 0, __LINE__, __FUNCTION__);
0873: return FALSE;
0874: }
0875: //DB更新
0876: } else {
0877: $stmt2 = $this->pdo->prepare($sql_update);
0878: $stmt2->bindValue(':user_id', $userID, PDO::PARAM_STR);
0879: $stmt2->bindValue(':word', $word, PDO::PARAM_STR);
0880: $stmt2->bindValue(':count', $row['count'] + $count, PDO::PARAM_INT);
0881: $stmt2->bindValue(':dt', date(DATE_W3C, time()), PDO::PARAM_STR);
0882: $ret = $stmt2->execute();
0883: if ($ret < 1) {
0884: $this->error = TRUE;
0885: $this->errmsg = 'Error SQLite: ' . $word . ' -- cannot update vectors.';
0886: $this->putAppLog($this->errmsg, 0, __LINE__, __FUNCTION__);
0887: return FALSE;
0888: }
0889: }
0890: }
0891: return TRUE;
0892: }
参考サイト
- PHPで機械学習(その1):ツイートを取得しDB格納:ぱふぅ家のホームページ
- PHPで機械学習(その2):ツイート内容を学習:ぱふぅ家のホームページ
- PHPで機械学習(その3):単純ベイズ分類機:ぱふぅ家のホームページ
- PHPとデータベース:ぱふぅ家のホームページ
- PHPでTwitterに投稿(ツイート)する:ぱふぅ家のホームページ
- 機械学習とは:sas
- ベイズの定理:高校数学の美しい物語
- 数式無しで理解する機械学習(エンジニア向け):情強志向
- 天文でも機械学習が始まるみたいです:迷人の日記
- PHPで形態素解析(分かち書き)する方法:浜村拓夫の世界
今回は、収集したデータ(ツイート)を単語に分解し、学習させた結果をデータベース(SQLite)に登録していく。
機械学習にはいくつかのアルゴリズムがあるが、ここでは実装が簡単な単純ベイズ分類器を用いることにする。学習方法は簡単で、ユーザー別の単語の出現回数をデータベースに登録していけばいい。
(2021年7月11日)PHP8対応,リファラ・チェック改良