BETA

phpでマルコフ連鎖を使って複数の文章(ツイート)を一つの文章にする

投稿日:2018-10-16
最終更新:2018-10-24

やりたいこと

phpでTwitterのアニメ実況ツイートを5件取得し、その5件のツイートを要約して1つのツイートにまとめる

方法が全然わからなかったのでYahoo知恵袋で質問をしたところ、マルコフ連鎖というアルゴリズムを使えばとりあえず実現できそうなことはわかった。

マルコフ連鎖とは?

名前だけ聞いたことはあったけど、よく知らなかったのでとりあえずググってみた。

マルコフ連鎖(マルコフれんさ、英: Markov chain)とは、確率過程の一種であるマルコフ過程のうち、とりうる状態が離散的(有限または可算)なもの(離散状態マルコフ過程)をいう。また特に、時間が離散的なもの(時刻は添え字で表される)を指すことが多い(他に連続時間マルコフ過程というものもあり、これは時刻が連続である)。マルコフ連鎖は、未来の挙動が現在の値だけで決定され、過去の挙動と無関係である(マルコフ性)。各時刻において起こる状態変化(遷移または推移)に関して、マルコフ連鎖は遷移確率が過去の状態によらず、現在の状態のみによる系列である。特に重要な確率過程として、様々な分野に応用される。 Wikipdiaより

うん...意味がわからない。

色々調べた結果わかりやすい解説を見つけた

一般に「マルコフ連鎖でついったーbot」と言われた時にみんながやっているのは(たぶん)下のようなこと。

まずはツイートひとつひとつを分かち書きする。

私はヨーグルトが好きです。 を分かち書きすると 私 は ヨーグルト が 好き です 。 になる。

ここから1つずらしながら、3つずつの要素からなる塊を以下のようにたくさんつくる。

(はじまり) 私 は 私 は ヨーグルト は ヨーグルト が ヨーグルト が 好き が 好き です 好き です 。 です 。 (おわり) これを対象となるすべてのツイートに対して作ってあげる。

上の「私はヨーグルトが好きです。」の他にもう1つ、「ヨーグルトが嫌いだ」というフレーズに対しても同様に作れば、

(はじまり) ヨーグルト が ヨーグルト が 嫌い が 嫌い だ 嫌い だ (おわり) となる。

こんな中で、3つの要素の塊をつなげていくのがマルコフ連鎖。 (マルコフ連鎖でTwitter Botをつくりましたより)

コード

<?php
function array_from_new_sentence_generation($array) {
    $str = "";

    foreach ($array as $str_foreach) {
      $str .= $str_foreach;
    }

    $keyword = "";

    /*
    gooの形態素解析APIを使う
    アプリケーションIDはこのページから取得↓
    https://labs.goo.ne.jp/jp/apiregister/
    */

    $POST_DATA = array(
        'app_id' => '<Your Application ID>',
        'sentence' => $str
    );
    $curl=curl_init("https://labs.goo.ne.jp/api/morph");
    curl_setopt($curl,CURLOPT_POST, TRUE);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($POST_DATA));
    curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl,CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($curl,CURLOPT_COOKIEJAR,      'cookie');
    curl_setopt($curl,CURLOPT_COOKIEFILE,     'tmp');
    curl_setopt($curl,CURLOPT_FOLLOWLOCATION, TRUE);

    $output= curl_exec($curl);

    $arr = json_decode($output,true);

    //gooの形態素解析APIからのデータ
    //var_dump($arr["word_list"]);

    $syugo;
    $jyutsugo;

    //品詞取得
    for ($n = 0; $n < count($arr["word_list"]); $n++){
      for ($i = 0; $i < count($arr["word_list"][$n]); $i++){
        //名詞だったら
        if ($arr["word_list"][$n][$i][1] == "名詞") {
          if ($arr["word_list"][$n][$i+1][1] == "名詞接尾辞") {
            //主語(多分)
            $syugo[] = $arr["word_list"][$n][$i][0].$arr["word_list"][$n][$i+1][0];
          } else {
            //名詞接尾辞がなかったら1つ目だけ
            $syugo[] = $arr["word_list"][$n][$i][0];
          }
        //形容詞だったら
        } else if ($arr["word_list"][$n][$i][1] == "形容詞語幹") {
          if ($arr["word_list"][$n][$i+1][1] == "形容詞接尾辞") {
            //述語(多分)
            $jyutsugo[] = $arr["word_list"][$n][$i][0].$arr["word_list"][$n][$i+1][0];
          }
        }
      }
    }
    //主語の配列
    //var_dump($syugo);
    //述語の配列
    //var_dump($jyutsugo);
    $syugo_random = array_rand($syugo,1);
    $jyutsugo_random = array_rand($jyutsugo,1);
    return $syugo[$syugo_random].$jyutsugo[$jyutsugo_random];
}

echo array_from_new_sentence_generation(array("さぎりたんかわいい","正宗かっこいい","とにかくかわいい","かわいすぎる","尊い..."));

実行結果

・さぎりたんかわいすぎ
・さぎりたん尊い
・さぎりたんかっこいい
・正宗かわいい

こんな感じで複数の文章を一つの文章にできた

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@tsumugu1515の技術ブログ

よく一緒に読まれる記事

4件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
10/16 20:32

バグってる?