pythonで文章生成 ~形態素解析によるアメコミヒーローのプロフィール生成~

python,文章生成,python,形態素解析,文章生成

今回はpythonのMeCabとmarkovifyで形態素解析を行い、以前スクレイピングしたアメコミヒーローの情報をもとにプロフィール情報をしてみました。

スクレイピング自体については以下過去記事参照。

今回入力データは上記のスクレイピングで出力したエクセルを使用します。ただし、上記参照しなくとも以下のエクセルを使用いただければ大丈夫です。

ソースコード

使用する主なライブラリはMeCabとmarkovify。

import tkinter
from tkinter import filedialog
import os.path

import pandas as pd

import MeCab
import markovify


# エクセルファイルを開く
fTyp = [("", "*")]
iDir = os.path.abspath(os.path.dirname(__file__))
filename = tkinter.filedialog.askopenfilename(filetypes=fTyp, initialdir=iDir , title="対象のエクセルファイルを選択" )

# エクセルファイルを読み出し
d = pd.read_excel(filename)

data = []
for index, row in d.iterrows():
    input_data = row['能力']
    if None != input_data:
        data.append(input_data)

def main():
    global data
    mecab = MeCab.Tagger()

    # 上手く解釈できない文字列を定義しておく
    breaking_chars = ['(', ')', '[', ']', '「', '」','"', "'","nan"]
    # 最終的に1文に収めるための変数
    splitted_profile = ''

    for line in data:
        #print('Line : ', line)
        # lineの文字列をパースする
        parsed_nodes = mecab.parseToNode(str(line))

        while parsed_nodes:
            try:
                # 上手く解釈できない文字列は飛ばす
                if parsed_nodes.surface not in breaking_chars:
                    splitted_profile += parsed_nodes.surface
                # 句読点以外であればスペースを付与して分かち書きをする
                if parsed_nodes.surface != '。' and parsed_nodes.surface != '、':
                    splitted_profile += ' '
                # 句点が出てきたら文章の終わりと判断して改行を付与する
                if parsed_nodes.surface == '。':
                    splitted_profile += '\n'
            except UnicodeDecodeError as error:
                print('Error : ', line)
            finally:
                # 次の形態素に上書きする。なければNoneが入る
                parsed_nodes = parsed_nodes.next

    # print('解析結果 :\n', splitted_profile)

    # マルコフ連鎖のモデルを作成
    model = markovify.NewlineText(splitted_profile, state_size=3)

    # 文章を生成する
    for i in range(10):
        sentence = model.make_sentence(tries=1000)
        if sentence is not None:
            # 分かち書きされているのを結合して出力する
            print('---------------------------------------------------')
            print(''.join(sentence.split()))
            print('---------------------------------------------------')
        else:
            print('None')

if __name__ == "__main__":
    main()

以下をエクセルの列(「能力」か「概要」)にすることで期待する列の出力が得られます。

    input_data = row['能力']

出力結果

能力の場合

それっぽいけど若干何を言っているかわからない。

---------------------------------------------------
完全に生命力を吸い取り、自らの生命力を吸われた犠牲者はセレーネと同じく生命力を吸い取り、自らの生命力を吸収された身体能力を持つ。
---------------------------------------------------
---------------------------------------------------
壁を登ることが可能。
---------------------------------------------------
---------------------------------------------------
従って、外から見ると命じるだけで他人の意思を支配し、その肉体を自分のもののように見ることができる。
---------------------------------------------------
---------------------------------------------------
体全体を膨張させて超人的な速度で行動できる。
---------------------------------------------------
---------------------------------------------------
ハイペリオンなどスクワードロン・スプリームのキャラクターは、出身次元が作品によって飛行、フォースフィールド、エネルギーブラストなどスーパーヒー 
ローのような危険察知能力。
---------------------------------------------------
---------------------------------------------------
これにより超人的な怪力。
---------------------------------------------------
---------------------------------------------------
作中、ウェンウーは『マンダリン』という名前は、お気に入りのテレビ番組からつけた。
---------------------------------------------------
---------------------------------------------------
ヒョウ型になれば超人的な腕力や身体能力を持つ。
---------------------------------------------------
---------------------------------------------------
使い方によって超人的な腕力、耐久力、身体能力。
---------------------------------------------------
---------------------------------------------------
マークはスマイス博士と共にテレポートする魔法は重宝されていても非常に低い確率である。
---------------------------------------------------

概要の場合

正直文章生成というより、文章を抽出しただけのように見える。

---------------------------------------------------
兄を探すためにM.U.S.E.L.D.と新チャールズ・エグゼビア学園に引取られる。
---------------------------------------------------
---------------------------------------------------
実は祖母がセレーネらしく、父親と思って1人地球に帰還を果たしたスパイダーマンやデアデビルなど、ニューヨークのクライムファイターとして発見した。 
---------------------------------------------------
---------------------------------------------------
髪色は茶であるが、自分の活動も見逃せない。
---------------------------------------------------
---------------------------------------------------
地球では、シークレット・インベージョンのとき、スクラルに入れ替わられていたペギー・カーターの姪である。
---------------------------------------------------
---------------------------------------------------
動物と鳥類のハイブリッドバードブレインを巡る事件の際はサヴェッジランドで活動するX-MEN設立前に二番目のモデルとして活動することがあり、頭脳のリー
ドに対して協力的。
---------------------------------------------------
---------------------------------------------------
オリジナルであるスパイダーマンに続いてアルティメット・ユニバースの二代目となる。
---------------------------------------------------
---------------------------------------------------
シビル・ウォーIでは、元ニューウォリアーズとして活動した。
---------------------------------------------------
---------------------------------------------------
M-Dayで能力を消失し、人間の体に戻す研究を続けている。
---------------------------------------------------
---------------------------------------------------
ウルヴァリンの恋人だった時期もあった。
---------------------------------------------------
---------------------------------------------------
その際、オーディンの娘であるメイガステクナークの子として通用した。
---------------------------------------------------

参考サイト

今回形態素解析を実装するにあたり以下サイトを参考にしました。形態素解析についてもかなり簡単かつ分かりやすく説明してくれています。

感想

ちゃんと使える文章を生成させるにはまだまだ課題がありそうです。

今回はマルコフ連鎖を用いて文章の生成を行いましたが、次はディープラーニングの手法を用いて、より使い勝手のいい文章の生成に挑戦してみたいと思います。