Music
マルコフ連鎖を使って一千一秒物語の新作が読みたい [TextGenerator]
2019.1.12 JS FrontEnd CSS Design

僕Pythonはおろかプログラミングにド素人なので、その辺はご了承ください!

あなたはよく読む本ってありますか?
小説の場合、一回読んで終わりってことが多いですが、常に懐に忍ばせている本があります。
それが 稲垣足穂「一千一秒物語」です。
稲垣足穂(1900-1977)とは大正モダニズムの中でギラッギラな作品を遺した方で、のちの「少年愛の美学」で第1回日本文学大賞を受賞しました。
神戸に住む僕にとってこの人の存在は大きくて、この「一千一秒物語」は主に北野とか山本通の街に起こるモダンなおとぎ話(ショートショートよりも短い)が幾つか収録されています。
かいつまんでみると、お月様にぶん殴られたり星を食べたりポケットの中に入れた自分を落としてしまったり、未来派と呼ばれた作風は今読んでも新鮮ですわ。

で、稲垣足穂さんはとっくの昔にお亡くなりになっているし、ずっと同じような作風で書いてるわけではなくて、おんなじようなものは「第三半球物語」くらいしかありません。でも新作が読みたい!!
自分で書いて見たこともありましたが、恥ずかしいのでやめました

というわけで、技術の力を使います。
よくTwitterのbotとかであるマルコフ連鎖を使います。
しゅうまい君とか、タイムラインの文章を学習するやつと同じです。

しゅうまい君 (@shuumai) | Twitterhttps://twitter.com/shuumai

Twitterで簡単にbotを組めるサービスとかありますが、今回は
ともっくすさんによる TextGeneratorを使わせてもらいます。

さらに一番Forkが多かったからあげ先生もものを使います。

karaage0703 / TextGeneratorhttps://github.com/karaage0703/TextGenerator

Pythonで動作し、形態素分析には MeCabを使います。

  1. 一千一秒物語を学習させる
  2. MeCabで形態素分析
  3. マルコフ連鎖で文章生成

という流れです。

下ごしらえ

 

macOSで動かすことを前提に書きます。
ほとんどの作業をTerminal.appで行います。

NOTE

この記事にはターミナルのコマンドを記載してあります。
$ が入ってあるコマンドはあなたが打ち込むコマンドです。打ち込む時$は省きます。

多分こんなことしようと持っている人は大丈夫だと思いますが、
brewのインストールとか一応書いておきます。
Python2はMacにあらかじめ入っています。

Python

pythonコマンドでインストールされているPythonを確認します。

$ python
Python 2.7.10 (default, Feb  6 2017, 23:53:20) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 

↑こんな風に出たらOKです。
⌘+D を押してエスケープします。

pipを入れる

curlでpipのインストーラファイルをダウンロードします。

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

次に、ダウンロードしたファイルをPythonで実行します。

$ python get-pip.py --user

次にパスを通します。

$ export PATH="$HOME/Library/Python/2.7/bin:$PATH"
$ echo 'export PATH="$HOME/Library/Python/2.7/bin:$PATH"' >> ~/.bash_profile

次にインストールできているか確認します。

$ pip -V
pip 18.1 from /.../Library/Python/2.7/lib/python/site-packages/pip (python 2.7)

と出ればOKです。

Homebrewを入れる

次にmacOS用のパッケージマネージャ Homebrew をインストールします。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

インストールができたら

$ brew -v

で確認します。

Homebrew 1.8.2
Homebrew/homebrew-core (git revision 1377de; last commit 2018-11-06)

みたいなのが出たらOKですよ。

Gitを入れる

$ brew install git

でGitをインストールします。

$ git --version

でインストールできているか確認しましょう。

これで下ごしらえはできました。

MeCabを入れる

形態素解析エンジンMeCab (和布蕪)を入れます。

MeCabは 京都大学情報学研究科−日本電信電話株式会社コミュニケーション科学基礎研究所 共同研究ユニットプロジェクトを通じて開発されたオープンソース 形態素解析エンジンです。
言語, 辞書,コーパスに依存しない汎用的な設計を 基本方針としています。 (中略)
また、平均的に ChaSen, Juman, KAKASIより高速に動作します。 ちなみに和布蕪(めかぶ)は, 作者の好物です。

とのことです。

MeCabは日本語の文を解析し、形態素を分けて、カテゴライズしてくれる代物です。

形態素(けいたいそ)というのは「意味をもつ表現要素の最小単位」のことです。

言語学の用語で、意味をもつ表現要素の最小単位。 ある言語においてそれ以上分解したら意味をなさなくなるところまで分割して抽出された、音素のまとまりの1つ1つを指す。

形態素 – Wikipedia

例えば

その進化はミニじゃない。

という文があって、これを形態素ごとに分けると、

その / 進化 / は / ミニ / じゃ / ない / 。

となります。
この形態素ごとに分ける作業をやってくれるのがMeCabさんということです。
すごいですね!

インストール

Homebrewからインストールします。

$ brew install mecab

でインストールされます。
次にMeCabに辞書を追加します。

$ brew install mecab-ipadic

インストールできたら、試しに実行して見ます。
mecabを実行した後、文章を入れてエンターします。

$ mecab
その進化はミニじゃない。
その  連体詞,*,*,*,*,*,その,ソノ,ソノ
進化  名詞,サ変接続,*,*,*,*,進化,シンカ,シンカ
は   助詞,係助詞,*,*,*,*,は,ハ,ワ
ミニ  名詞,一般,*,*,*,*,ミニ,ミニ,ミニ
じゃ  助詞,副助詞,*,*,*,*,じゃ,ジャ,ジャ
ない  助動詞,*,*,*,特殊・ナイ,基本形,ない,ナイ,ナイ
。   記号,句点,*,*,*,*,。,。,。
EOS

すげえ!

これだけでなんかもうやばいです。

次に、TextGeneratorはPythonで書かれているので、MeCabをPythonから動かせるようにしないといけません。

$ pip install mecab-python-0.996.tar.gz 

をインストールして、Pythonから動かせるようにします。

TextGeneratorを動かす

いよいよ、TextGeneratorを使ってみます。
Gitからcloneしてきます。

$ git clone https://github.com/karaage0703/TextGenerator

cloneできたら、ディレクトリに移動します。

$ cd TextGenerator

素材ファイルを作る

からあげ先生のForkでは、sample.txtからサンプリングするようになっています。
ですのでここに「一千一秒物語」を入れれば、マルコフ連鎖で新作が出来上がるということですね!

今回は著作権上ここに載せちゃいけないのでオリジナルの一千一秒物語ライクな文章を作りました。

キネオラマのお月様がぶら下がっている夜 プラタナスの並木道を一人で歩いていると
後ろから聞き覚えのあるモーターバイクの音が聞こえてきた
誰だろうと思っていると友人であったので挨拶をしたが
モーターバイクを止めるなり「自分を落としてしまった」友達が言うので
ガス灯の明かりを元にあたりを探し回ったが ついに見つけることができなかった

これをsample.txtに書き込み保存します。
このファイルを元にデータベースを作ります。

$ python PrepareChain.py sample.txt

を実行するとデータベースファイルができあがります。
このデータベースを元に、文章を生成します。

$ python GenerateText.py 10

後ろの10というのは文の数です。

これで生成されたのがこちら↓

モーターバイクを止めるなり「自分を落としてしまった」友達が言うので誰だろうと思っていると誰だろうと思っていると誰だろうと思っていると誰だろうと思っているとモーターバイクを止めるなり「自分を落としてしまった」友達が言うので誰だろうと思っていると友人であったので挨拶をしたが誰だろうと思っていると友人であったので挨拶をしたが誰だろうと思っているとキネオラマのお月様がぶら下がっていると友人であったので挨拶をしたが ついに見つけることができなかった

意味がわかんないです

多分、サンプリングしたテキストが短すぎるんですよね。
ブログには書けませんが、ここは一人でシコシコ書き写していくとして、記事的に終わらせるために、青空文庫にあったカフカの「城」をサンプリングします。

フランツ・カフカ 城 | 青空文庫https://www.aozora.gr.jp/cards/001235/card49862.html

たといほんとうはもういかせた。どうもひどく身体の工合がいいのでしょう。
あの子の好意を確保することに関しては、わたしにたよったりなんかしないと――私はちょっとした勢力を得たのだが、この件についての記録をくわしく考えることはどれくらい前の朝、眼の前にある人間は、亭主は、小生は怒るでしょう。
「また助手たちによってさえもありえますが、そのため陳情人たちはほんとうにだれがいっさいのことは、フリーダを見るのは、若い健康な娘たちの困難、いや午前中に村長がいった。
というのは、建物は前面よりもまず、父がすでに終ってしまったら、あの人はすぐにまた身体をほとんど全部焚きつくして、自分が驚いた顔つきをしてはいますが、次に自分のために、わたしたちの義務であってももちろんいつでも自分自身を君に何も私は体験した。
「でも、それはバルナバスには望みが少なくとも橋亭では、クラムについてもたえず新しいことを保証します」と、アマーリアがソルティーニから受け取って調べている人のほうをながめているんですわ。
少なくとも、君にどんなことが、前へ前へと小さな家々と凍いてついた窓ガラスのがたがたいう音が聞こえた。
どうしてそんなところはないもんで?」と、村長がいった。
そして、中傷だって?」ともかく君の手を取っているのは、客たちは毛布をかぶってストーブのそばで横になり、ふと立ち上がって、不可解なほどすっかり疲れたように命令し、過労と失望との交渉に疲れきって、ハンスに何が起って、衣きぬずれの音がしないような事件を扱うことでしょう」

本編より読むの疲れますね!!
僕も疲れました!!!!

機械が読みやすい文章を作る

まだ諦めたくないので、sample.txtを改良します。

キネオラマのお月様が ぶら下がっている夜、プラタナスの並木道を 一人で歩いていると、
後ろから聞き覚えのある モーターバイクの 音が聞こえてきた。
誰だろうと思っていると 友人であったので挨拶をしたが、
モーターバイクを 止めるなり 「自分を落としてしまった」 友達が言うので、
ガス灯の明かりを 元にあたりを探し回ったが、ついに見つけることができなかった。

このように、句読点をつけて、意味が分かれるところでは意図的に半角スペースを入れてあります。
これを元に生成した作品をご覧ください。

「ついに見つけることができなかった話」

ガス灯の明かりを元にあたりを探し回ったが、ついに見つけることができなかった。モーターバイクを止めるなり「自分を落としてしまった」友達が言うので、キネオラマのお月様がぶら下がっている夜、プラタナスの並木道を一人で歩いていると、キネオラマのお月様がぶら下がっている夜、プラタナスの並木道を一人で歩いていると、後ろから聞き覚えのあるモーターバイクの音が聞こえてきた。後ろから聞き覚えのあるモーターバイクの音が聞こえてきた。誰だろうと思っている夜、プラタナスの並木道を一人で歩いていると、後ろから聞き覚えのあるモーターバイクの音が聞こえてきた。モーターバイクを止めるなり「自分を落としてしまった」友達が言うので、ガス灯の明かりを元にあたりを探し回ったが、ついに見つけることができなかった。

???????