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

[17/08/06 23:38 更新]

次に、今作ったchar_lstm_train.plchar_lstm_gen.plを、文字レベルの学習から単語レベルの学習に変更する。

学習と保存 (word_lstm_train.pl)

char_lstm_train.plword_lstm_train.plにコピーしておく。次に、GetOptionsの中のprefixのデフォルトを適宜指定しておくとよい。


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

後半のpackage main;が始まるまでは変更なし。データを読み込んだあとの、


$fdata = pdl(map{ exists $vocabulary{$_} ? $vocabulary{$_} : ($vocabulary{$_} = $i++) } split(//, $fdata));

で何をしてるかというと、データを1文字づつ切りだして、文字に番号を振るとともに、$fdataを番号の列にしている。これを単語レベルにするには、


$fdata = pdl(map{ exists $vocabulary{$_} ? $vocabulary{$_} : ($vocabulary{$_} = $i++) } split(/(\s+)/, $fdata));

とすればよい。splitの中身が変わっただけである。切り出し条件に括弧をつけておくのがミソ。そうすれば、空白や改行も1つの単語として扱ってくれる。まあ、「people.」と「people」が区別されるとか、単語の区切りで空白が入る保証がないとか、いろいろ不都合はあるが、とにかくやってみる。

変更点はこれだけ!!

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


Epoch[0] Train-Perplexity=35.112393
Epoch[0] Time cost=25.970
Epoch[1] Train-Perplexity=17.254632
Epoch[1] Time cost=26.752
Epoch[2] Train-Perplexity=9.023592
Epoch[2] Time cost=28.247
Epoch[3] Train-Perplexity=3.670179
Epoch[3] Time cost=28.284
Epoch[4] Train-Perplexity=1.833269
Epoch[4] Time cost=28.729
Epoch[5] Train-Perplexity=1.538267
Epoch[5] Time cost=28.528
Epoch[6] Train-Perplexity=1.349279
Epoch[6] Time cost=29.093
Epoch[7] Train-Perplexity=1.260853
Epoch[7] Time cost=29.003
Update[1002]: Changed learning rate to 9.90000e-04
Epoch[8] Train-Perplexity=1.213611
Epoch[8] Time cost=29.064
Epoch[9] Train-Perplexity=1.176342
Epoch[9] Time cost=29.036
Epoch[10] Train-Perplexity=1.159915
Epoch[10] Time cost=29.293
Epoch[11] Train-Perplexity=1.155166
Epoch[11] Time cost=29.381
Epoch[12] Train-Perplexity=1.144163
Epoch[12] Time cost=30.306
Epoch[13] Train-Perplexity=1.132149
Epoch[13] Time cost=29.419
Epoch[14] Train-Perplexity=1.128299
Epoch[14] Time cost=29.442
Epoch[15] Train-Perplexity=1.122329
Epoch[15] Time cost=28.333
Update[2002]: Changed learning rate to 9.80100e-04
Epoch[16] Train-Perplexity=1.117205
Epoch[16] Time cost=28.125
Epoch[17] Train-Perplexity=1.112755
Epoch[17] Time cost=27.983
Epoch[18] Train-Perplexity=1.108915
Epoch[18] Time cost=28.814
Epoch[19] Train-Perplexity=1.105198
Epoch[19] Time cost=28.301
Epoch[20] Train-Perplexity=1.102652
Epoch[20] Time cost=29.219
Epoch[21] Train-Perplexity=1.100201
Epoch[21] Time cost=28.100
Epoch[22] Train-Perplexity=1.098867
Epoch[22] Time cost=29.769
Epoch[23] Train-Perplexity=1.096245
Epoch[23] Time cost=29.723
Epoch[24] Train-Perplexity=1.094614
Epoch[24] Time cost=29.439
Saved checkpoint to "word_lstm-0025.params"

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

char_lstm_gen.plを改造。

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


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

……、以上!!

実行結果はこんな感じ。


First, you know Caius Marcius is chief enemy to the people.

All:
We know't, we know't.

First Citizen:
Let us kill him, and we'll have corn at our own price.
Is't a verdict?

All:
No more talking on't; let it be done: away, away!

Second Citizen:
One word, good citizens.

First Citizen:
We are further, we are undone already.

MENENIUS:
I tell you, friends, most charitable care
Have the patricians of you. For your wants,
Your suffering in this dearth, you may as well
Strike at the heaven with your staves as lift them
Against the Roman state, whose course 

心配していた、単語間の空白を飛ばすというのは、無さそうに見える。まあ、そのくらいの規則は学ぶか。

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