N階マルコフ連鎖を使用して特定の人がいいそうな事を自動生成するプログラムを作っていきます。
マルコフ連鎖の理論は以下のリンク先に書いてありますが、これらの理論を実装したモジュールがあるため理解しなくても大丈夫です。
https://en.wikipedia.org/wiki/Markov_chain
目次
テキストの取得
自動生成と言いましたが、生成元となるデータが必要なため、別途txtファイル等にあらかじめ対象の発言を保存しておく必要があります。
このため、以下実行ディレクトリに”text.txt”が存在するものとしてコードを書いていきます。
text = "".join([i for i in open("text.txt").readlines() if i != "\n"])コンストラクタ
tokenizerクラスも含めた変数を初期化しておきます。
import janome.tokenizer
import markovify
class Sentence:
def __init__(self,text) -> None:
self.text = text
self.tokenizer = janome.tokenizer.Tokenizer()
self.tokens = None
self.sentence = ""
self.model = None
passTokenizerクラスからトークン取得メソッドを継承しました。
トークンの作成
形態素解析用のモジュールを使用してトークンを取得します。
def tokenize(self) -> None:
self.tokens = self.tokenizer.tokenize(text=self.text)ここまでで、元となる文章のトークン化が完了しました。
マルコフ連鎖モデルの作成
marcovifyモジュールを使用すると一行でマルコフ連鎖を導入できます。
ビルトインではないため、pipを使用してモジュールを取得しておきます。
pip install janome
pip install marcovifydef setModel(self) -> None:
self.model = markovify.NewlineText(self.sentence, state_size=2)文章のベクトル化
形態素解析で取得したトークンから、マルコフ連鎖で文字列を再生成するために文字列をベクトル化します。この際、staticメソッドとして、句読点を判別できる関数を別途用意します。
def generateSentence(self) -> None:
for i in [t.surface for t in list(self.tokens)]:
if self.isPunctuation(i):
self.sentence += '\n'
else:
self.sentence += i
self.sentence += ' '
@staticmethod
def isPunctuation(char):
if char == '。':
return True
return False結果の取得
ゲッターメソッドとして、自動生成された文章を取り出します。
def getResult(self) -> str:
return self.model.make_sentence(tries=100)コード全体像
コピーアンドペーストで実行できるようにテンプレートを置いておきます。
実行のためのメインメソッドを追加しています。
import janome.tokenizer
import markovify
class Sentence:
def __init__(self,text) -> None:
self.text = text
self.tokenizer = janome.tokenizer.Tokenizer()
self.tokens = None
self.sentence = ""
self.model = None
pass
def tokenize(self) -> None:
self.tokens = self.tokenizer.tokenize(text=self.text)
@staticmethod
def isPunctuation(char):
if char == '。':
return True
return False
def setModel(self) -> None:
self.model = markovify.NewlineText(self.sentence, state_size=2)
def generateSentence(self) -> None:
for i in [t.surface for t in list(self.tokens)]:
if self.isPunctuation(i):
self.sentence += '\n'
else:
self.sentence += i
self.sentence += ' '
def getResult(self) -> str:
return self.model.make_sentence(tries=100)
def main(text):
sentence = Sentence(text)
sentence.tokenize()
sentence.generateSentence()
sentence.setModel()
print(sentence.getResult())
if __name__ =="__main__":
main("".join([i for i in open("text.txt").readlines() if i != "\n"]))

