PerlとMXNetで文章生成: 日本語の単語レベル学習と文章生成

[17/08/07 00:38 更新]

今作ったchar_lstm_train_jp.plchar_lstm_gen_jp.plを、文字レベルの学習から単語レベルの学習に変更する。そのために、Text::MeCabを使うので、インストールのページを参考に、インストールしておくこと。

学習と保存 (word_lstm_jp_train.pl)

char_lstm_jp_train.plword_lstm_jp_train.plにコピーしておく。GetOptionsの中のprefixのデフォルトを変更。


    'prefix=s'       => \(my $prefix  = 'word_lstm_jp' ),

後半のpackage main;が始まるまでは変更なし。Text::MeCabを読み込む。


use Text::MeCab;

データを読み込んだあとに、ちょっとした工夫をしている。改行を単語のひとつに数えるために、別の文字列に変換している。後で戻すことを忘れないこと。


$fdata =~ s/\n/ :: /g;

そのあとは、mecabを利用して単語に分けて%vocabulary$fdataを作る。


my @wds = ();
my $mc = Text::MeCab->new();
my $nx = $mc->parse($fdata);
while ($nx) {
	my $wd = decode_utf8($nx->surface);
	push @wds, $wd if $wd;
	$nx = $nx->next;
}
my %vocabulary; my $i = 0;
$fdata = pdl(map{ exists $vocabulary{$_} ? $vocabulary{$_} : ($vocabulary{$_} = $i++) } @wds);

変更点はこれだけ。

Epoch数25で実行してみると、こんな感じ。


Epoch[0] Train-Perplexity=76.289168
Epoch[0] Time cost=11.779
Epoch[1] Train-Perplexity=9.079578
Epoch[1] Time cost=11.905
Epoch[2] Train-Perplexity=2.950353
Epoch[2] Time cost=11.736
Epoch[3] Train-Perplexity=1.856245
Epoch[3] Time cost=11.962
Epoch[4] Train-Perplexity=1.535606
Epoch[4] Time cost=12.036
Epoch[5] Train-Perplexity=1.396455
Epoch[5] Time cost=12.439
Epoch[6] Train-Perplexity=1.318441
Epoch[6] Time cost=12.289
Epoch[7] Train-Perplexity=1.268591
Epoch[7] Time cost=12.545
Epoch[8] Train-Perplexity=1.233796
Epoch[8] Time cost=12.583
Epoch[9] Train-Perplexity=1.207820
Epoch[9] Time cost=12.458
Epoch[10] Train-Perplexity=1.187615
Epoch[10] Time cost=12.449
Epoch[11] Train-Perplexity=1.171490
Epoch[11] Time cost=13.016
Epoch[12] Train-Perplexity=1.158333
Epoch[12] Time cost=13.069
Epoch[13] Train-Perplexity=1.147435
Epoch[13] Time cost=13.049
Epoch[14] Train-Perplexity=1.138458
Epoch[14] Time cost=12.956
Epoch[15] Train-Perplexity=1.131047
Epoch[15] Time cost=13.190
Update[1002]: Changed learning rate to 9.90000e-04
Epoch[16] Train-Perplexity=1.124606
Epoch[16] Time cost=13.073
Epoch[17] Train-Perplexity=1.118849
Epoch[17] Time cost=13.466
Epoch[18] Train-Perplexity=1.113460
Epoch[18] Time cost=12.984
Epoch[19] Train-Perplexity=1.108719
Epoch[19] Time cost=14.556
Epoch[20] Train-Perplexity=1.104825
Epoch[20] Time cost=13.404
Epoch[21] Train-Perplexity=1.101403
Epoch[21] Time cost=13.549
Epoch[22] Train-Perplexity=1.097612
Epoch[22] Time cost=13.182
Epoch[23] Train-Perplexity=1.094173
Epoch[23] Time cost=13.348
Epoch[24] Train-Perplexity=1.090882
Epoch[24] Time cost=13.315
Saved checkpoint to "word_lstm_jp-0025.params"

呼出と文章生成 (word_lstm_jp_gen.pl)

char_lstm_jp_gen.plを改造。

まず、GetOptionsの中で、prefixのデフォルトをword_lstm_jp_train.plに合わせておく。


    'prefix=s'       => \(my $prefix  = 'word_lstm_jp' ),

sub sampleの出力部分は、一旦変数に収めて、改行文字の変換を元に戻して、表示。


		my $nxt = $reverse_vocab{$next_char};
		$nxt =~ s/::/\n/;
        print encode_utf8($nxt);

実行結果はこんな感じ。


思ったときが、一番間違いやすい。
 うまくいかないと思ったときは、既に間違っている」
%%
「マーフィの法則を熟知したるものは、マーフィの法則に縛られる」
%%
「議論がすれ違ったときには、まず、言葉の定義が共通であるかどうか確かめよ」
KGKによる議論の第一法則
%%
「感情的な発言は、議論を後退させる事はあっても、議論を進ませる事はない」
KGKによる議論の第二法則
%%
「問題を解決するためには、その問題に対して何等かの判断を下さなければならない。そして、正しい判断は、正しい情報と正しい分析の上に初めてなり立つ」
KGKによる知的問題解決の一般法則その1
%%
「同じ結果を生むのなら、楽な解決法を選ぶべきである。
 同じ労力なら、美しい解決法を選ぶべきである」
KGKに

……、文章生成というより、文章再生? 入力データが小さすぎるか?

おまけ

単語に分けるだけより、品詞を反映した方がいいんじゃないかと思って、「[品詞]単語」で学習させてみたのだが、考えてみれば、あまり意味がなかった。この方法が意味を持つには、同じ単語が別の品詞に分類されることが多くなければならない。

まあ、作ってみたんで、lc_word_lstm_jp_train.pllc_word_lstm_jp_gen.plの名で置いている。

[「日本語の文字レベル学習と文章生成」に戻る] [「PerlとMXNetで文章生成」に戻る] [「あえてのPerl」に戻る]