FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Googleの言語構文解析ツールSyntaxNetを試行(ツールの改造と学習試行)

https://3.bp.blogspot.com/-M-7PIST2hq8/VzTFhESMeuI/AAAAAAAAA_s/k4wOQe0UlnwmoVnZtuU6CNHw6xLQRN7egCLcB/s1600/asawb.png

msyksphinz.hatenablog.com

前回の続き。

前回は、一応インストールが完了し、基本的な学習方法を調査したのだが、実際に試行してみるとエラーが出てきたのだった。

1. カテゴリ分類時のエラーを除去するための再ビルド

エラーとなったのは、学習対象の Universal Dependency のトレーニングセットが詳細分類が被っているために発生する以下のエラーだった。

F syntaxnet/term_frequency_map.cc:166] Check failed: category == it->second (VERB vs. AUX)POS tag cannot be mapped to multiple coarse POS tags. 'VB' is mapped to: 'VERB' and 'AUX'

これ、エラーメッセージが示しているように、トレーニングセットの分類を行っている最中に発生している。当該ソースコードは以下だ。

github.com

void TagToCategoryMap::SetCategory(const string &tag, const string &category) {
  const auto it = tag_to_category_.find(tag);
  if (it != tag_to_category_.end()) {
    CHECK_EQ(category, it->second)
        << "POS tag cannot be mapped to multiple coarse POS tags. "
        << "'" << tag << "' is mapped to: '" << category << "' and '"
        << it->second << "'";
  } else {
    tag_to_category_[tag] = category;
  }
}

別に詳細分類が被っても、学習には特に問題にならないんじゃないのかなあ? ともかく、この条件式を外して、問答無用でカテゴリ分類するように変更してみる。

void TagToCategoryMap::SetCategory(const string &tag, const string &category) {
  const auto it = tag_to_category_.find(tag);
  tag_to_category_[tag] = category;
}

これで再度SyntaxNetのビルドを行い、学習させてみる。

$ bazel test syntaxnet/... util/utf8/...
$ bazel-bin/syntaxnet/parser_trainer \
  --task_context=syntaxnet/context.pbtxt \
  --compute_lexicon \
  --arg_prefix=brain_pos \
  --graph_builder=greedy \
  --training_corpus=training-corpus \  # names of training/tuning set
  --tuning_corpus=tuning-corpus \
  --output_path=models \  # where to save new resources
  --batch_size=32 \       # Hyper-parameters
  --decay_steps=3600 \
  --hidden_layer_sizes=128 \
  --learning_rate=0.08 \
  --momentum=0.9 \
  --seed=0 \
  --params=128-0.08-3600-0.9-1  # name for these parameters
INFO:tensorflow:Computing lexicon...
I syntaxnet/lexicon_builder.cc:124] Term maps collected over 204586 tokens from 12543 documents
I syntaxnet/term_frequency_map.cc:137] Saved 18731 terms to models/brain_pos/greedy/128-0.08-3600-0.9-1/word-map.
I syntaxnet/term_frequency_map.cc:137] Saved 15710 terms to models/brain_pos/greedy/128-0.08-3600-0.9-1/lcword-map.
I syntaxnet/term_frequency_map.cc:137] Saved 50 terms to models/brain_pos/greedy/128-0.08-3600-0.9-1/tag-map.
I syntaxnet/term_frequency_map.cc:137] Saved 17 terms to models/brain_pos/greedy/128-0.08-3600-0.9-1/category-map.
I syntaxnet/term_frequency_map.cc:137] Saved 47 terms to models/brain_pos/greedy/128-0.08-3600-0.9-1/label-map.
I syntaxnet/term_frequency_map.cc:101] Loaded 47 terms from models/brain_pos/greedy/128-0.08-3600-0.9-1/label-map.
I syntaxnet/embedding_feature_extractor.cc:35] Features: stack(3).word stack(2).word stack(1).word stack.word input.word input(1).word input(2).word inp
ut(3).word;input.digit input.hyphen;stack.suffix(length=2) input.suffix(length=2) input(1).suffix(length=2);stack.prefix(length=2) input.prefix(length=2
) input(1).prefix(length=2)
....

INFO:tensorflow:Epochs: 9, num steps: 56900, seconds elapsed: 471.62, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57000, seconds elapsed: 472.42, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57100, seconds elapsed: 473.18, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57200, seconds elapsed: 474.00, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57300, seconds elapsed: 474.78, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57400, seconds elapsed: 475.55, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57500, seconds elapsed: 476.32, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57600, seconds elapsed: 477.08, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57700, seconds elapsed: 477.82, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57800, seconds elapsed: 478.58, avg cost: 0.04,
INFO:tensorflow:Epochs: 9, num steps: 57900, seconds elapsed: 479.35, avg cost: 0.04,
I syntaxnet/reader_ops.cc:141] Starting epoch 10

お、何か学習したようだ。成功だ。

思うに、今回は無料のCONLLデータセットであるUniversal Dependencyを使用したから発生したエラーではないだろうか。 Googleの説明には、ほかにも有料のデータセットを使うことができるが、Universal Dependencyのみ無料で使うことができる。 有料版では、このようなエラーを発生させるデータセットは存在しなかったということかなあ?

ここで、学習パラメータとして128-0.08-3600-0.9-1を指定している。 試しに、models/brain_pos/greedy/128-0.08-3600-0.9-1 を参照してみると、以下のようなファイルが作成されていた。

-rw-rw-r-- 1 vagrant vagrant   114377 May 18 15:37 model.meta
-rw-rw-r-- 1 vagrant vagrant      110 May 18 15:37 checkpoint
-rw-rw-r-- 1 vagrant vagrant 16264746 May 18 15:37 model
-rw-rw-r-- 1 vagrant vagrant   114377 May 18 15:37 latest-model.meta
-rw-rw-r-- 1 vagrant vagrant 16264746 May 18 15:37 latest-model
-rw-rw-r-- 1 vagrant vagrant     1077 May 18 15:37 status
-rw-rw-r-- 1 vagrant vagrant   104888 May 18 15:29 graph
-rw-rw-r-- 1 vagrant vagrant      407 May 18 15:29 tag-to-category
-rw-rw-r-- 1 vagrant vagrant    62459 May 18 15:29 prefix-table
-rw-rw-r-- 1 vagrant vagrant    48771 May 18 15:29 suffix-table
-rw-rw-r-- 1 vagrant vagrant      172 May 18 15:29 category-map
-rw-rw-r-- 1 vagrant vagrant      547 May 18 15:29 label-map
-rw-rw-r-- 1 vagrant vagrant   168481 May 18 15:29 lcword-map
-rw-rw-r-- 1 vagrant vagrant      407 May 18 15:29 tag-map
-rw-rw-r-- 1 vagrant vagrant   195686 May 18 15:29 word-map
-rw-rw-r-- 1 vagrant vagrant     5359 May 18 15:29 context

いくつかのカテゴリ情報と、モデルなどが生成されている。ともかく、これで最初のステップである学習は上手くいったかな?

2. 学習結果をもとに分類テストを実行

次に、学習したモデルをもとに実際に単語の分類をしてみよう。これは、チュートリアルにおける以下に該当する(と思う)。

github.com

さっそく実行してみる。トレーニングセットとして、先ほど学習させたパラメータPARAMS=128-0.08-3600-0.9-1を利用する。

これにより、syntaxnet/context.pbtxtに記載されているen-ud-test.conlluを使って学習結果をテストするという訳だ。

input {
  name: 'dev-corpus'
  record_format: 'conll-sentence'
  Part {
    file_pattern: '/home/vagrant/work/ud-treebanks-v1.3/UD_English/en-ud-test.conllu'
  }
}

実行してみよう。

$ for SET in training tuning dev
do
   bazel-bin/syntaxnet/parser_eval    \
   --task_context=models/brain_pos/greedy/$PARAMS/context  \
   --hidden_layer_sizes=128   \
   --input=$SET-corpus  \
   --output=tagged-$SET-corpus  \
   --arg_prefix=brain_pos  \
   --graph_builder=greedy  \
   --model_path=models/brain_pos/greedy/$PARAMS/model
done

I syntaxnet/term_frequency_map.cc:101] Loaded 47 terms from models/brain_pos/greedy/128-0.08-3600-0.9-1/label-map.
I syntaxnet/embedding_feature_extractor.cc:35] Features: stack(3).word stack(2).word stack(1).word stack.word input.word input(1).word input(2).word inp
ut(3).word;input.digit input.hyphen;stack.suffix(length=2) input.suffix(length=2) input(1).suffix(length=2);stack.prefix(length=2) input.prefix(length=2
) input(1).prefix(length=2)
I syntaxnet/embedding_feature_extractor.cc:36] Embedding names: words;other;suffix;prefix
I syntaxnet/embedding_feature_extractor.cc:37] Embedding dims: 64;4;8;8
I syntaxnet/term_frequency_map.cc:101] Loaded 18731 terms from models/brain_pos/greedy/128-0.08-3600-0.9-1/word-map.
I syntaxnet/term_frequency_map.cc:101] Loaded 50 terms from models/brain_pos/greedy/128-0.08-3600-0.9-1/tag-map.
INFO:tensorflow:Building training network with parameters: feature_sizes: [8 2 3 3] domain_sizes: [18734     5  4195  5342]
INFO:tensorflow:Created variable transition_scores:0 with shape (32, 50) and init <function _initializer at 0x7fb7d1383a28>
INFO:tensorflow:Created variable step:0 with shape () and init <function OnesInitializer at 0x7fb7d1383ed8>
...
INFO:tensorflow:Processed 14 documents
INFO:tensorflow:Processed 17 documents
INFO:tensorflow:Processed 45 documents
INFO:tensorflow:Processed 16 documents
INFO:tensorflow:Processed 34 documents
I syntaxnet/reader_ops.cc:141] Starting epoch 2
INFO:tensorflow:Processed 2 documents
INFO:tensorflow:Total processed documents: 2077
INFO:tensorflow:num correct tokens: 23093
INFO:tensorflow:total tokens: 25096
INFO:tensorflow:Seconds elapsed in evaluation: 1.77, eval metric: 92.02%

最後に分類精度が表示されている。92.02%ということかな?

先ほど参照したパラメータセットのディレクトリに、新しくファイルが作成されていた。

$ ls -lt models/brain_pos/greedy/128-0.08-3600-0.9-1/
total 40528
-rw-rw-r-- 1 vagrant vagrant   796274 May 18 15:38 tagged-dev-corpus
-rw-rw-r-- 1 vagrant vagrant   798668 May 18 15:38 tagged-tuning-corpus
-rw-rw-r-- 1 vagrant vagrant  6518513 May 18 15:38 tagged-training-corpus
-rw-rw-r-- 1 vagrant vagrant   114377 May 18 15:37 model.meta
-rw-rw-r-- 1 vagrant vagrant      110 May 18 15:37 checkpoint
-rw-rw-r-- 1 vagrant vagrant 16264746 May 18 15:37 model
-rw-rw-r-- 1 vagrant vagrant   114377 May 18 15:37 latest-model.meta
-rw-rw-r-- 1 vagrant vagrant 16264746 May 18 15:37 latest-model
-rw-rw-r-- 1 vagrant vagrant     1077 May 18 15:37 status
-rw-rw-r-- 1 vagrant vagrant   104888 May 18 15:29 graph
-rw-rw-r-- 1 vagrant vagrant      407 May 18 15:29 tag-to-category
-rw-rw-r-- 1 vagrant vagrant    62459 May 18 15:29 prefix-table
-rw-rw-r-- 1 vagrant vagrant    48771 May 18 15:29 suffix-table
-rw-rw-r-- 1 vagrant vagrant      172 May 18 15:29 category-map
-rw-rw-r-- 1 vagrant vagrant      547 May 18 15:29 label-map
-rw-rw-r-- 1 vagrant vagrant   168481 May 18 15:29 lcword-map
-rw-rw-r-- 1 vagrant vagrant      407 May 18 15:29 tag-map
-rw-rw-r-- 1 vagrant vagrant   195686 May 18 15:29 word-map
-rw-rw-r-- 1 vagrant vagrant     5359 May 18 15:29 context

tagged-dev-corpusがテスト結果だと思うのだが、ある程度は合っている、という印象だ。最初の一文を抜き出してみよう。以下は学習結果によるテスト。

1       What    _       PRON    WP      _       0       root    _       _
2       if      _       ADP     IN      _       4       mark    _       _
3       Google  _       PROPN   NNP     _       4       nsubj   _       _
4       Morphed _       VERB    VBN     _       1       advcl   _       _
5       Into    _       PROPN   NNP     _       6       case    _       _
6       GoogleOS        _       NUM     CD      _       4       nmod    _       _
7       ?       _       PUNCT   .       _       4       punct   _       _

ちなみに本来の答えはこちら。

1       What    what    PRON    WP      PronType=Int    0       root    _       _
2       if      if      SCONJ   IN      _       4       mark    _       _
3       Google  Google  PROPN   NNP     Number=Sing     4       nsubj   _       _
4       Morphed morph   VERB    VBD     Mood=Ind|Tense=Past|VerbForm=Fin        1       advcl   _       _
5       Into    into    ADP     IN      _       6       case    _       _
6       GoogleOS        GoogleOS        PROPN   NNP     Number=Sing     4       nmod    _       SpaceAfter=No
7       ?       ?       PUNCT   .       _       4       punct   _       _

いくつか外れているものがある。これが学習の成果、ということなのかな?