第八話 より正しい(?)日本語で、タイトルを生成させてみます ~生まれ変わったら負けないもえるバトラー満員電車
フレ登録、ブクマ、ポイント、ご質問などお気軽にどうぞ。
なおコードの左に全角スペースが2個入っている所が、実行時にエラーになる場合は、Tabに変更して実行してください。
みなさんこんにちは。なろう系タイトルジェネレータ開発の第八話です。
第七話では、キーワードをファイルから読み込めるようにしてみました。今日はその機能を利用して、日本語としてより正しい、より質の高いタイトルを作ることに、挑戦してみたいと思います。
さてここで、簡単な質問なのですが、「日本語として正しい、より質の高いタイトルを作るための方法」として、最近有名なのは、なんでしょうか?
はい、そこのあなた正解です。そう、正解は「新聞や論文、なろうの小説などを使って、日本語を学習させた人工知能に作らせる」、ですね。
そこで、私も人工知能を使うことを考えたんですけど、そういうのって研究者とか、サラリーマンの人が、国家や企業からお金をもらいながらやっているものですし、私のように趣味でなろうのタイトルを生成させたいと思っている人などは、誰からもお金をもらえません(きっぱり。
ということで、私は「学習をしてもらった人工知能がどう動くか」を、想像し、それをプログラムで簡単に実現することで、「人工知能もどき」を作ることにしました。さて、そんなことうまくいくのでしょうか?
そんな無謀なチャレンジに、簡単に挑戦してみた結果が、このコードです。
(コードここから)
# -*- coding: utf-8 -*-
import tkinter
import random
title_str = ""
n_depth = 0
depth_max = 0
use_encode='utf-8' #shift-jis or utf-8
def read_word_list(filename):
read_data=[]
list_return=[]
with open(filename,mode="rt",encoding=use_encode) as f:
read_data = list(f)
for i in read_data:
list_return.append(i.replace('\n',''))
return list_return
list_word_top=[]
list_word_top = read_word_list("word_list_top.txt")
list_word_meisi=[]
list_word_meisi = read_word_list("word_list_meisi.txt")
list_word_keiyou=[]
list_word_keiyou = read_word_list("word_list_keiyou.txt")
list_word_jyosi=[]
list_word_jyosi = read_word_list("word_list_jyosi.txt")
list_word_dousi=[]
list_word_dousi = read_word_list("word_list_dousi.txt")
list_word_keidou =[]
list_word_keidou = read_word_list("word_list_keidou.txt")
list_word_bottom =[]
list_word_bottom = read_word_list("word_list_bottom.txt")
#ウインドウ設定
tk=tkinter.Tk()
tk.title(u"なろう系タイトルジェネレータ")
tk.minsize(480,200)
#ウインドウ表示
win=tkinter.Canvas(bg="black",width=480,height=200)
win.place(x=0,y=0)
btn_quit = tkinter.Button(tk, text='終了')
btn_quit.place(x=130, y=80)
btn_create = tkinter.Button(tk, text='自動作成')
btn_create.place(x=50, y=80)
txt_title=tkinter.Label(text=u"ここにランダムで作成したタイトルが表示されます。")
txt_title.place(x=0,y=0)
def select_keyword(keyword_list):
n=len(keyword_list)
return keyword_list[random.randint(1,n)-1]
def make_title_start():
global title_str
global n_depth
global depth_max
title_str = ""
n_depth=0
depth_max = random.randint(4,7)
p_top=3
p_meisi=50
p_keidou=70
p=random.randint(1,100)
if(p<p_top):
gene_top()
elif(p<p_meisi):
gene_meisi()
elif(p<p_keidou):
gene_keidou()
else:
gene_keiyou()
def gene_top():
global title_str
global n_depth
global depth_max
p_meisi=30
p_keiyou=70
title_str=title_str+select_keyword(list_word_top)
if(n_depth<depth_max):
n_depth=n_depth+1
p=random.randint(1,100)
if(p<p_meisi):
gene_meisi()
elif(p<p_keiyou):
gene_keiyou()
else:
gene_keidou()
def gene_meisi():
global title_str
global n_depth
global depth_max
p_bottom=1
p_meisi=3
p_jyosi=90
title_str=title_str+select_keyword(list_word_meisi)
if(n_depth<depth_max):
n_depth=n_depth+1
p=random.randint(1,100)
if(p<p_bottom):
gene_bottom()
elif(p<p_meisi):
gene_meisi()
elif(p<p_jyosi):
gene_jyosi()
else:
gene_keidou()
def gene_keiyou():
global title_str
global n_depth
global depth_max
p=random.randint(1,100)
title_str=title_str+select_keyword(list_word_keiyou)
gene_meisi()
def gene_jyosi():
global title_str
global n_depth
global depth_max
p_meisi=30
p_keiyou=60
p_dousi=90
title_str=title_str+select_keyword(list_word_jyosi)
n_depth=n_depth+1
p=random.randint(1,100)
if(p<p_meisi):
gene_meisi()
elif(p<p_keiyou):
gene_keiyou()
elif(p<p_dousi):
gene_dousi()
else:
gene_keidou()
def gene_dousi():
global title_str
global n_depth
global depth_max
p_meisi=45
p_keiyou=90
title_str=title_str+select_keyword(list_word_dousi)
if(n_depth<depth_max):
n_depth=n_depth+1
p=random.randint(1,100)
if(p<p_meisi):
gene_meisi()
elif(p<p_keiyou):
gene_keiyou()
else:
gene_bottom()
def gene_keidou():
global title_str
global n_depth
global depth_max
title_str=title_str+select_keyword(list_word_keidou)
gene_dousi()
def gene_bottom():
global title_str
global n_depth
global depth_max
p_keizoku = 50
p_top = 53
p_meisi = 70
title_str=title_str+select_keyword(list_word_bottom)
p=random.randint(1,100)
if(p<p_keizoku):
if(p<p_top):
gene_top()
elif(p<p_meisi):
gene_meisi()
else:
gene_keiyou()
def display_title():
make_title_start()
txt_title["text"]=title_str
print(title_str)
btn_create["command"]=display_title
def destroy_tk():
tk.destroy()
btn_quit["command"]=destroy_tk
tk.mainloop()
(コードここまで)
簡単に解説しておくと、まずword_list_top.txt、word_list_keiyou.txt、word_list_keiyou.txt、word_list_jyosi.txt、word_list_dousi.txt、word_list_keidou.txt、word_list_bottom.txt、というファイルに、キーワードを日本語の品詞ごとに分類して登録しておきます。コードの最初の方で、それを読み込み、タイトル自動生成に備えます。
そして、「自動生成」ボタンが押された時に実行される関数、display_title()の中で、さらに別の関数、make_title_start()をコールして、タイトルの自動生成をスタートしています。make_title_start()関数の最初に、いろいろ変数を初期化します。そして、 p_top、p_meisi、p_keidou、という3つの変数で、「最初にどんな種類のキーワードを選ぶか」の、確率を設定してあげています。「p_top=3」というのは、「文の先頭(top)に来ると自然なキーワードを、3%の確率で選びなさい」という設定です。p_meisi=50は、「名詞を47%の確率で選びなさい」、ということです。なぜ47%なのかというと、これはp_meisiの50から、p_topの3を引いた値なのです。
※あまり詳しく説明しても、難解なだけなのでこの辺で省略(汗。
上で説明したように、「top」は「文の先頭に来ると自然なキーワード」、「meisi」は「名詞」ですが、それ以外に、「keiyou」は形容詞、「jyosi」は助詞、「dousi」は動詞、「keidou」は形容動詞、「bottom」は、文の終わりに来ると自然なキーワード、というルールで、変数名をつけています。
どういう品詞が選ばれた時に、次にどういう品詞を選ぶのかは、それぞれの品詞に対応した関数の中で、新たに確率を設定して、乱数で選ばせます。それらの関数名は、gene_top()、gene_meisi()、gene_keiyou()、gene_jyosi()、gene_dousi()、gene_keidou()、gene_bottom()ですが、品詞の定義とか、確率と合わせてリストにすると、次のようになります。
タイトル作成開始 make_title_start()
次のように分岐。
文頭っぽいワード3%、名詞47%、形容動詞20%、形容詞30%、
文頭 gene_top()
まず文頭っぽいキーワードをタイトルに追加した上で、次のように分岐。
名詞30%、形容動詞70%、形容詞30%
gene_meisi() 名詞。
まず名詞をタイトルに追加した上で、次のように分岐。
文末っぽいワード1%、名詞2%、助詞87%、形容動詞10%
gene_keiyou() 形容詞。
まず形容詞をタイトルに追加した上で、次のように分岐。
名詞100%
gene_jyosi() 助詞。
まず助詞をタイトルに追加した上で、次のように分岐。
名詞30%、形容詞30%、動詞30%、形容動詞10%
gene_dousi() 動詞。
まず動詞をタイトルに追加した上で、次のように分岐。
名詞45%、形容詞45%、文末10%
gene_keidou() 形容動詞。
まず形容動詞をタイトルに追加した上で、次のように分岐。
動詞100%
gene_bottom() 文末。
まず文末っぽいキーワードをタイトルに追加した上で、次のように分岐。
50%の確率で、タイトル生成を終了。
文頭から作成し直す3%、名詞17%、形容詞30%
どうですか? 頭が痛くなってきましたね(ズキズキ。
まあ細かいことは置いておいて、結果をご覧いただきましょう。なお、使ったキーワードファイルは、第六話で作成したキーワードファイルの、約900個あるキーワードのうちの、218個を使ったものです(約25%程度)。なぜ全部やってないかというと、途中で疲れてしまったからですね(汗汗汗。
ということで、いつものように、10回ランダム生成させたものを、赤裸々に並べていきますね。
大胆にしたいヒロイン突然に届けなファッション雑誌な心
みだったらオーバー頂戴とでした
祝福の死んだトラン小さく届くどうでしょう?
漬けを日が感じのカルトを砕く
突然に行くあふれるスライムに中心に終りだったら錬金術師
埋葬抱きしめる恋の都市伝説だったらそっと叫べ戦士と走る
慎重怪だったらシュタインズ・ジャックがしたい
誰かからレースに抱きしめる
か弱いトップ小さく叫べなスタイル小さくしたあふれるニュートン小さく破ってヒール
異形で残酷のブルーな都市伝説を届くみたいな恋
うーん……。これは私個人の感想ですが、確かに日本語としての、文法的な品質は上がったものの、第七回までのコードが持っていたような、読む人の脳を破壊するような、破壊力はもっていないタイトルになってしまった感があります。
日本語として、おかしなタイトルだからこその、笑えるタイトルだったのでしょうか、うーん……(笑)。
という所で今回は終了とさせていただきます。次回は、第六回までに使用していた、約900のキーワードをすべて分類した上で自動生成させてみて、元の奇抜なタイトルが生成できるようになるのかを、お試しして公開させていただく予定です。どうなることやら(笑笑笑笑。
では次回またお会いしましょう。
おまけ:
※今回のタイトル自動生成に使ったファイルを、おまけに付けておきます。興味あるんだけど使い方わからないーっていう人は、コメントで質問するか、私(超プリン体)あてにこっそりメッセージをいただければ、時間の許す範囲でご説明しますので、ご遠慮なくご質問ください。
word_list_bottom.txt:
だった件
してももう遅い
ですか?
したい
ですし
じゃない?
いいですか?
したかった
どうでしょう?
でござる
ないですか?
あげてください
お楽しみください
だからね!
です
してる?
いいと思うよ?
した件
美味しいです
しないで
教えてね
のせて
つまらない
だいじょうぶ
伝えたい
抱きしめて
もう一度
止めて
忘れないで
負けない
浴びて
なれど
謝れ
なんて
していく
本気出す
一切ナシ
の妹
の書
word_list_dousi.txt:
歌う
戦う
走る
砕く
守って
あふれる
破って
震えて
輝いて
した
する
こうなる
なります
でした
して
いらない
記す
あがなう
問われる
焼かれる
焼かれた
叫ぶ
叫べ
叫んだ
された
した
走る
死んだ
したい
行く
届く
届け
包みこめ
抱きしめる
晒す
いない
word_list_jyosi.txt:
と
が
で
に
なので
を
の
だったら
と
から
word_list_keidou.txt:
大胆に
そっと
強く
のように
小さく
突然に
word_list_keiyou.txt:
負けない
オーバー
か弱い
慎重
映画のような
寄りそう
強く
あふれる
はみ出した
恋の
シュタインズ・
始まる
から始まる
かわいい
大人の
露骨な
みたいな
感じの
的な
ブルーな
な
word_list_meisi.txt:
ヒロイン
錬金術師
勇者
戦士
学校
スライム
ロード
ドラゴン
頂戴
ちょうだい
大嫌い
天国
地獄
エンジェル
今夜
心
シャワー
都会
ヒール
ファッション雑誌
恋
バニーちゃん
アンノ
ミコン
ニュートン
シュレディンガー
アインシュタイン
シェリー
ジャック
ストーン
アックス
トビー
トム
出会い
別れ
始まり
終り
日
オンライン
RPG
ダンジョン
っ子
日々
人生
早見表
シチュエーション
結果
場合
ファンタジー
物語
理由
妄想
家
祝福
すぎ
スタイル
どこか
ゲーム
プレイ
人生ゲーム
レース
大会
僕
私
あなた
あいつ
のんびり
瓶詰め
脳内
ランダム
死亡フラグ
砲
機械
漬け
刃
手違い
誰か
例
上
中心
お
み
トレス
トラン
絞り
トップ
ガン
瞬間
ホラー
奇怪
不死者
残酷
残虐
怪談
怪
異形
オカルト
アングラ
カルト
地下
都市伝説
石仏
儀式
埋葬
怪奇
殺戮
殺害
殺人
霊
word_list_top.txt:
とある
転生したら
ねえ、
ようこそ
怒らないでよ
もう一度
もし
生まれ変わったら
大きくなったら
ときどき
いろいろと
もしも
燃え尽きた