PerlとMXNetで文章生成: 英語の文字レベル学習と文章生成

[17/08/06 14:42 更新]

なんとか動くようになったchar_lstm.plを、「学習と保存」と「呼出と文章生成」の2つに分ける。

学習と保存 (char_lstm_train.pl)

まず、間に合わせのパッケージを使うので、どこかで読み込んでおく。


use Makeshift::MXNet::Module;

他と保存ファイル名がかぶらないようにGetOptionsの中で、デフォルトを適宜指定しておくとよい。


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

後半の$modelを作るところは、mx->mod->Moduleの代わりにMakeshift::MXNet::Module->newで。


my $model = Makeshift::MXNet::Module->new(

最終結果を保存するだけなら、$model->fitの中のbatch_end_callbackは要らない。

保存すべき情報は、デフォルトの他に、$seq_size$batch_size$fdata%vocabularyの4つのように見えるので、追加。


$model->add_info(seq_size => $seq_size, batch_size => $batch_size,
				 fdata => [$fdata->list], vocabulary => \%vocabulary);

[PDLをJSON化するのは面倒そうだったので、$fdataは、配列のリファレンスに変換している]

あとは、保存するだけ。


$model->save_current($prefix);

この時点で文章を生成させたければ、


sample();
print "\n";

で出来るが、動作確認が終れば、この部分も、sub sampleも要らない。 文章生成にのみ必要なsample-sizeなどのオプションもGetOptionsから消してよい。

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


Epoch[0] Train-Perplexity=7.248963
Epoch[0] Time cost=59.961
Epoch[1] Train-Perplexity=2.474827
Epoch[1] Time cost=64.465
Epoch[2] Train-Perplexity=1.649309
Epoch[2] Time cost=64.303
Update[1002]: Changed learning rate to 9.90000e-04
Epoch[3] Train-Perplexity=1.395134
Epoch[3] Time cost=64.086
Epoch[4] Train-Perplexity=1.290365
Epoch[4] Time cost=62.896
Epoch[5] Train-Perplexity=1.238024
Epoch[5] Time cost=61.078
Update[2002]: Changed learning rate to 9.80100e-04
Epoch[6] Train-Perplexity=1.203136
Epoch[6] Time cost=60.580
Epoch[7] Train-Perplexity=1.193806
Epoch[7] Time cost=62.304
Epoch[8] Train-Perplexity=1.180628
Epoch[8] Time cost=60.123
Epoch[9] Train-Perplexity=1.172655
Epoch[9] Time cost=60.844
Update[3002]: Changed learning rate to 9.70299e-04
Epoch[10] Train-Perplexity=1.162962
Epoch[10] Time cost=60.458
Epoch[11] Train-Perplexity=1.160919
Epoch[11] Time cost=60.829
Epoch[12] Train-Perplexity=1.156535
Epoch[12] Time cost=60.995
Update[4002]: Changed learning rate to 9.60596e-04
Epoch[13] Train-Perplexity=1.149714
Epoch[13] Time cost=60.510
Epoch[14] Train-Perplexity=1.146489
Epoch[14] Time cost=58.861
Epoch[15] Train-Perplexity=1.150732
Epoch[15] Time cost=59.526
Update[5002]: Changed learning rate to 9.50990e-04
Epoch[16] Train-Perplexity=1.147942
Epoch[16] Time cost=59.534
Epoch[17] Train-Perplexity=1.147097
Epoch[17] Time cost=60.930
Epoch[18] Train-Perplexity=1.144301
Epoch[18] Time cost=59.259
Epoch[19] Train-Perplexity=1.141809
Epoch[19] Time cost=58.906
Update[6002]: Changed learning rate to 9.41480e-04
Epoch[20] Train-Perplexity=1.138199
Epoch[20] Time cost=59.861
Epoch[21] Train-Perplexity=1.139673
Epoch[21] Time cost=59.157
Epoch[22] Train-Perplexity=1.136089
Epoch[22] Time cost=58.821
Update[7002]: Changed learning rate to 9.32065e-04
Epoch[23] Train-Perplexity=1.138953
Epoch[23] Time cost=59.350
Epoch[24] Train-Perplexity=1.135490
Epoch[24] Time cost=59.446
Saved checkpoint to "lstm-0025.params"

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

これも、char_lstm.plを改造。

まず、間に合わせのパッケージを使うので、どこかで読み込んでおく。


use Makeshift::MXNet::Module;

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


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

sample-size以外のオプションは要らないので、ばっさり削る。

そのあとは、package main;までをばっさり削る。

あとは、呼び出して、必要な情報を取り出す。


my $model = Makeshift::MXNet::Module->load_current($prefix);
my $seq_size = $model->info->{seq_size};
my $batch_size = $model->info->{batch_size};
my $fdata = pdl($model->info->{fdata});
my %vocabulary = %{$model->info->{vocabulary}};
my %reverse_vocab = reverse %vocabulary;

最後は、文章生成して終り。


sample();
print "\n";

実行結果はこんな感じ。




All:
Speak, speak.

First Citizen:
You are all resolved rather to die than to famish?

All:
Resolved.
And cell him noble that was now your hate,
Him vile that was your garland. What's the matter,
Th

そこそこ英語っぽく見える。

[次の「英語の単語レベル学習と文章生成」へ] [「間に合わせのパッケージ」に戻る] [「PerlとMXNetで文章生成」に戻る] [「あえてのPerl」に戻る]