動機

NLPのタスクの中で、文章分類タスクがある。多くのチュートリアルでは文章分類タスクとして、livedoorのコーパスを使って学習させているようだ。できたら、テキストから動物の病気を分類したい。けど、学習させるためのテキストデータがない。そいえば、テキスト自体を生成できるモデルがあったような。。テキストをNLPのモデルで作成して、他のNLPのモデルで学習させてみるか。そいうえば、日本語テキスト作成のモデルが公開されたと最近ニュースで見たような。

rinna

rinna株式会社がテキスト生成ができるGPT2のモデルを公開したとニュースになっていた。日本語テキスト(70GB)を学習しており、その学習期間、なんと1カ月だそうだ。とにかく凄そうだ。研究成果を公開してくれて感謝しかない。

hugging faceには、japanese-gpt2-mediumというモデルの名前で登録されている。

https://huggingface.co/rinna/japanese-gpt2-medium

Licenese:The MIT license

コード

このサイトを参考にさせてもらった。

https://note.com/npaka/n/n96dde45fdf8d

Google colabでの実行を想定。まず、学習済みモデルの読み込みを行う。以下のコードでエラーが出る場合には、ランタイムの再起動を行うとエラーが消える。

!pip install -q transformers
!pip install -q sentencepiece

from transformers import T5Tokenizer, AutoModelForCausalLM
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium")
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-medium")

文章を作成させてみる。

犬と一緒に公園に行った。の後の文章を、最大長さ50(max_length)、文章10個(num_return_sequences)を生成させてみる。

input = tokenizer.encode("犬と一緒に公園に行った。", return_tensors="pt")
output = model.generate(input,
                        do_sample=True,
                        max_length=50,
                        num_return_sequences=10)
print(tokenizer.batch_decode(output))
['犬と一緒に公園に行った。</s> 犬の吠え声のおかげで少し涼しくなった。 このあたり、いつものんびり散歩するよりもずっと短い距離だと気づいた。 散歩して、ふらふらと散歩しよう、ということになった。', 
'犬と一緒に公園に行った。</s> 公園に 動物達が沢山いたので 遊びに行った。 公園で見かけた動物の写真を 撮ってみた。 動物達は とても綺麗だった。 写真を撮ってない動物も多く', 
'犬と一緒に公園に行った。</s> 1歳2歳のおともだちのお兄ちゃんが遊びに来ていて一緒に遊んだ。 犬はおともだちだとは思っていたけど、なんか違うんだろうな、うちの子。', 
'犬と一緒に公園に行った。</s> 公園の駐車場から歩いていくと、ふと周りの景色が見えた。 この公園にはたくさんの桜(おそらく満開)が植えられており、花見もできる。 しばらく見とれていたが', 
'犬と一緒に公園に行った。</s> 今日は天気が良いので、ドッグラン に行った。散歩をしていて、突然知らない犬が吠えだした。 犬が吠えた時は、すぐに止めなければいけなかった。 ドッグランに行', 
'犬と一緒に公園に行った。</s> 犬と一緒にいる人がすんごく多くて、犬は皆で仲良く遊ぶのが大好きなんだなーと思った。 でも、それは犬と私がそういう環境じゃないからそう思うんだろうな。', 
'犬と一緒に公園に行った。</s> 犬と一緒に公園に行った。 犬の散歩の時間はもう夕方の5時になってしまった。 犬と一緒に公園に行った。 犬と一緒に公園に行った。 犬と一緒に公園に行った。 犬は、かなり興奮している',
 '犬と一緒に公園に行った。</s> 犬は私の後をついて来るようだけど、私は犬に吠えることができない。 公園ではたくさんの犬がいた。 私は公園の入り口で手を振って、一緒に入った。 私は犬に吠', 
'犬と一緒に公園に行った。</s> 私と犬はボールで遊ばなかったから、犬を連れて行ったら すごい怒られたんだよ。 犬と遊んで楽しいかったけど、犬が散歩に行けたのは2回くらいだ', 
'犬と一緒に公園に行った。</s> 犬たちの吠え声がだんだん近づいて来て、うちの子たちはその音に すごく落ち込んだ。 怖かったし、悲しかった。 自分の子を思うと涙が止まらなくなった。']

すごい。。。。

学習用データの生成

飼い主からチャットで、犬猫の相談がきたときに、犬猫の病気が緊急性があるのか、緊急性がないのか、そこを判断できる機械学習モデルを作りたいと思う。NLPモデルに学習させるため、緊急性のある文章と緊急性のない文章のデータを作成したい。

緊急性のあるテキスト

犬が緊急事態 という文書の後を3文作成してもらう。

input = tokenizer.encode("犬が緊急事態。", return_tensors="pt")
output = model.generate(input, do_sample=True, max_length=50, num_return_sequences=3)
print(tokenizer.batch_decode(output))
['犬が緊急事態。</s> pic.twitter.com/6wdvsbt4zw 犬には緊急事態かもしれんけど、ペットショップにいる犬にも緊急事態は起こる可能性あるから、そういう時に冷静に対処できる',
 '犬が緊急事態。</s> 私「えっとですね、これは私の友達の犬じゃない?もしこの子達が我が家にやって来たならば?皆で一緒に遊んではどうかってお話が出てるんですけどね」 私「',
'犬が緊急事態。</s> _ トップページ _ 犬のしつけを今すぐやらなければならない理由 犬がトイレをしなくなった。 突然、犬がトイレで失敗して、排泄をしなくなった場合、']

3番目の文は、犬が排泄しなくなったら大変だ。ショック状態かもしれない。この調子で作文してもらえば、本当に緊急事態のテキストデータができてしまう。

今度は緊急事態ではないテキストデータを作成してみたいと思う。

緊急性のないテキスト

犬がリラックスしている。 という文書の後を3文作成してもらう。

input2 = tokenizer.encode("犬がリラックスしている。", return_tensors="pt")
output2 = model.generate(input2, do_sample=True, max_length=50, num_return_sequences=3)
print(tokenizer.batch_decode(output2))
['犬がリラックスしている。</s> 猫がリラックスしている。その違いはいったい何なのでしょうか? 犬と猫は同じ空間で過ごしています。なのでその感覚は一緒ではないでしょうか? 猫の行動原理は大きく分けて',
 '犬がリラックスしている。</s> でも、 犬は自分のことを分かっていない。 犬が私たちに教えてくれるのは 自分にとって大切な時間 犬はとても幸せな時間、そして私にとって大きな支えになっています。 今週の土曜日',
 '犬がリラックスしている。</s> 犬はストレスを感じていない。あなたのお家の犬はいつも どこかの世界で元気にしていますか? 私たちの愛犬に癒されていますか? 犬を飼おうかなと考えている方、どんな']

どれも緊急性なさそう。3番目なんかは、同居犬が1匹なくなって、もう一匹がストレスを感じて食欲がなくなり、もう一匹飼ってあげたほうがいいですかね?という質問につながりそう。

緊急性あり・緊急性なし、それぞれ100個づつ文を生成して、緊急性ありはラベル1、緊急性なしはラベル0として、データフレームに格納しておく。

また、書き出しの文は毎回同じになってしまうのだが(犬が緊急事態。犬がリラックスしている。)、幸い区切り</s>がついている。</s>を使って文章を分けて、後ろ側だけを保存していく。

このデータはのちに、NLPの文章分類問題の学習データとして使ってみる。(それぞれクラス内データが100だときっと少ないけど、とにかくやってみる。)

→やっぱり100じゃダメだった。1000にした。

import pandas as pd
log = pd.DataFrame(0, columns=['label','sentence'], index=range(200))
for i in range(200):
  if i < 100:
    log.iloc[i,0] = 1
    log.iloc[i,1] = tokenizer.batch_decode(output)[i].split('</s>')[1]
  else:
    log.iloc[i,0] = 0
    log.iloc[i,1] = tokenizer.batch_decode(output2)[i-100].split('</s>')[1]
log.to_csv("created_sentences.csv",index=False)

すごい技術!!しかし、実際に自分の手でこれを動かしてみると、ヤバさも感じた。

Categories:

category