エジンバラ大学神経機械翻訳システムnematus使用ノート

11788 ワード

*ブログアドレス:http://blog.csdn.net/wangxinginnlp/article/details/64921476
*step by step instructionがないため、コードにめまいがして、後で使うために説明ドキュメントを書きます.[注意、赤い字は穴だらけです]
コードの準備:
nematus https://github.com/rsennrich/nematus
subword-nmt  https://github.com/rsennrich/subword-nmt
データの準備:
nematusには1000文の英独バイリンガル語彙(En-de)が付属している
実験環境:
nematusには構成が必要だと書かれています.
Nematus requires the following packages:
  • Python >= 2.7
  • numpy
  • Theano >= 0.7 (and its dependencies).

  • we recommend executing the following command in a Python virtual environment:  pip install numpy numexpr cython tables theano
    the following packages are optional, but highly recommended
  • CUDA >= 7 (only GPU training is sufficiently fast)
  • cuDNN >= 4 (speeds up training substantially)

  • you can run Nematus locally. To install it, execute  python setup.py install
    実験の疑問点:
    1.  なぜsource dictionariesが複数あるのですか?Linguistic Input Featuresをサポートし、Feautureごとにdictionary?
    nematusは複数のsource dictionariesの転送をサポート
    nmt.pyでsource dictionaryコードを受信:
    train = TextIterator(datasets[0], datasets[1],                          dictionaries[:-1], dictionaries[-1],
      ....)
    data_iterator.pyにTextIteratorがあります
    self.source_dicts = []
    for source_dict in source_dicts:     self.source_dicts.append(load_dict(source_dict))
    確かにそうです.READMEをよく読んでいません.
    --dictionaries PATH [PATH ...] network vocabularies (one per source factor, plus target vocabulary)
    *中国語と英語の練習語彙に中国語の部分に「|」の記号があり、そのまま掛けました.
    w = [self.source_dicts[i][f] if f in self.source_dicts[i] else 1 for (i,f) in enumerate(w.split('|'))] 
    ここでwはinput unit、デフォルトはword、Linguistic Input Featuresの間は「|」で区切られています.
    ステップ1:ファイルの解凍
    爱丁堡大学神经机器翻译系统 nematus 使用笔记_第1张图片
    **フォルダnematus-masterとsubword-nmt-masterは同じディレクトリの下にあります.
    ステップ2:データ処理、用語集vocabularyの生成.
    **独自のpreprocess.shスクリプト[スクリプトに問題があるようです]を使用して、バイリンガル語彙を処理します.
    独自のpreprocess.shは:
    #!/bin/bash
    
    P=$1
    
    # source language (example: fr)
    S=$2
    # target language (example: en)
    T=$3
    
    # path to nematus/data
    P1=$4
    
    # path to subword NMT scripts (can be downloaded from https://github.com/rsennrich/subword-nmt)
    P2=$5
    
    # tokenize
    perl $P1/tokenizer.perl -threads 5 -l $S < {P}.${S} > {P}.${S}.tok
    perl $P1/tokenizer.perl -threads 5 -l $T < {P}.${T} > {P}.${T}.tok
    
    # learn BPE on joint vocabulary:
    cat {P}.${S}.tok {P}.${T}.tok | python $P2/learn_bpe.py -s 20000 > ${S}${T}.bpe
    
    python $P2/apply_bpe.py -c ${S}${T}.bpe < {P}.${S}.tok > {P}.${S}.tok.bpe
    python $P2/apply_bpe.py -c ${S}${T}.bpe < {P}.${T}.tok > {P}.${T}.tok.bpe
    
    # build dictionary
    python $P1/build_dictionary.py {P}.${S}.tok.bpe
    python $P1/build_dictionary.py {P}.${T}.tok.bpe

    しかし、上のPとP 1の2つは処理中に逆になったようです.
    手動で書き換えることができます.
    #!/bin/bash
    
    #           (    )
    P=$1
    
    #        
    # source language (example: fr)
    S=$2
    
    #         
    # target language (example: en)
    T=$3
    
    #       
    # path to nematus/data
    P1=$4
    
    # subword      
    # path to subword NMT scripts (can be downloaded from https://github.com/rsennrich/subword-nmt)
    P2=$5
    
    #        tokenization
    # tokenize
    perl $P/tokenizer.perl -threads 5 -l $S < ${P1}.${S} > ${P1}.${S}.tok
    perl $P/tokenizer.perl -threads 5 -l $T < ${P1}.${T} > ${P1}.${T}.tok
    
    #  BPE         
    # learn BPE on joint vocabulary:
    cat ${P1}.${S}.tok ${P1}.${T}.tok | python $P2/learn_bpe.py -s 20000 > ${S}${T}.bpe
    
    #                  subword  
    python $P2/apply_bpe.py -c ${S}${T}.bpe < ${P1}.${S}.tok > ${P1}.${S}.tok.bpe
    python $P2/apply_bpe.py -c ${S}${T}.bpe < ${P1}.${T}.tok > ${P1}.${T}.tok.bpe
    
    #    subword          
    # build dictionary
    python $P/build_dictionary.py ${P1}.${S}.tok.bpe
    python $P/build_dictionary.py ${P1}.${T}.tok.bpe

    入力コマンド:./preprocess.sh./en de../test/data/corpus........./subword-nmt-master/
    コマンド前のデータディレクトリを入力します.nematus-master/test/dataの下(システムに付属)ファイル:
    爱丁堡大学神经机器翻译系统 nematus 使用笔记_第2张图片
    入力コマンド処理中:
    爱丁堡大学神经机器翻译系统 nematus 使用笔记_第3张图片
    コマンド処理後のデータディレクトリを入力します.nematus-master/test/dataの下のファイル:
    爱丁堡大学神经机器翻译系统 nematus 使用笔记_第4张图片
    corpus.enはシステムに付属する語彙です
           corpus.en.tokはtokenization後(perl $P/tokenizer.perl-threads 5-l$S<${P 1}.${S}>${P 1}.${S}.tok)の語料[持参語料は実はtoken過]
           corpus.en.tok.bpeはsubword処理後の語彙です
           corpus.en.tok.bpe.jsonはjson形式の英語(en)vocabulary
    nematusは2つのストレージフォーマットのvocabularyをサポートし、nematus/util.pyで辞書を読み取る関数は次のとおりです.
    def load_dict(filename):
        try:
            with open(filename, 'rb') as f:
                return unicode_to_utf8(json.load(f))
        except:
            with open(filename, 'rb') as f:
                return pkl.load(f)

    ディクショナリフォーマット:1.jasonフォーマット[nematusスクリプト付きデフォルト生成]
                      2.pkl形式
    ステップ3:モデルトレーニング
    nematus-master/testに付属のtest_train.sh
    #!/bin/bash
    
    # warning: this test is useful to check if training fails, and what speed you can achieve
    # the toy datasets are too small to obtain useful translation results,
    # and hyperparameters are chosen for speed, not for quality.
    # For a setup that preprocesses and trains a larger data set,
    # check https://github.com/rsennrich/wmt16-scripts/tree/master/sample
    
    mkdir -p models
    
    ../nematus/nmt.py \
      --model models/model.npz \
      --datasets data/corpus.en data/corpus.de \
      --dictionaries data/vocab.en.json data/vocab.de.json \
      --dim_word 256 \
      --dim 512 \
      --n_words_src 30000 \
      --n_words 30000 \
      --maxlen 50 \
      --optimizer adam \
      --lrate 0.0001 \
      --batch_size 40 \
      --no_shuffle \
      --dispFreq 500 \
      --finish_after 500
    

    パラメータはnematus-masterのREADME.mdで説明されています.最も重要なのは--datasets および --dictionariesパラメータは、訓練されたバイリンガル語彙とバイリンガル語彙にそれぞれ対応します.
    持参した語彙は1000文しかないため,訓練反復は最大500回(--finish_afterパラメータ)であり,訓練はすぐに終了した.
    爱丁堡大学神经机器翻译系统 nematus 使用笔记_第5张图片
    トレーニングが終了すると、モデルはパラメータ(--model)パスの下に保存され、そのパスの下で生成されたファイルを観察します.
    爱丁堡大学神经机器翻译系统 nematus 使用笔记_第6张图片
    ステップ4:モデルテスト
    test_translate.pyではsennrichが訓練したWMT 16 En->De En->Roモデルをネットからダウンロードする必要があります.このモデルをダウンロードしたくない場合は、手動でコードを変更します.
    1.ダウンロードモデルを直接実行する
    THEANO_FLAGS=mode=FAST_RUN,floatX=float32,device=gpu python test_translate.py
    **En->Deモデルは615 MBあり、ダウンロードに時間がかかります.
    En->Deモデルファイルを参照:http://data.statmt.org/rsennrich/wmt16_systems/de-en/
    2.構成を変更し、自分がさっき走ったモデルを実行します.モデルのダウンロードコードの一部を注釈します.
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    import os
    import unittest
    import requests
    
    sys.path.append(os.path.abspath('../nematus'))
    from translate import main as translate
    
    
    def load_wmt16_model(src, target):
            path = os.path.join('models', '{0}-{1}'.format(src,target))
            try:
                os.makedirs(path)
            except OSError:
                pass
            for filename in ['model.npz', 'model.npz.json', 'vocab.{0}.json'.format(src), 'vocab.{0}.json'.format(target)]:
                if not os.path.exists(os.path.join(path, filename)):
                    r = requests.get('http://data.statmt.org/rsennrich/wmt16_systems/{0}-{1}/'.format(src,target) + filename, stream=True)
                    with open(os.path.join(path, filename), 'wb') as f:
                        for chunk in r.iter_content(1024**2):
                            f.write(chunk)
    
    class TestTranslate(unittest.TestCase):
        """
        Regression tests for translation with WMT16 models
        """
    
        '''
        def setUp(self):
            """
            Download pre-trained models
            """
            #print '-------------'
            load_wmt16_model('en','de')
            load_wmt16_model('en','ro')
        '''
        def outputEqual(self, output1, output2):
            """given two translation outputs, check that output string is identical,
            and probabilities are equal within rounding error.
            """
            for i, (line, line2) in enumerate(zip(open(output1).readlines(), open(output2).readlines())):
                if not i % 2:
                    self.assertEqual(line, line2)
                else:
                    probs = map(float, line.split())
                    probs2 = map(float, line.split())
                    for p, p2 in zip(probs, probs2):
                        self.assertAlmostEqual(p, p2, 5)
    
        # English-German WMT16 system, no dropout
        def test_ende(self):
            os.chdir('models/en-de/')
            translate(['model.npz'], open('../../en-de/in'), open('../../en-de/out','w'), k=12, normalize=True, n_process=1, suppress_unk=True, print_word_probabilities=True)
            os.chdir('../..')
            self.outputEqual('en-de/ref','en-de/out')
    
        '''
        # English-Romanian WMT16 system, dropout
        def test_enro(self):
            os.chdir('models/en-ro/')
            translate(['model.npz'], open('../../en-ro/in'), open('../../en-ro/out','w'), k=12, normalize=True, n_process=1, suppress_unk=True, print_word_probabilities=True)
            os.chdir('../..')
            self.outputEqual('en-ro/ref','en-ro/out')
        '''
    
    
    if __name__ == '__main__':
        unittest.main()
    

    コードがmodels/en-de/ディレクトリからmodel.npzファイルを読み取ることを発見し、models/en-de/ディレクトリを構築し、さっき訓練したmodel.npzコピーを入力します.
    モデル.npz.jasonファイルが見つかりません.モデル.npz.jasonはモデルのプロファイルです.モデル.npzはモデルのパラメータです.
    エラーを報告し続けます.model.npz.jasonではバイリンガル辞書のパスが間違っています.前のステップで保存したmodel.npz.jasonは相対パスの語彙表ファイルを記録しています.ディレクトリを切り替えましたが、このファイルが読めません.変更が必要です dictionaries:プロパティ.
    しかし、さっきの訓練の語彙が少なかったため、モデルの訓練が悪かったので、復号された文はすべて「,」から構成されていた.
    ステップ5:subwordリカバリ
    TBD
    ステップ6:翻訳パフォーマンス評価
    TBD