ぬゅぼうのPython日記【指定された単語を含む文章を生成するコードが書きたいよ~!!!】
タイトルが長い!!!!!!
さて今回はやたら長い上にひねりもなくただただ読みにくいタイトルの通り、
指定された単語を含む文章を生成するコード
を書きマ~~~~~~~~~~~ウ!!!!!!!!(なげやり)
…と、本題に入る前に近況を。
このぬゅぼうのPython日記、
三日坊主な僕には珍しくもう20日も続いております。
(連続ではありません。そこまで筆まめではないもので。)
元々自分用の備忘録くらいのノリで始めた日記ですが、
嬉しいことに毎回1~2のスキを安定していただいておりまして。
こないだなんかは面白いとお褒めのコメントを初めていただいた
なんてこともあり、非常にモチベーションになっております。
成長のためにもアウトプットが大事とは良く言ったもので、
noteを初めて以来、
自分史上過去に類を見ないペースでコードが書けておりまして。
これからも末永く続けていけたらな~~と思っておりマウ。
さて、表題の件です。
僕の中での目標が『人工知能型チャットボット』の作成ということで、
そのためには任意の文章を出力する機能が必要なわけで。
ただ現状のデータ構造では、
まだ出力される文章に意味を持たせることは難しいので…
とりあえず指定した単語を含む自然な文章を生成するコードということで妥協。
それではさっそく作業していきましょうね。
def sentence_analysis(*word):
とりあえず関数名はsentence_analysisとしております。
文章生成とは言いましたが、大半は文法データを分析して
そのパターンを数値化する処理になるのでこの名前に。
ちなみにこの引数、*を付けて可変長引数にしております。
想定は複数のstr型の単語です。
sentence_data=ast.literal_eval(func.txtfile('sentence_data.txt'))
続いて以前学習させた文法パターンのファイルを読み込みます。
詳しくは↑こちら↑の記事から。
return_dict={}
word_list=[]
正直ここはとりあえず作ったオブジェクトです。
ぶっちゃけまだ着地点探り探りで書いてるので使わない可能性もある…
for word_i in word:
可変長引数として受け取った引数wordはtuple型として処理されているので
forループで回すことができます。とってもイテラブル(謎)
word_i=func.janome(word_i)
word_list.append(word_i)
wordの中身をjanomeにかけます。
後々使うかもしれないのでword_listに保存しておきます。
for word_ii in word_i:
cate=word_ii[1:7]
さっきのjanomeにかけたものをまたループに渡し、
単語カテゴリを切り出します。
cate_dict={'front':[],'behind':[]}
for sen_i in [sen for sen in sentence_data if cate in sen]:
ここからが今回のキモです。
list内包表記で上記の単語カテゴリを含む文章をsentence_dataから抽出し、
その文章を一つづつ変数sen_iとしてループさせます。
この後の処理でその前後関係をdict化していく感じですね。
sen_i=[('文頭',)]+list(sen_i)+[('文末',)]
ind=sen_i.index(cate)
説明が難しいのですが、
『この単語は文章の先頭に来がち』
『この単語は文章の末尾に来がち』
などの傾向を掴むために、
文頭と文末をわかりやすくしといたほうが都合が良いんですよ。
ということで、文法パターンsen_iにその2つを追加します。
形式はlistの項目と同じくtupleに。
そして先程切り出したcateがsen_iのどこにあるか、indexを取得します。
cate_dict.get('front').append(sen_i[ind-1])
cate_dict.get('behind').append(sen_i[ind+1])
cate_dictのfrontに一つ前の単語、
behindに一つ後の単語を入れます。
ここ、似たような処理なので1行にまとめてもいいかなと思ったんですが
かえってめんどくさいことになりそうだったのであえて2行で書いてます。
for k,v in cate_dict.items():
v_dict={v_i:v.count(v_i)*100/len(v) for v_i in set(v)}
cate_dict[k]=v_dict
完成したcate_dictをまたもやループで回します。
参考までに、ここでのvの中身を載せておきますね。
[('文頭',), ('文頭',), ('文頭',), ('助詞', '接続助詞', '*', '*', '*', '*'), ('助詞', '係助詞', '*', '*', '*', '*'), ('助詞', '係助詞', '*', '*', '*', '*'), ('文頭',), ('助詞', '連体化', '*', '*', '*', '*'), ('助詞', '格助詞', '一般', '*', '*', '*'), ('助詞', '連体化', '*', '*', '*', '*'), ('文頭',), ('文頭',), ('接頭詞', '名詞接続', '*', '*', '*', '*'), ('助詞', '連体化', '*', '*', '*', '*'), ('接頭詞', '名詞接続', '*', '*', '*', '*'), ('文頭',), ('文頭',), ('接続詞', '*', '*', '*', '*', '*'), ('文頭',), ('文頭',), ('助動詞', '*', '*', '*', '特殊・タ', '基本形'), ('文頭',), ('文頭',), ('文頭',), ('動詞', '自立', '*', '*', '一段', '連用形'), ('文頭',), ('文頭',), ('助詞', '連体化', '*', '*', '*', '*'), ('動詞', '非自立', '*', '*', '五段・ワ行促音便', '命令e'), ('助動詞', '*', '*', '*', '不変化型', '基本形'), ('助動詞', '*', '*', '*', '不変化型', '基本形'), ('助詞', '係助詞', '*', '*', '*', '*')]
例として、('名詞', '一般', '*', '*', '*', '*')というカテゴリに属する単語の
front(一つ前の単語のカテゴリ)です。
わかりやすい特徴としてはやはり('文頭',)が多いですね。
「蟹は美味しい」とか、
「キノコがうまい」のように
名詞を文の先頭に置いて始めるパターンが多いからです。
このままだと計算できないので、どんなカテゴリが多いのか
次の処理で数値化します。
v_dict={v_i:v.count(v_i)*100/len(v) for v_i in set(v)}
cate_dict[k]=v_dict
上記のようなvの中身をdict内包表記で処理します。
やってることは単純にパーセント化してるだけなので割愛。
長ぁぁ……
もうややグロッキーですが、ここまでの処理で得られたcate_dictを貼ります~
入力≫「魚」
出力≫
{'front': {('助詞', '格助詞', '一般', '*', '*', '*'): 3.125, ('助詞', '連体化', '*', '*', '*', '*'): 12.5, ('接頭詞', '名詞接続', '*', '*', '*', '*'): 6.25, ('助動詞', '*', '*', '*', '不変化型', '基本形'): 6.25, ('助詞', '接続助詞', '*', '*', '*', '*'): 3.125, ('助動詞', '*', '*', '*', '特殊・タ', '基本形'): 3.125, ('助詞', '係助詞', '*', '*', '*', '*'): 9.375, ('文頭',): 46.875, ('接続詞', '*', '*', '*', '*', '*'): 3.125, ('動詞', '自立', '*', '*', '一段', '連用形'): 3.125, ('動詞', '非自立', '*', '*', '五段・ワ行促音便', '命令e'): 3.125}, 'behind': {('助詞', '格助詞', '一般', '*', '*', '*'): 46.875, ('名詞', '接尾', '一般', '*', '*', '*'): 3.125, ('文末',): 9.375, ('助詞', '係助詞', '*', '*', '*', '*'): 28.125, ('助動詞', '*', '*', '*', '特殊・ダ', '連用形'): 3.125, ('動詞', '自立', '*', '*', '一段', '基本形'): 3.125, ('動詞', '自立', '*', '*', '五段・ワ行促音便', '仮定形'): 3.125, ('助詞', '終助詞', '*', '*', '*', '*'): 3.125}}
パッと見分かりにくいですが、frontでは『文頭』つまり文章の一番最初に
『魚』のような一般名詞の単語が配置される割合が46.875%で最も高く、
behind(その単語の後ろにどんな単語が来るか)では
格助詞(が、の、を など)が同じ割合で最も多い結果に。
割合が同じになるのは学習させた文章のパターンにさほど幅がなかったか、
そもそもデータ量が足りてないのどちらかだと思われるので、
今後データを追加していけばより精度の高い数値が出るはずです。
そのためにはデータ構造も考えていかなければ…(伏線)
ともあれ、体感的にも正しそうなデータが出ました。(適当)
長くなっちゃったんで今回はここまで!
次回はこのデータを利用して文章を生成する処理に入っていきます!!
うわぁぁ
脅威の4000字超え!!!!!寝ろ!!!!
それでは!!!!
この記事が気に入ったらサポートをしてみませんか?