BrainScript CNTK Textformatsprachausgabe
Diese Seite dokumentiert den CNTKTextFormatReader aus der Sicht von BrainScript, aber Python-Benutzer können auch lernen, indem sie dieses Dokument lesen – die Konzepte, Parameter und Muster sind alle identisch.
CNTKTextFormatReader (später einfach CTF Reader) wurde entwickelt, um Eingabetextdaten zu nutzen, die gemäß der nachstehenden Spezifikation formatiert sind. Es unterstützt die folgenden Hauptfeatures:
- Mehrere Eingabedatenströme (Eingaben) pro Datei
- Sowohl geringe als auch dichte Eingaben
- Variable Längensequenzen
CNTK Textformat (CTF)
Jede Zeile in der Eingabedatei enthält ein Beispiel für eine oder mehrere Eingaben. Da jede Zeile (explizit oder implizit) auch an eine Sequenz angefügt wird, definiert sie eine oder <mehrere Sequenzen, Eingaben, Beispielbeziehungen> . Jede Eingabezeile muss wie folgt formatiert werden:
[Sequence_Id](Sample or Comment)+
where
Sample=|Input_Name (Value )*
Comment=|# some content
- Jede Zeile beginnt mit einer Sequenz-ID und enthält ein oder mehrere Beispiele (mit anderen Worten, jede Zeile ist eine nicht angeordnete Sammlung von Beispielen).
- Die Sequenz-ID ist eine Zahl. Es kann weggelassen werden, in diesem Fall wird die Zeilennummer als Sequenz-ID verwendet.
- Jedes Beispiel ist effektiv ein Schlüsselwertpaar, das aus einem Eingabenamen und dem entsprechenden Wertvektor besteht (die Zuordnung zu höheren Dimensionen erfolgt als Teil des Netzwerks selbst).
- Jedes Beispiel beginnt mit einem Rohrsymbol () gefolgt vom Eingabenamen (
|
ohne Leerzeichen), gefolgt von einem Leerzeichentrennzeichen und einer Liste der Werte. - Jeder Wert ist entweder eine Zahl oder eine indexpräfixierte Zahl für geringe Eingaben.
- Sowohl Registerkarten als auch Leerzeichen können austauschbar als Trennzeichen verwendet werden.
- Ein Kommentar beginnt mit einer Pipe unmittelbar gefolgt von einem Hashsymbol:
|#
und dann gefolgt vom tatsächlichen Inhalt (Textkörper) des Kommentars. Der Textkörper kann beliebige Zeichen enthalten, aber ein Rohrsymbol im Textkörper muss durch Anfügen des Hashsymbols an das Textzeichen escapet werden (siehe das folgende Beispiel). Der Textkörper eines Kommentars wird bis zum Ende der Zeile oder der nächsten nicht entweichten Röhre fortgesetzt, je nachdem, was zuerst kommt.
Einfaches Beispiel
Dieses Beispiel basiert auf einer minimalen Gruppe von Parametern und Formatoptionen.
So verwenden Sie den CTF Reader im readerType
CNTKTextFormatReader
Abschnitt "Reader" Ihrer CNTK-Konfiguration:
...
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 ...
(Dieses Fragment sowie andere NDL-Beispiele in diesem Dokument enthalten nur reader
Abschnitt, wobei der Rest der CNTK-Konfiguration weggelassen wird. Weitere Informationen finden Sie am Ende dieser Seite für Zeiger auf eine Reihe vollständiger Beispielnetzwerke und die entsprechenden Datasets)
Der CTF Reader erfordert den folgenden Satz von Parametern:
file
- Pfad zur Datei mit dem Dataset.input
- Unterabschnitt, der Eingaben definiert, die durch Eingabenamen (A
B
undC
im obigen Beispiel) identifiziert werden. Innerhalb jeder Eingabe müssen die folgenden erforderlichen Parameter angegeben werden:format
- gibt den Eingabetyp an. Muss entweder seindense
odersparse
dim
- gibt die Dimension des Eingabewertvektors an (für dichte Eingabe entspricht dies direkt der Anzahl der Werte in den einzelnen Beispielen, damit die Obergrenze für den Bereich möglicher Indexwerte begrenzt ist).
Die Eingabedaten, die der obigen Lesekonfiguration entsprechen, sollten wie folgt aussehen:
|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
Beachten Sie Folgendes über das Eingabeformat:
|Input_Name
gibt den Anfang jedes Eingabebeispiels an. Dieses Element ist obligatorisch und folgt dem korrespondenten Wertvektor.- Dichter Vektor ist nur eine Liste der Gleitkommawerte; Der geringe Vektor ist eine Liste von
index:value
Tupeln. - Sowohl Registerkarten als auch Leerzeichen sind als Werttrennzeichen (innerhalb von Eingabevektoren) sowie Eingabetrennzeichen (zwischen Eingaben) zulässig.
- Jede separate Zeile stellt eine "Sequenz" der Länge 1 dar ("Reale" Variable-Length-Sequenzen werden im folgenden erweiterten Beispiel erläutert).
- Jeder Eingabebezeichner kann nur einmal in einer einzelnen Zeile angezeigt werden (was pro Eingabe pro Zeile in ein Beispiel übersetzt wird).
- Die Reihenfolge der Eingabebeispiele in einer Zeile ist NICHT wichtig (konzeptual ist jede Zeile eine ungeordnete Auflistung von Schlüsselwertpaaren)
- Jede gut gebildete Linie muss entweder mit einem Symbol "Linienfeed"
\n
oder "Wagenrücklauf, Linienfeed"\r\n
enden.
Erweitertes Beispiel
In diesem Beispiel werden alle möglichen Konfigurationsparameter und verschiedene Eingabeformatoptionen angezeigt. Weitere Informationen zu den in diesem Beispiel verwendeten Konfigurationsparametern finden Sie in den nachstehenden Tabellen.
...
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 ...
Mit einem zusammengesetzten Reader würde es wie folgt aussehen:
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"}
}
})
}
Die entsprechende Eingabedatei kann dann ungefähr wie folgt aussehen:
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
Alle im obigen Beispiel beschriebenen Optionen gelten hier noch. Darüber hinaus haben wir zwei zusätzliche Features eingeführt:
Eingabenamenalias
Eingabenamen können beliebig lang sein und so diese während der Eingabedatei wiederholt werden, ist möglicherweise nicht platzeffizient. Um dies zu verringern, kann das Dataset "Aliase" anstelle vollständiger Eingabenamen verwenden. Aliase müssen dann innerhalb der einzelnen Eingabeunterabschnitte angegeben werden. In unserem Beispiel verwendet das Dataset Aliase a
und b
, die dem Abschnitt "Some_very_long_input_name" und "Some_other_also_very_long_input_name" zugeordnet sind.
Sequenz-IDs
Wie bereits erwähnt, stellt jede separate Zeile in der Eingabedatei eine Sequenz dar, die ein einzelnes Beispiel für jede Eingabe enthält. Wenn jedoch eine Zeile mit einer nicht negativen Zahl präfixiert wird, wird die Zahl als entsprechende Sequenz-ID verwendet. Alle nachfolgenden Zeilen, die dieselbe Sequenz-ID teilen, werden zusammengeführt, um Teil derselben Sequenz zu werden. Das Wiederholen desselben numerischen Präfixes für N-Zeilen ermöglicht es daher, eine Mehrbeispielsequenz zu erstellen, wobei jede Eingabe zwischen 1 und N-Beispielen enthalten ist. Das Auslassen des Sequenzpräfixes auf der zweiten und folgenden Zeilen hat denselben Effekt. Daher definiert das obige Beispiel-Dataset fünf Sequenzen mit IDs100
, 200
, 333
400
und .500
Durch Festlegen skipSequenceIds
des Parameters im Leseabschnitt auf true
, erzwingt der Leser, alle expliziten Sequenz-IDs im Dataset zu ignorieren und separate Zeilen als einzelne Sequenzen zu behandeln. Außerdem hat das Auslassen der Sequenz-ID in der ersten Zeile im Dataset denselben Effekt – alle nachfolgenden Sequenz-IDs werden ignoriert, Zeilen werden wie in diesem Beispiel als einzelne Sequenzen behandelt:
|a 1 2 3 |b 100 200
100 |a 4 5 6 |b 101 201
200 |b 102983 14532 |a 7 8 9
Einige letzte Dinge, die bei der Verwendung von Sequenzen berücksichtigt werden sollen:
- Sequenz-IDs müssen eindeutig sein.
- Id-Präfixe können nur für aufeinander folgende Zeilen wiederholt werden.
- Die Sequenzlänge in Zeilen (also die Anzahl der Zeilen, die dasselbe ID-Präfix teilen), darf die maximale Eingabelänge in Beispielen (die Anzahl der Beispiele in einer Eingabe) in dieser Sequenz nicht überschreiten.
Beispielsweise sind die folgenden Datasets ungültig:
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
Einige Real-World Beispiele
- Klassifizierung: Jede Zeile enthält ein Beispiel, bestehend aus einer Bezeichnung und Features. Es ist keine Sequenz-ID erforderlich, da jede Zeile eine eigene "Sequenz" der Länge 1 ist.
|class 23:1 |features 2 3 4 5 6
|class 13:1 |features 1 2 0 2 3
...
- DSSM: Jede Zeile enthält ein Quellzieldokumentpaar, das durch einen Beutel von Wörtern ausgedrückt wird und als sparsame Vektoren codiert ist.
|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
- Teil-of-Speech-Tagging: Sequenzen zuordnen jedes Element zu einer entsprechenden Bezeichnung. Die Sequenzen werden vertikal ausgerichtet (ein Wort + Tag pro Zeile).
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
...
- Sequenzklassifizierung: Sequenzen, die einer einzelnen Bezeichnung zugeordnet sind. Sequenzen werden vertikal ausgerichtet; Die Bezeichnung "Klasse" kann in einer beliebigen Zeile mit derselben SequenceId auftreten.
Hinweis
Derzeit darf die Anzahl der Zeilen nicht die Länge der längsten Sequenz überschreiten. Dies bedeutet, dass die Bezeichnung nicht in einer Zeile selbst angezeigt werden kann. Dies ist ein Implementierungsdetails, das künftig aufgehoben wird.
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
- Sequenz zur Sequenz: Zuordnen einer Quellsequenz zu einer Zielsequenz. Die beiden Sequenzen werden vertikal ausgerichtet und im einfachsten Fall direkt nach einem anderen gedruckt. Sie werden verbunden, indem sie dieselbe gesamt "Sequenz-ID" haben (die dann in diesem Fall zu einer "Arbeitseinheits-ID" wird).
Hinweis
Derzeit darf die Anzahl der Zeilen nicht die Länge der längsten Sequenz überschreiten. Dies bedeutet, dass Sequenzen horizontal ausgerichtet werden müssen. Dies ist ein Implementierungsdetails, das künftig aufgehoben wird.
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
...
- Learning zu Rang: Eine "Sequenz" stellt eine Abfrage dar, jedes Beispiel ein Dokument mit einer handbeschrifteten Bewertung. In diesem Fall ist die "Sequenz" nur ein Multiset, das (im Kontext einer Lern-zu-Rang-Verlustfunktion) keine Reihenfolge hat.
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
...
Konfigurationsparameter
Parameter | BESCHREIBUNG |
---|---|
precision |
Gibt die Gleitkommagenauigkeit (double oder float ) der Eingabewerte an. Optional, Standardwerte für float . |
reader
Abschnitt
Parameter | BESCHREIBUNG |
---|---|
readerType |
Gibt einen der unterstützten CNTK Leser an, die geladen werden sollen (z. B. CNTKTextFormatReader ). Erforderlich. |
file |
Pfad zur Datei mit dem Eingabedatensatz (Windows oder Linux-Stil). Erforderlich. |
randomize |
Gibt an, ob die Eingabe zufällig (true , false ). Optional, Standardeinstellungen für true . |
randomizationSeed |
Initial randomization seed value (incremented every sweep when the input data is re-randomized). Optional, Standardeinstellungen für 0 . |
randomizationWindow |
Gibt die Größe (positive Ganze Zahl) des Randomisierungsfensters (d. h. Zufallszahl) an. Dieser Parameter wirkt sich darauf aus, wie viel des Datasets gleichzeitig im Arbeitsspeicher enthalten sein muss. Optional, je nach sampleBasedRandomizationWindow Wert, standardisiert entweder die Größe des gesamten Datasets in Beispielen (d. h., die Eingabe wird im gesamten Dataset zufälligisiert), oder 4 GB Speicherplatz wert von Blöcken (d. 128 h., wenn die Chunkgröße 32 MB entspricht). Dieser Parameter wird ignoriert, wenn es sich um randomize false . |
sampleBasedRandomizationWindow |
Wenn true die Größe des Randomisierungsfensters als bestimmte Anzahl von Beispielen interpretiert wird, andernfalls -- als eine Reihe von Blöcken. Optional, Standardeinstellungen für false . Ähnlich wie randomizationWindow dieser Parameter wird ignoriert, wenn randomize false es sich um einen Wert handelt. |
skipSequenceIds |
Wenn true der Leser Sequenz-IDs in der Eingabedatei ignoriert, interpretiert jede separate Zeile als unabhängige Sequenz von Größe 1 (siehe Abschnitt auf den Sequenz-IDs). Optional, Standardeinstellungen für false . |
maxErrors |
Anzahl der Eingabefehler, nach denen eine Ausnahme ausgelöst werden sollte. Optional, Standardeinstellungen 0 , was bedeutet, dass der erste falsch formatierte Wert eine Ausnahme auslöst. |
traceLevel |
Ausgabe-Verbositätsstufe. 0 - Nur Fehler anzeigen; 1 - Fehler und Warnungen anzeigen; 2 - Alle Ausgabe anzeigen. Optional, Standardeinstellungen für 1 . |
chunkSizeInBytes |
Anzahl der aufeinanderfolgenden Bytes, die vom Datenträger in einem einzelnen Lesevorgang gelesen werden sollen. Optional, Standardeinstellungen ( 33554432 32 MB). |
keepDataInMemory |
Wenn true das gesamte Dataset im Arbeitsspeicher zwischengespeichert wird. Optional, Standardeinstellungen für false . |
frameMode |
true signalisiert den Leser, eine packungsmethode zu verwenden, die für Frames optimiert ist (Sequenzen, die nur ein einzelnes Beispiel enthalten). Optional, Standardeinstellungen für false . |
cacheIndex |
Gibt an, ob die metadaten, die während der Vorverarbeitungsphase erstellt wurden, auf Datenträger geschrieben und von Datenträger geladen werden sollen, sofern verfügbar (true , false ). Optional, Standardeinstellungen für false . Weitere Details finden Sie im folgenden Abschnitt. Neu in CNTK Version 2.1. |
Indexspeicherung
Hinweis
Neu in CNTK Version 2.1.
Indiz-Zwischenspeicherung ermöglicht es deutlich (durch einen Faktor von 2-3x) die Startzeiten zu reduzieren, insbesondere bei der Arbeit mit großen Eingabedateien. Durch Festlegen des cacheIndex
Flags true
wird der Leser signalisiert, dass die Indizierungsmetadaten auf Datenträger (dasselbe Verzeichnis wie die Eingabedatei) geschrieben werden, wenn die Cachedatei nicht verfügbar ist oder wenn es veraltet ist (älter als die Eingabedatei). Das Schreiben ist am besten geeignet und wird auf einem separaten Thread durchgeführt, um die Leseleistung nicht zu beeinträchtigen. Wenn die Cachedatei vorhanden ist und auf dem neuesten Stand ist, übergibt der Leser die Eingabedatei nicht mehr, um den Index zu erstellen, sondern lädt den Index aus der Cachedatei. Bitte beachten Sie, dass bestimmte Lesekonfigurationsparameter direkte Auswirkungen auf die Indexierung haben (z. B. unterschiedliche Werte frameMode
, die möglicherweise zu Indizes führen könnten, die verschiedene Anzahl von Sequenzen haben). Aus diesem Grund könnte eine Cachedatei von einem Leser ignoriert werden, der sich von einer Konfiguration unterscheidet, die den Cache erzeugt hat. Um den vollständigen Vorteil der Zwischenspeicherung zu sehen, sollte die Konfiguration bei nachfolgenden Wiederholungen nicht geändert werden.
input
Unterabschnitt
input
kombiniert eine Reihe einzelner Eingaben, die jeweils mit einem entsprechend beschrifteten Konfigurationsunterabschnitt versehen sind. Alle unten beschriebenen Parameter sind spezifisch für einen Teilabschnitt " Eingabename ", der einer bestimmten Eingabe zugeordnet ist.
Parameter | BESCHREIBUNG |
---|---|
alias |
Ein alternativer Kurzhandname (String), der verwendet wird, um die Eingabe im Dataset zu identifizieren. Optional |
format |
Gibt den Eingabetyp (dense , sparse ) an. Erforderlich. |
dim |
Dimension (positive ganze Zahl) des Eingabewerts (d. h., die Anzahl der Eingabewerte in einem Beispiel für dichte Eingabe, die obere Grenze im Indexbereich für sparse Eingabe). Erforderlich. |
definesMBSize |
Flag (Standard false), der angibt, ob die Minibatchgröße in Beispielen aus diesem bestimmten Datenstrom optional gezählt werden soll. |
Sie finden vollständige Netzwerkdefinitionen und die entsprechenden Beispiele im CNTK Repository. Dort finden Sie auch einen End-to-End-Test , der den CNTKTextFormat-Reader verwendet.