それっぽい文章を書くAIを作る(Markov連鎖)

Python
この記事は約8分で読めます。

OpenAIのChatGPTやGoogleのBardなど生成AIがこの頃盛んですね。

今回はそれに便乗(?)して、それっぽい文章を書くAIもどきを作りたいと思います。

この記事が向いている人

  • Malkov連鎖で遊びたい人 or 学びたい人
  • Macabをインストールしたい人(下までスクロールしてください)

Markov連鎖とは

未来に起こることを、現在の事象のみで予測すること。

確率的に未来の事象を予測。

天気での例

上の天気での例では、今日の天気が晴れの時、

  • 40%で次の日も晴れ
  • 50%で次の日は曇り
  • 10%で次の日は雨

となります。

また、「現在の事象のみ」で未来のことが決まるため、「晴れ→雨→曇り→晴れ…」と現実ではありえないことが出力されることもあります。

文章にあてはめる

例として、「私はトマトが好きです。」と「私は休みが欲しいです。」という文があるとき、

その単語間の関係は次のようになります。

この関係をモデルといいます。

このマルコフモデルでは、形態素(各単語)をノード(結び目、集合点、節)としています。

この時、ランダムでノードを選択していくと、

「私はトマトが欲しいです。」という文が新たにできます。

これがMarkov連鎖での文章生成の仕組みとなります。

用意するもの

  • Windows Python3環境(pip)
  • 使いたいデータ

実際にやってみる

必要なものをインストール

MeCab

https://github.com/ikegami-yukino/mecab/releasesにアクセスし、LatestのexeをDL&実行

文字コード選択の際に UTF-8 を選択しましょう。

cmd上では文字化けしますが、問題ありません。

Pathも通しておきます。

<MeCabインストールフォルダ>\Mecab\bin 

上記のパスをを環境変数に追加しておきましょう。(自分の環境のものに置き換えてください)

mecab -v

が正常に帰ってきたらOKです。(できなかったら再起動など)

Pythonライブラリ

pip install mecab-python3
pip install markovify

動作確認用に下記のコードを実行してみてください。下のような返答があればおけです。

import MeCab
 
mecab = MeCab.Tagger()
target_str = "私には、走っていると思っていた時期があった。"
print(mecab.parse(target_str))
私      名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
、      記号,読点,*,*,*,*,、,、,、
走っ    動詞,自立,*,*,五段・ラ行,連用タ接続,走る,ハシッ,ハシッ
て      助詞,接続助詞,*,*,*,*,て,テ,テ
いる    動詞,非自立,*,*,一段,基本形,いる,イル,イル
と      助詞,格助詞,引用,*,*,*,と,ト,ト
思っ    動詞,自立,*,*,五段・ワ行促音便,連用タ接続,思う,オモッ,オモッ
て      助詞,接続助詞,*,*,*,*,て,テ,テ
い      動詞,非自立,*,*,一段,連用形,いる,イ,イ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
時期    名詞,副詞可能,*,*,*,*,時期,ジキ,ジキ
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
あっ    動詞,自立,*,*,五段・ラ行,連用タ接続,ある,アッ,アッ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。      記号,句点,*,*,*,*,。,。,。
EOS

もし ImportError: DLL load failed while importing _MeCab: 指定されたモジュールが見つかりません。のようなエラーが出る場合は、

C:\Users\<Username>\AppData\Roaming\Python\lib\site-packages\MeCab
の中のlibmecab.dll
C:\Users\<Username>\AppData\Roaming\Python\Python<Version>\site-packages\MeCab
に移動させましょう。(パスは環境によりけり)

もととなるデータを用意

今回は青空文庫にある「走れメロス」を使用しました。

そのままコピペするとルビ(以下)が紛れ込んでしまいます。

そのため、ブラウザのConsoleからコードを実行してコピペ、input.txtに保存。

Array.from(document.querySelectorAll('rt')).forEach(el => el.remove());

形態素解析でモデル生成&出力

import markovify
import MeCab
  

# 読み込み(input.txt)
with open("input.txt", "r", encoding="utf-8") as f:
    text = f.read()
    
# 形態素解析
parsed_text = MeCab.Tagger('-Owakati').parse(text)

print(parsed_text)

# モデル作成
text_model = markovify.Text(parsed_text, state_size=2, well_formed=False)

# 出力
for _ in range(10):
    sentence = text_model.make_short_sentence(100, 20, tries=100).replace(' ', '')
    print(sentence)
メロスは、おまえらは、二度、口から血が噴き出た。
メロスは、ゆらゆら地平線に没し、まさに最後の死力を尽して、ほっと溜息をついた。
メロスは両手で掬って、「ただ、――」と言いかけて、てれていた。
メロスは、よくよく不幸な男であったが、喉がつぶれて嗄れた声で低く笑った。
メロスは疾風の如く走り出た。
メロスは悪びれずに答えた。この嘘つきに騙された。
メロスは、あたりをはばかる低声で低く笑った。
メロスは、よろよろ二、三日目の前に引き出されて走ったのだ。生意気なことを命じて居りました。
メロスは、王は、よろよろと歩き出し、家へ帰って来るというのです。三日目の前に一隊の山賊が躍り出た。
メロスは、嗄れた声で精一ぱいに努めて来た。「とんでもない嘘を言うわい。どうせ帰って来た。

…..\(^o^)/

だいぶ怪しいですが、一応出力はされました。

意味を理解しているわけではないため、いろいろ混ざってしまっていますが、文法上の間違いは少ないです。

まあ何にせよ成功したためよかったです。

「メロスは」以外から始まるよう改善

import markovify
import MeCab
  

text = ""

# 読み込み(input.txt)
with open("input.txt", "r", encoding="utf-8") as f:
    for i in f.read().split('\n'):
        text += MeCab.Tagger('-Owakati').parse(i)
    

print(text)

# モデル作成
text_model = markovify.NewlineText(text, state_size=2) #ピリオドではなく改行で1文を判定
#state_sizeを伸ばせば伸ばすほど長文になります(5が上限、あげるほど単調になる)

# 出力
for _ in range(10):
    sentence = text_model.make_short_sentence(100, 20, tries=100).replace(' ', '')
    print(sentence)
ロスは、すぐに出発した時から正直な男のままにして死なせて下さい。
メロスは口惜しく、地団駄踏んだ。再び立って走れるように深く眠った。
それを聞いて王は、すぐに出発した時、メロスの十六の妹も、きょうは兄の、正直者とかいう奴輩にうんと見せつけてやりたいものさ。
群衆の中からも、きょうは兄の、正直者とかいう奴輩にうんと見せつけてやりたいものさ。
勇者は、ひどく赤面した。暴君ディオニスは、ものも言いたくなくなった。
どっと群衆の中からも、きょうは兄の、疲労困憊の姿を見つけて驚いた。
山賊たちは、単純な男であった。メロスの懐中からは短剣が出て仕事をはじめていた。
妹は頬を殴った。メロスの右頬を殴った。
どっと群衆の中からも、消えようとした時、メロスをひしと抱きしめた。
セリヌンティウスは、正義の士として死ぬ事が出来るぞ。ああ、陽は既に高く昇って、

「メロスは」以外から始まるようになりました。

おわりに

今回は、PythonのライブラリであるMarkovifyを使用して、それっぽい文章を生成する方法を紹介しました。

ただ、原因不明の挙動をすることが多かったため、もっと勉強する必要がありそうです。

この記事がどなたかの役に立てば幸いです。

それでは!

参考にさせていただいたサイト

https://omedstu.jimdo.com/2018/05/06/マルコフ連鎖による文書生成/

[Python] MeCab とマルコフ連鎖ライブラリ markovify を使い、文章を学習して自動生成する方法 - Qiita
はじめに日本語形態素解析エンジン MeCab とマルコフ連鎖ライブラリ markovify を使って文章を学習して自動生成します。markovify の使い方についても説明します。結果とりあ…
Learn from aozora bunko and output markov chain
Learn from aozora bunko and output markov chain. GitHub Gist: instantly share code, notes, and snippets.

コメント

タイトルとURLをコピーしました