サムネがコーヒーの記事は書きかけです。

N階マルコフ連鎖を利用して文章の再構築

前回、特定のユーザーのツイートをTwitter APIを使用して取得する方法について考えました。

今回は、せっかく取得したツイートのデータがあるので、マルコフ連鎖を利用して文章を再構築していきたいと思います。

マルコフ連鎖とは

wikipediaでマルコフ連鎖について調べると、以下のような定義が見つかります。

“各時刻において起こる状態変化(遷移または推移)に関して、マルコフ連鎖は遷移確率が過去の状態によらず、現在の状態のみによる系列である。”

https://ja.wikipedia.org/wiki/マルコフ連鎖#定義

言い換えれば、今の状態のみによって未来の状態が決定するということになります。

この性質の良いところは、過去の状態を使う必要が無いという点にあります。

N階マルコフ連鎖

過去の状態を使用しないと言えど、ある程度要素の因果関係をはっきりさせておきたい時にはN階マルコフ連鎖を使用します。

N階マルコフ連鎖とは、過去N個の状態の影響を考慮したマルコフ連鎖という意味です。

難しく聞こえますが、markovifyというモジュールを使用して実装していくため、コードはシンプルになります。

ツイートの取得

自分の過去ツイートを拾ってきてやってみます。

特定の人のツイートを一括取得する方法はこの記事にまとめています。

import tweepy
import unicodedata
 
API_KEY = "####################"
API_SECRET = "####################"
ACCESS_TOKEN = "####################"
ACCESS_TOKEN_SECRET = "####################"
 
def is_japanese(string):
    k = unicodedata.name(string,'a')
    if "CJK UNIFIED" in k or "HIRAGANA" in k or "KATAKANA" in k:
        return True
    else:
        return False

def is_dot(string):
    if string == '。' or string == '、':
        return True
    else:
        return False

auth = tweepy.OAuthHandler(API_KEY, API_SECRET) 
auth.set_access_token(ACCESS_TOKEN , ACCESS_TOKEN_SECRET) 
api = tweepy.API(auth) 

tweets = api.user_timeline(id='@japbros_poco',count=500)
text = ''
for t in tweets:
    text += str('。')
    for string in t.text:
        if is_japanese(string) or is_dot(string):
            text+= string
        else:
            pass
text += str('。')
print(text)

得られたツイートデータをtextに代入しておきます。

テキストの整形

マルコフ連鎖を使用して文章を再構築するために、テキストをあらかじめ整形しておきます。

この部分で形態素解析が必要になってきます。

import janome.tokenizer
import markovify
from text import text

tokenizer = janome.tokenizer.Tokenizer()
tokens = tokenizer.tokenize(text=text)
text = ''
for i in [t.surface for t in list(tokens)]:
    if i != '。':
        text += i   
    elif i == '。':
        text += '\n'
    text += ' '
print(text)

マルコフ連鎖の実装

上記のテキストを使用してマルコフ連鎖を実装していきます。

2階マルコフ連鎖の実装

N=2の場合について考えてみます。

初めに、2階マルコフモデルを生成します。

text_model = markovify.NewlineText(text, state_size=2)

生成したモデルを使用して、文章を生成します。

for i in range(20):
    print('sentence No.' + str(i))
    print(text_model.make_sentence(tries=100))

以下が実行結果です。

sentence No.0
解析 結果 を 研究 室 から もらっ た けど 外資 系 って そういう こと ね
sentence No.1
学会 発表 で これ やっ て たら 、 累乗 の 記号 を じ ゃなくてにしててずっと エラー なっ て ほしく なく て 、 めちゃくちゃ 罪悪 感 が ある
sentence No.2
はま 寿司 の カルフォルニア ロール
sentence No.3
数行 の コード です から 、 研究 室 初日 タスク の 部屋 の 片付け
sentence No.4
家 帰っ て き た
sentence No.5
あー 失敗 だ 最悪 、 先生 に は ちゃんと 自信 が ある
sentence No.6
就活 って 、 多方面 の 経験 から くる 独創 性 を 無視 し て いざ 日本 に 来 た エビ の 友達 き た バイオインフォマティクス の アルゴリズム を 自分 の 得意 分野 に は なり そう
sentence No.7
学会 発表 で これ やっ て たら ミッドサマー みたい な 臭い する
sentence No.8
従業 員 全員 女 の 会社 で 育休 産休 を 推進 し たら し て たら ミッドサマー みたい な 記事 掘り返し た
sentence No.9
検査 し たら 結構 な 頻度 で 日本語 勉強 し てる けど 、 留学 先 に データ 送ら れ て も わから ん けど 読ん だら スペイン 語 動詞 可愛 すぎる 絶対 泣き声 そのまま 動詞 に なっ て た ので あと 週間 延長 です
sentence No.10
話題 の デートスポット に 週末 お出かけ 、 家 で は のんびり 好き な 分野 さえ 把握 でき て 後で 振り返れ た の に なっ た ちょっと 嬉しい けど 大変 そう
sentence No.11
年明け から ずっと 禁欲 し てる 週末 デート 俺 断然 の 方 が 何 歳 な の か 一切 知ら ない 普段 会話 で 気 に し て た から 引っ張り 出し たら タマネギ だっ た
sentence No.12
誰 か 私 を 幸せ に し てる けど 、 よほど 凄腕 ハッカー 相手 に し てる こと に 気づい て ない シカ 可愛い
sentence No.13
移行 が 中途半端 で 二つ の 研究 室 の 水槽 に エビ の 友達 が 魚 の 赤ちゃん 足 で 挟ん で 連れ 回っ てる
sentence No.14
応答 曲面 作ろ う と し た おかげ で 好き な 分野 さえ 把握 でき て 後で 振り返れ た の アホ みたい や けど 、 やっぱり 一 人 で いる の が 大変 な 日本語 を め ちゃ くち 頑張っ て 習得 し て ジョン ・ ・ ケネディ 国際 空港 に 着陸 と 同時に 死に ます
sentence No.15
い なかっ たら 俺 も 頑張ろ う と 試み て たら 、 、 って なっ て ほしく なく て 、 図星 すぎ て スカイ ダイビング し たい から マック から 送っ てる
sentence No.16
家具 とか ほぼ 買っ て ない と 参加 でき ない らしい
sentence No.17
検査 し て 後 から 役に立て ば いい や と 思っ て た 人 って 外国 語 の 発音 も 上手 だ し 、 自分 の 得意 分野 を 誰 か に 役立てる こと し てる だけ で 乗っ取ら れ た って 言っ て 全く 筋 トレ し たら 童貞 だっ た
sentence No.18
踏ん だ だけ で 乗っ取ら れ た って 言っ てる 人 よく 見る けど 、 グラフ に し て いざ 日本 に いる とき 結構 な 頻度 で 日本語 勉強 し て 後 から 役に立て ば いい や と 思っ てる
sentence No.19
いま まで 考え て き て 開口一番 が な の か な

俺が言いそうなことが自動生成されています。

3階マルコフ連鎖の実装

試しにN=3の場合も実装して結果を見てみます。

import janome.tokenizer
import markovify
from text import text

tokenizer = janome.tokenizer.Tokenizer()
tokens = tokenizer.tokenize(text=text)
text = ''
for i in [t.surface for t in list(tokens)]:
    if i != '。':
        text += i   
    elif i == '。':
        text += '\n'
    text += ' '
print(text)
text_model = markovify.NewlineText(text, state_size=3)
for i in range(20):
    print('sentence No.' + str(i))
    print(text_model.make_sentence(tries=100))

実行結果は以下です。

sentence No.0
外国 に いる とき 結構 な 頻度 で 日本語 勉強 し てる の を 見 て くれ て た の は 嬉しい
sentence No.1
だから 誰 か が この 国 の って とこ に 行き たい って 言っ てる 人 よく 見る けど 、 よほど 凄腕 ハッカー 相手 に し てる やつ い て おもしろかっ た
sentence No.2
本当 の スクワット は 回 やっ た だけ で 汗だく に なる とか 言っ て て ソリ が 合わ なく なっ た
sentence No.3
美容 師 行っ た 日 後 くらい が 当初 予定 し て い た ので 、 データ に なら ない と いけ ない タイミング が すぐ 訪れる よ ね
sentence No.4
禁欲 ヶ月 目 に 習得 し た 、 欲求 に 負け そう に なっ て て 部屋 で ひっくり返っ てる
sentence No.5
踏ん だ だけ で 乗っ取ら れ た って 言っ てる 気持ち が わから ない
sentence No.6
利き手 だけ 筋 トレ し ない 奴
sentence No.7
踏ん だ だけ で 乗っ取ら れ た って 言っ てる 気持ち が わから ない
sentence No.8
自分 と 向き合う の が 一番 楽しい 家 の 外 に 出 て き た とりあえず 明日 は 研究 室 初日 タスク の 部屋 の 片付け
sentence No.9
と が おんなじ よう な もの だ と 思っ て たら 、 累乗 の 記号 を じ ゃなくてにしててずっと エラー なっ て た
sentence No.10
ラカンパネラ ずっと 弾い てる だけ で もう 十分
sentence No.11
いま まで 考え て き た ちなみに 曲名
sentence No.12
最近 よく お腹 壊れる と 思っ て たら 、 累乗 の 記号 を じ ゃなくてにしててずっと エラー なっ て た
sentence No.13
細胞 検出 は だいぶ 精度 上がっ て き てる の を 見 て くれ て た の は 嬉しい
sentence No.14
外資 系 っていう 言葉 今 まで なん な の か 一切 知ら ない 普段 会話 で 気 に し ねえ から
sentence No.15
三 連休 リラックス し まくっ た から 、 研究 室 変わっ た ついで に パソコン 初期 化 する
sentence No.16
ラカンパネラ ずっと 弾い てる だけ で もう 十分
sentence No.17
この 前 研究 室 の 水槽 に 来 た エビ の 友達 が 何 歳 な の か 分かっ て なかっ た けど 外資 系 って そういう こと ね
sentence No.18
本当 の スクワット は 回 やっ た だけ で 汗だく に なる とか 言っ て て ソリ が 合わ なく なっ た
sentence No.19
美容 師 行っ た 日 後 くらい が 当初 予定 し て い た ので 、 データ に なら ない か 不安

以上で、人のツイートを拾ってきて、その人がいいそうなことを自動生成するプログラムの完成です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です