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

誰かが言いそうなことを自動生成するプログラム Python

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
        pass

Tokenizerクラスからトークン取得メソッドを継承しました。

トークンの作成

形態素解析用のモジュールを使用してトークンを取得します。

def tokenize(self) -> None:
        self.tokens = self.tokenizer.tokenize(text=self.text)

ここまでで、元となる文章のトークン化が完了しました。

マルコフ連鎖モデルの作成

marcovifyモジュールを使用すると一行でマルコフ連鎖を導入できます。

ビルトインではないため、pipを使用してモジュールを取得しておきます。

pip install janome
pip install marcovify
def 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"]))
    

コメントを残す

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