機械学習を使って作文を生成してみた

学校の自由課題で「税の作文」が出ているのですが、これを機械学習で生成したら面白いのではないかと思ったのでやってみました。

まず初めにマルコフ連鎖という手法を使ったのですが、この手法はあまり精度がよくなく、文章中に出てくる単語が学習元のデータと同じになってしまうことがあるので著作権などの問題があります。

そこで、今回は「危険すぎる」と話題になったGPT2を使ってやっていきます。

試しに使ってみる

まず下のコマンドでGPT2をインストールします。

git clone https://github.com/tanreinama/gpt2-japanese
cd gpt2-japanese
pip install -r requirements.txt

次に下のコマンドでsmallモデルをダウンロードして解凍します。

wget https://www.nama.ne.jp/models/gpt2ja-small.tar.bz2
tar xvfj gpt2ja-small.tar.bz2

これで文章を生成するための環境は完成しました。 下のコマンドで文章の生成を実行します。

python gpt2-generate.py --model gpt2ja-small --num_generate 1

パラメータは下の通りです。

  • --model:モデル(デフォルト gpt2ja-medium)

  • --num_generate:生成するテキスト数(デフォルト 5)

  • --context:開始する文章(デフォルト <|endoftext|>)

  • --top_k:各ステップでk個の単語からランダム選択(デフォルト 40)

  • --top_p:生成テキストを累積確立に制限(デフォルト 0、制限なし)

  • --temperature : 温度(デフォルト1、推奨0.7〜1.0)

  • --min_length:文章の最小の長さ(デフォルト 0、最大 1024)

  • --max_length:文章の最大の長さ(デフォルト 500)

結果は下のようになりました。

ただ、ここまで書いてきた時点で、その可能性はゼロに等しいと思うのですが・・。

「私、この小説で、お前らに付けられた賞は、何だろう…と、私たちを見て思った」とか「誰だって、お前らの作品があの世で、あるいは、私たちの作品でもない限りは、こんなことなんだろう…と思っている」とか「私たちは、こうすることができる」ということになるのは、普通は考えにくいものですので。

ただ、やはり…

「私たち」ならば、その「あり方」が一番あり得たものです。

「あり方」が、「あり方」が、「あり方」が。

それらが、何らかの理由で、「あり方」の「あり方」が「私たち」にとって「あるべきもの」であってこそ、「無かったことができる」という現象になるかもしれません。

「あり方」の「あり方」は、「あり方」が「あり方」から見た見た、世界観です。

それを前提にしているのであれば、「無かったことができる」という過程も一緒です。

もし、「あり方」が「あり方」との「あり方」を否定する場合であれば、「これはまずい」「これは、「何も見えません」「あることを見えません」となる恐れがあるので、否定することもできるでしょう。

しかし、この

結構支離滅裂な文章ですね

学習させる

データセットの準備

今回は税の作文のホームページからpdfをダウンロードして使いました。

DownThemAll!などを使ってpdfを全部ダウンロードします。

pdfの結合サービスなどを使ってpdfを結合しpdfをtxtに変換するサービスを使ってtxt形式に変換します。

VScodeなどを使って正規表現を使うなどしてタイトルなどいらない部分を消します。

(例).*?\n.*\n.*\n

pdfをtxtに変換したままの形では文章の切れ目にかかわらず改行が入ってしまっているので改行をすべてなくします。

そして、「。」の後に改行コードを入れて改行させます。 これで文章ごとに改行を行うことができます。

学習のために会話の切れ目には<|endoftext|>を入れなければいけないので改行の前に<|endoftext|>を付け足します。

この先の工程が僕のPC上の環境ではうまくいかなかったのでgoogle colab上で行いました。

google colab上に下のコマンドを使って同じ環境を作ります。

!git clone https://github.com/tanreinama/gpt2-japanese
%cd gpt2-japanese
!pip install -r requirements.txt
!wget https://www.nama.ne.jp/models/gpt2ja-small.tar.bz2
!tar xvfj gpt2ja-small.tar.bz2

先ほど作成したファイルのファイル名を「dataset.txt」にして、google colab上の「gpt2-japanese」フォルダ直下に「data」などの適当な名前のフォルダを作り、その下に配置します。

そして下のコマンドで変換用のプログラムをダウンロードし、「finetune.npz」に変換します。

!git clone https://github.com/tanreinama/Japanese-BPEEncoder.git
!python ./Japanese-BPEEncoder/encode_bpe.py --src_dir data --dst_file finetune

そして、出来上がった「finetune.npz」をダウンロードしてPC上の「gpt2-japanese」にコピーします。

これでデータセットは完成です。

ファインチューニング

ファインチューニングは「run_finetune.py」を使います。

「Ctrl + C」で学習を終了するのですが、うまく終了できないので、プログラムでエポック数を指定します。 「run_finetune.py」を開いて217行目あたりにしたのような記述があります。

       try:
            #while True:
            for i in range(500):
                if counter % args.save_every == 0:
                    save()

                (_, v_loss, v_summary) = sess.run(
                    (opt_apply, loss, summaries),
                    feed_dict=sample_feature())
 
                summary_log.add_summary(v_summary, counter)

                avg_loss = (avg_loss[0] * 0.99 + v_loss,
                            avg_loss[1] * 0.99 + 1.0)

上のように「while True」を「for」文に変更します。for文でエポック数を指定します。(コードでは500)

下のコマンドを実行してファインチューニングを行います。

python run_finetune.py --base_model gpt2ja-small --dataset finetune.npz --run_name gpr2ja-finetune_run1-small --save_every 100

パラメータは以下の通りです。

  • --dataset : データセット(npzファイル)

  • --base_model : モデルファイルのパス (デフォルト: gpt2ja-small)

  • --batch_size : バッチサイズ (デフォルト: 1)

  • --optim : オプティマイザ (adam, adagrad, sgd) (デフォルト: adam)

  • --learning_rate : オプティマイザーの学習率 (デフォルト: 5)

  • --warmup_steps : 学習率のウォーミングアップステップ (デフォルト: 0)

  • --run_name : 実行ID。 checkpoint/とsamples/のサブフォルダ名 (デフォルト: gpt2ja_finetune)

  • --save_every : Nステップ毎にチェックポイントを書き込むか (デフォルト: 1000)

  • --gpu : GPU番号 (デフォルト: '0')

これでモデルは完成しました。

動作確認

下のコマンドで動作確認ができます。

python gpt2-generate.py --model checkpoint/gpr2ja-finetune_run1-small --num_generate 1

実行結果は下のようになりました。

これらの要素の中で、「僕は税金によって成り立っている税金使い方に取り組みたい」と思った人は多いはずである。

「--context」などを使って開始の文章を「税金は」などに指定して、応募要項を見ると原稿用紙3枚以内と書いてあるので「--min_length」を1000くらい、「--max_length」を1200にして実行してみます。

python gpt2-generate.py --model checkpoint/gpr2ja-finetune_run1-small --num_generate 1 --context "税金は" --min_length 1000 --max_length 1200

これで実行すると下のようになりました。

税金は制度の都合で不可能になったものであることがわかった。

そして、政府は税金の使い途を定めるためのワイヤを整書し、国の借金を軽減するための政策をとった。

国債発行や現金払いの他にも巨額の徴収があったが、これら税金は国債の発行と同時に民事・地方公共団体の犯罪の防止や犯罪の防止のための仕組みである。

また、行政や社会の仕組みは憲法で定められているが、全て税金を国債に替えさせるためのものである。

いずれの税金も、それぞれの地域や地域の公共サービスに還元され、国民の不満度を高めた。

また、最近ではコロナウイルス感染症の流行や感染拡大による国民の緊張などにより、税金の導入は難しくなったが、国家や地方公共団体の年目滑りとしての使命を果たすだけの働きはした。

一方、税金の使途の確定から支払いまでが主な仕事であり、国民の安全・安心と豊かで幸せな暮らしを保障するために行われている。

また、令和二年度の一般会計予算は十九兆十九すう事業所である。

東京などの大都市に出ており、初めての対面式の税金会議は嬉しくもあり、とても荘厳な運営であった。

令和二年度のこみめらしい税の歳出規模の拡大には、政府は税金の使途の明確化を必要とし、国民の負担を軽減している。

一方、医療、年金、公共サービス等の保障に関わる税は府県や市などの公共サービスを円滑に使わせるために困難な時期を経て建設されている。

また、ごみを収集し回収する等の収集事業は、国に補助を得て維持している。

今後の税の未来は、今後も大きな問題が出てくるのではないだろうか。私は思う。

私の不平不満はつらいが、自分に足りないものだ。

不景気な世の中になり、税金を払うことに対する消極的な自分がいることに気づかされた。

しかし、世の中に目を向けた今、税金の使途に最初から興味がまったくなった。

私は、世の中に関心がなかったがために、税金の使途に興味をもったのではないかと思う。

たとえば、私が払っている給料から税金を支払い、うまくいった食いつき方で世の中に貢献するといった作業が、日々の生活で直接納め、あとで支払う消費税などには関心がない。

しかし、税金は世の中にどのような姿を現しているだろうか。

私は、今まで税金には目もくれず、ぼんやりと見ていたことがあり、興味関心が持てた。

税という形は、日常生活に密着していなくてはならないものであり、その作り方についても日々試行錯誤している。

また、税金は税金の見え方が大きく異なり、ごみを収集することなくちんすこくをまかなえる。

また、ごみを処理する現場を見たことがない人から学ぶことのできるアイディアもいくつか見つかる。

これらは、私が思い描いていたものと大きく変わらない。

なぜなら、税金をしっかり世の中に役立てているからだ。

私の経験した税金とは別に、たくさんの問題が私の中で渦となっている。

まとめ

学習したデータが少なかったせいかあまり高い精度で生成することができませんでした。

これでは学校の先生にバレてしまうので素直に自分で書きましょう。

しかし、この技術を使ってパラメータや学習データを増やすともっと精密な文章を生成することも可能です。

簡単に高い精度の文章を大量に作ることが出来るので、悪用はしないようにしましょう。

リンク集

GitHub - tanreinama/gpt2-japanese: Japanese GPT2 Generation Model

令和2年度 中学生の「税についての作文」各大臣賞・国税庁長官賞受賞者発表 | 税の学習コーナー|国税庁

DownThemAll! - Chrome ウェブストア

【無料】PDFを結合 - Adobe 公式 | Adobe Acrobat(日本)

PDF TXT 変換。オンライン フリー — Convertio