次の方法で共有


BrainScript CNTK テキスト形式リーダー

このページでは、BrainScript の観点から CNTKTextFormatReader について説明しますが、Python ユーザーもこのドキュメントを読むことで学習できます。概念、パラメーター、パターンはすべて同じです。

CNTKTextFormatReader (後で単純に CTF リーダー) は、以下の仕様に従って書式設定された入力テキスト データを使用するように設計されています。 次の主な機能がサポートされています。

  • ファイルごとに複数の入力ストリーム (入力)
  • スパース入力と高密度入力の両方
  • 可変長シーケンス

CNTK テキスト形式 (CTF)

入力ファイルの各行には、1 つ以上の入力に対して 1 つのサンプルが含まれています。 (明示的または暗黙的に) すべての行もシーケンスにアタッチされるため、1 つ以上 <のシーケンス、入力、サンプル> の関係を定義します。 各入力行は、次のように書式設定する必要があります。

[Sequence_Id](Sample or Comment)+

where

Sample=|Input_Name (Value )*

Comment=|# some content

  • 各行はシーケンス ID で始まり、1 つ以上のサンプルが含まれます (つまり、各行は順序付けられていないサンプルのコレクションです)。
  • シーケンス ID は数値です。 この場合は、シーケンス ID として行番号が使用されます。省略できます。
  • 各サンプルは、実質的には、入力名と対応する値ベクトルで構成されるキーと値のペアです (より高い次元へのマッピングは、ネットワーク自体の一部として行われます)。
  • 各サンプルは、パイプ記号 (|) の後に入力名 (スペースなし)、空白区切り記号、値の一覧で始まります。
  • 各値は、スパース入力の数値またはインデックスプレフィックス付きの番号です。
  • タブとスペースの両方を区切り記号として同じ意味で使用できます。
  • コメントはパイプの直後にハッシュ記号で始まり、 |#その後にコメントの実際のコンテンツ (本文) が続きます。 本文には任意の文字を含めることができますが、本文内のパイプ シンボルをエスケープするには、ハッシュ 記号を追加する必要があります (次の例を参照)。 コメントの本文は、行の末尾または次のエスケープされていないパイプのいずれか早い方まで続きます。

簡単な例

この例は、パラメーターと書式オプションの最小セットに基づいています。

CTF リーダーを使用するには、readerTypeCNTKTextFormatReader CNTK構成のリーダー セクションで to を設定します。

...
reader = [
    readerType = "CNTKTextFormatReader"
    file = "c:\mydata\SampleInput.txt" # See the second example for Linux path example

    # IMPORTANT!
    # All inputs are grouped within "input" sub-section.
    input = [
        A = [
            dim = 5
            format = "dense"
        ]
        B = [
            dim = 1000000
            format = "sparse"
        ]
        C = [
            dim = 1
            format = "dense"
        ]
    ]
]
# the rest of the cntk config ...

(このフラグメントと、このドキュメントの他の NDL の例は、CNTK構成の残りの部分を省略し、完全な例のネットワークと対応するデータセットのセットへのポインターについては、このページの最後を参照してください)reader

CTF リーダーには、次のパラメーターのセットが必要です。

  • file - データセットを含むファイルへのパス。
  • input- 入力名 (ABおよびC上記の例) で識別される入力を定義するサブセクション。 各入力内で、次の必須パラメーターを指定する必要があります。
    • format - 入力の種類を指定します。 次のいずれかである必要があります。densesparse
    • dim - 入力値ベクトルの次元を指定します ( 高密度 入力の場合、これは各サンプルの値の数に直接対応します。 スパース の場合、これは可能なインデックス値の範囲の上限を表します)。

上記のリーダー構成に対応する入力データは、次のようになります。

|B 100:3 123:4 |C 8 |A 0 1 2 3 4 |# a CTF comment
|# another comment |A 0 1.1 22 0.3 54 |C 123917 |B 1134:1.911 13331:0.014
|C -0.001 |# a comment with an escaped pipe: '|#' |A 3.9 1.11 121.2 99.13 0.04 |B 999:0.001 918918:-9.19

入力形式については、次の点に注意してください。

  • |Input_Name は、各入力サンプルの先頭を識別します。 この要素は必須であり、その後に対応する値ベクトルが続きます。
  • 高密度ベクトルは浮動小数点値のリストにすぎません。スパース ベクターはタプルの index:value 一覧です。
  • タブとスペースはどちらも、値区切り記号 ( 入力ベクトル内) と入力区切り記号 (入力間) として使用できます。
  • 各行は、長さ 1 の "シーケンス" を構成します ("Real" 可変長シーケンスについては、以下の拡張例で説明します)。
  • 各入力識別子は、1 行に 1 回しか表示できません (これは、 1 行の要件ごとに入力ごとに 1 つのサンプル に変換されます)。
  • 行内の入力サンプルの順序は重要ではありません (概念的には、各行はキーと値のペアの順序付けられていないコレクションです)。
  • 各整形式の線は、"ライン フィード" \n または "キャリッジ リターン、ライン フィード" \r\n 記号で終わる必要があります。

拡張例

この例では、使用可能なすべての構成パラメーターを特徴とし、さまざまな入力形式オプションを示します。 この例で使用される構成パラメーターの完全な説明については、 以下 の表を参照してください。

...
precision="double"

reader = [
    readerType = "CNTKTextFormatReader"
    file = "/home/mydata/SampleInput.txt" # See the first example for Windows style path example
    randomize = true
    randomizationWindow = 30
    skipSequenceIds = false
    maxErrors = 100
    traceLevel = 2

    chunkSizeInBytes = 1024

    keepDataInMemory = true
    frameMode = false

    input = [
        Some_very_long_input_name = [
            alias = "a"
            dim = 3
            format = "dense"
        ]
        Some_other_also_very_long_input_name = [
            alias = "b"
            dim = 2
            format = "dense"
        ]
    ]
]
# the rest of the cntk config ...

複合リーダーを使用すると、次のようになります。

reader = {
        verbosity = 0 ;
        randomize = true;
        randomizationWindow=30
        deserializers = ({
            type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
            file = "/home/mydata/SampleInput.txt" # See the first example for Windows style path example
            maxErrors = 100
            skipSequenceIds = false
            traceLevel = 2
            input = {
                qu1fea = {alias = "qui"; dim = 95589; format = "sparse"}
                qu2fea = {alias = "quj"; dim = 95589; format = "sparse"}
                pairweight = {alias = "wij"; dim = 1; format = "dense"}
            }
        })
    }

対応する入力ファイルは、次のようになります。

100 |a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
100 |b 102983 14532 |a 7 8 9
100 |a 7 8 9
200 |b 300 400 |a 10 20 30
333 |b 500 100
333 |b 600 -900
400 |a 1 2 3 |b 100 200
|a 4 5 6 |b 101 201
|a 4 5 6 |b 101 201
500 |a 1 2 3 |b 100 200

上記の例で説明したすべてのオプションは、ここでも適用されます。 その上で、次の 2 つの追加機能を導入しました。

入力名のエイリアス

入力名は任意の長さとすることができ、入力ファイル全体で繰り返す場合は、スペース効率が良くない可能性があります。 これを軽減するために、データセットでは、完全な入力名の代わりに "エイリアス" を使用できます。 その後、各入力サブセクション内でエイリアスを指定する必要があります。 この例では、データセットはエイリアス a を使用し b、リーダー構成セクションでそれぞれ "Some_very_long_input_name" と "Some_other_also_very_long_input_name" にマップされます。

シーケンス ID

既に説明したように、入力ファイル内の各行は、入力ごとに 1 つのサンプルを含む シーケンス を表します。 ただし、行の先頭に負以外の数値が付いている場合は、対応する シーケンス ID として番号が使用されます。同じシーケンス ID を共有する後続のすべての行は、同じシーケンスの一部になるように結合されます。 したがって、N 行に対して同じ数値プレフィックスを繰り返して、各入力に 1 ~ N 個のサンプルを含むマルチサンプル シーケンスを構築できます。 2 行目以降の行でシーケンス プレフィックスを省略すると、同じ効果が得られます。 したがって、上記の例のデータセットでは、id、100400200333および .500

reader セクションでパラメーターを設定 skipSequenceIds すると true、データセット内のすべての明示的なシーケンス ID が無視され、個別の行が個別のシーケンスとして扱われます。 また、データセットの最初の行でシーケンス ID を省略すると、同じ効果があります。次の例のように、後続のすべてのシーケンス ID は無視され、行は個々のシーケンスとして扱われます。

|a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
200 |b 102983 14532 |a 7 8 9

シーケンスを使用する際に考慮すべき最後の点をいくつか次に示します。

  • シーケンス ID は一意である必要があります。
  • ID プレフィックスは、連続する行に対してのみ繰り返すことができます。
  • シーケンスの長さ (つまり、同じ ID プレフィックスを共有する行数) は、このシーケンス内のサンプルの最大入力長 (入力内のサンプル数) を超えてはなりません。

たとえば、次のデータセットは 無効です

100 |a 1 2 3 |b 100 200
200 |a 4 5 6 |b 101 201
100 |b 102983 14532 |a 7 8 9

123 |a 1 2 3 |b 100 200
456 |a 4 5 6
456 |b 101 201

いくつかのReal-Worldの例

  • 分類: すべての行には、ラベルと特徴で構成されるサンプルが含まれています。 すべての行は長さ 1 の独自の "シーケンス" であるため、シーケンス ID は必要ありません。
|class 23:1 |features 2 3 4 5 6
|class 13:1 |features 1 2 0 2 3
...
  • DSSM: すべての行には、スパース ベクターとしてエンコードされた単語のバッグを介して表現されたソースとターゲットのドキュメント のペアが含まれています。
|src 12:1 23:1 345:2 45001:1    |tgt 233:1 766:2 234:1
|src 123:1 56:1 10324:1 18001:3 |tgt 233:1 2344:2 8889:1 2234:1 253434:1
  • 品詞タグ付け: すべての要素を対応するラベルにマッピングするシーケンス。 シーケンスは垂直方向に配置されます (行ごとに 1 単語 + タグ)。
0 |word 234:1 |tag 12:1
0 |word 123:1 |tag 10:1
0 |word 123:1 |tag 13:1
1 |word 234:1 |tag 12:1
1 |word 123:1 |tag 10:1
...
  • シーケンス分類: 1 つのラベルにマップされたシーケンス。 シーケンスは垂直方向に配置されます。"class" ラベルは、同じ sequenceId を持つ任意の行で発生する可能性があります。

注意

現時点では、行数が最も長いシーケンスの長さを超えてはなりません。 これは、ラベルを単独で行に表示できないことを意味します。 これは、今後解除される実装の詳細です。

0 |word 234:1 |class 3:1
0 |word 123:1
0 |word 890:1
1 |word 11:1 |class 2:1
1 |word 344:1
  • シーケンス先シーケンス: ソース シーケンスをターゲット シーケンスにマップします。 2 つのシーケンスは垂直方向に配置され、最も簡単なケースでは、次の順序で印刷されます。 これらは、全体的に同じ "シーケンス ID" を持つことによって結合されます (この場合は "作業単位 ID" になります)。

注意

現時点では、行数が最も長いシーケンスの長さを超えてはなりません。 つまり、シーケンスは水平方向に配置する必要があります。 これは、今後解除される実装の詳細です。

0 |sourceWord 234:1  |targetWord 344:1
0 |sourceWord 123:1  |targetWord 456:1
0 |sourceWord 123:1  |targetWord 2222:1
0 |sourceWord 11:1
1 |sourceWord 123:1
...
  • Rank にラーニング: "シーケンス" はクエリを表し、すべてのサンプルは手動でラベル付けされた評価を持つドキュメントを表します。 この場合、"シーケンス" は、(learning-to-rank 損失関数のコンテキストで) 順序付けを持たない単なるマルチセットです。
0 |rating 4 |features 23 35 0 0 0 21 2345 0 0 0 0 0
0 |rating 2 |features 0 123 0 22 44 44 290 22 22 22 33 0
0 |rating 1 |features 0 0 0 0 0 0 1 0 0 0 0 0
1 |rating 1 |features 34 56 0 0 0 45 1312 0 0 0 0 0
1 |rating 0 |features 45 45 0 0 0 12 335 0 0 0 0 0
2 |rating 0 |features 0 0 0 0 0 0 22 0 0 0 0 0
...

構成パラメーター

パラメーター 説明
precision 入力値の浮動小数点精度 (double または float) を指定します。 省略可能。既定値は float.

reader セクション

パラメーター 説明
readerType 読み込む、サポートされているCNTKリーダーの 1 つを指定します (例: CNTKTextFormatReader)。 [必須]
file 入力データセット (Windows または Linux スタイル) を含むファイルへのパス。 [必須]
randomize 入力をランダム化する必要があるかどうかを指定します (true, false). 省略可能。既定値は true.
randomizationSeed 初期ランダム化シード値 (入力データが再ランダム化されるときに、すべてのスイープがインクリメントされます)。 省略可能。既定値は 0.
randomizationWindow ランダム化ウィンドウのサイズ (正の整数) を指定します (つまり、ランダム化範囲)。 このパラメーターは、一度にメモリに格納する必要があるデータセットの量に影響します。 省略可能な値に sampleBasedRandomizationWindow 応じて、既定値はサンプル内のデータセット全体のサイズ (つまり、データセット全体でランダム化されます)、または 4 GB のディスク領域分のチャンク ( 128 チャンク サイズが 32 MB の場合) のいずれかになります。 このパラメーターは、次の場合randomizefalseは無視されます。
sampleBasedRandomizationWindow ランダム化ウィンドウのサイズが特定の数のサンプルとして解釈される場合は、それ以外の場合 trueはチャンクの数として解釈されます。 省略可能。既定値は false. 同様に randomizationWindow、このパラメーターは無視され、次の場合 randomizefalse無視されます。
skipSequenceIds この場合 true、リーダーは入力ファイル内のシーケンス ID を無視し、各行をサイズ 1 の独立したシーケンスとして解釈します (シーケンス ID のセクションを参照)。 省略可能。既定値は false.
maxErrors 例外を発生させる必要がある入力エラーの数。 省略可能です。既定値 0は、形式が正しくない最初の値が例外をトリガーすることを意味します。
traceLevel 出力詳細レベル。 0 - エラーのみを表示します。 1 - エラーと警告を表示します。 2 - すべての出力を表示します。 省略可能。既定値は 1.
chunkSizeInBytes 1 回の読み取り操作でディスクから読み取る連続バイト数。 省略可能。既定値は 33554432 (32 MB)。
keepDataInMemory この場合 true、データセット全体がメモリにキャッシュされます。 省略可能。既定値は false.
frameMode true は、フレーム (1 つのサンプルのみを含むシーケンス) 用に最適化されたパッキング方法を使用するようにリーダーに通知します。 省略可能。既定値は false.
cacheIndex 前処理ステージ中に構築されたメタデータをディスクに書き出し、使用可能な場合はディスクから読み込むかどうかを指定します (true, false)。 省略可能。既定値は false. 詳細については、以下のセクションを参照してください。 CNTK バージョン 2.1 の新機能。
インデックスのキャッシュ

注意

CNTK バージョン 2.1 の新機能。

インデックス キャッシュを使用すると、特に大きな入力ファイルを操作する場合に、起動時間を大幅に短縮できます (2 ~ 3 倍)。 このフラグをcacheIndextrue設定すると、キャッシュ ファイルが使用できない場合や古い (入力ファイルより古い) 場合に、インデックス作成メタ データをディスク (入力ファイルと同じディレクトリ) に書き込むようリーダーに通知されます。 この書き込みはベスト エフォートであり、リーダーのパフォーマンスに影響を与えないように、別のスレッドで実行されます。 キャッシュ ファイルが存在し、最新の状態である場合、リーダーは入力ファイルをスキミングしてインデックスを作成しなくなります。代わりに、キャッシュ ファイルからインデックスが読み込まれます。 特定のリーダー構成パラメーターがインデックス作成に直接影響することに注意してください (たとえば、値が frameMode 異なると、インデックスのシーケンス数が異なる可能性があります)。 そのため、キャッシュファイルは、キャッシュを生成した構成とは異なる構成を持つリーダーによって無視される可能性があります。 キャッシュの利点をすべて確認するには、以降の再実行で構成を変更しないでください。

input sub-section

input は多数の個々の入力を組み合わせ、それぞれに適切なラベル付けされた構成サブセクションが含まれています。 以下で説明するすべてのパラメーターは、特定の入力に関連付けられている 入力名 サブセクションに固有です。

パラメーター 説明
alias データセット内の入力を識別するために使用される別の短縮形名 (文字列)。 省略可能
format 入力の種類 (dense, sparse) を指定します。 [必須]
dim 入力値のディメンション (正の整数) (つまり、 入力のサンプル内の入力値の数、 スパース 入力のインデックス範囲の上限)。 [必須]
definesMBSize フラグ (既定の false)、この特定のストリームのサンプルでミニバッチ サイズをカウントする必要があるかどうかを示す 省略可能

完全なネットワーク定義対応するデータ セットの例は、CNTK リポジトリにあります。 CNTKTextFormat リーダーを使用 するエンド ツー エンド テスト もあります。