Dela via


BrainScript CNTK textformatläsare

Den här sidan dokumenterar CNTKTextFormatReader ur BrainScript-synvinkel, men Python användare kan lära sig genom att läsa det här dokumentet också – begreppen, parametrarna och mönstren är likadana.

CNTKTextFormatReader (senare helt enkelt CTF-läsare) är utformad för att använda textdata som är formaterade enligt specifikationen nedan. Den har stöd för följande huvudfunktioner:

  • Flera indataströmmar (indata) per fil
  • Både glesa och täta indata
  • Sekvenser med variabel längd

CNTK textformat (CTF)

Varje rad i indatafilen innehåller ett exempel för en eller flera indata. Eftersom (explicit eller implicit) varje rad också är kopplad till en sekvens, definierar den en eller <flera sekvenser, indata, exempelrelationer> . Varje indatarad måste formateras på följande sätt:

[Sequence_Id](Sample or Comment)+

var

Sample=|Input_Name (Value )*

Comment=|# some content

  • Varje rad börjar med ett sekvens-ID och innehåller ett eller flera exempel (med andra ord är varje rad en osorterad samling exempel).
  • Sekvens-ID är ett tal. Det kan utelämnas, i vilket fall radnumret används som sekvens-ID.
  • Varje exempel är i praktiken ett nyckel/värde-par som består av ett indatanamn och motsvarande värdevektor (mappning till högre dimensioner görs som en del av själva nätverket).
  • Varje exempel börjar med en pipe-symbol (|) följt av indatanamnet (inga blanksteg), följt av en avgränsare för blanksteg och sedan en lista med värden.
  • Varje värde är antingen ett tal eller ett indexprefix för glesa indata.
  • Både flikar och blanksteg kan användas synonymt som avgränsare.
  • En kommentar börjar med en pipe omedelbart följt av en hash-symbol: |#, följt av själva innehållet (brödtexten) i kommentaren. Brödtexten kan innehålla alla tecken, men en vertikalstreckssymbol i kroppen måste rymmas genom att hashsymbolen läggs till (se exemplet nedan). Brödtexten i en kommentar fortsätter till slutet av raden eller nästa icke-undantagna rör, beroende på vilket som kommer först.

Enkelt exempel

Det här exemplet baseras på en minimal uppsättning parametrar och formatalternativ.

Om du vill använda CTF-läsare anger du readerType till CNTKTextFormatReader i läsaravsnittet i CNTK konfigurationen:

...
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 ...

(Det här fragmentet och andra NDL-exempel i det här dokumentet innehåller endast reader avsnitt som utelämnar resten av CNTK konfigurationen. Se slutet av den här sidan för pekare till en uppsättning fullständiga exempelnätverk och motsvarande datauppsättningar)

CTF-läsaren kräver följande uppsättning parametrar:

  • file – sökväg till filen med datauppsättningen.
  • input– underavsnitt som definierar indata som identifieras med indatanamn (ABoch C i exemplet ovan). I varje indata måste följande obligatoriska parametrar anges:
    • format – anger indatatypen. Måste antingen vara dense eller sparse
    • dim – anger dimensionen för indatavärdesvektorn (för täta indata motsvarar detta direkt antalet värden i varje urval, för gles representerar detta den övre gränsen för intervallet med möjliga indexvärden).

Indata som motsvarar läsarkonfigurationen ovan bör se ut ungefär så här:

|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

Observera följande om indataformatet:

  • |Input_Name identifierar början av varje indataexempel. Det här elementet är obligatoriskt och följs av korrespondentvärdevektorn.
  • Tät vektor är bara en lista med flyttalsvärden; gles vektor är en lista över index:value tupplar.
  • Både flikar och blanksteg tillåts som värdeavgränsare (inom indatavektorer) samt indataavgränsare (mellan indata).
  • Varje separat rad utgör en "sekvens" av längd 1 ("Real" variabellängdssekvenser förklaras i det utökade exemplet nedan).
  • Varje indataidentifierare kan bara visas en gång på en enda rad (vilket översätts till ett exempel per indata per radkrav ).
  • Ordningen på indataexempel inom en rad är INTE viktig (konceptuellt är varje rad en osorterad samling nyckel/värde-par)
  • Varje välformulerad linje måste sluta med symbolerna "Radmatning" \n eller "Vagnretur, Linjematning" \r\n .

Utökat exempel

Det här exemplet innehåller alla möjliga konfigurationsparametrar och visar olika alternativ för indataformat. Se tabellerna nedan för en fullständig beskrivning av de konfigurationsparametrar som används i det här exemplet.

...
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 ...

Med en sammansatt läsare skulle den vilja ha följande:

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"}
            }
        })
    }

Motsvarande indatafil kan sedan se ut ungefär så här:

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

Alla alternativ som beskrivs i exemplet ovan gäller fortfarande här. Dessutom introducerade vi ytterligare två funktioner:

Alias för indatanamn

Indatanamn kan vara godtyckliga långa och därför är det inte säkert att det är utrymmeseffektivt att upprepa dem i hela indatafilen. För att undvika detta kan datauppsättningen använda "alias" i stället för fullständiga indatanamn. Alias måste sedan anges i varje underavsnitt för indata. I vårt exempel använder datauppsättningen alias a och b, som mappas till "Some_very_long_input_name" respektive "Some_other_also_very_long_input_name" i läsarkonfigurationsavsnittet.

Sekvens-ID:t

Som redan nämnts representerar varje separat rad i indatafilen en sekvens som innehåller ett enda exempel för varje indata. Men om en rad föregås av ett icke-negativt tal används talet som motsvarande sekvens-ID. Alla efterföljande rader som delar samma sekvens-ID sammanfogas för att bli en del av samma sekvens. Genom att upprepa samma numeriska prefix för N-linjer kan du därför skapa en sekvens med flera sampel, där varje indata innehåller mellan 1 och N exempel. Om du utelämnar sekvensprefixet på den andra och följande raden har samma effekt. Därför definierar exempeldatauppsättningen ovan fem sekvenser med ID: erna 100, 200, 333400 och 500.

Om parametern skipSequenceIds i läsaravsnittet anges till truetvingar det läsaren att ignorera alla explicita sekvens-ID:er i datauppsättningen och behandla separata rader som enskilda sekvenser. Om du utelämnar sekvens-ID:t på den första raden i datauppsättningen har det samma effekt – alla efterföljande sekvens-ID:er ignoreras, rader behandlas som enskilda sekvenser, som i det här exemplet:

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

Några sista saker att tänka på när du använder sekvenser:

  • Sekvens-ID:t måste vara unika.
  • ID-prefix kan bara upprepas för efterföljande rader.
  • Sekvenslängden i rader (dvs. antalet rader som delar samma ID-prefix) får inte överskrida den maximala indatalängden i prover (antalet prover i indata) i den här sekvensen.

Följande datauppsättningar är till exempel ogiltiga:

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

Några Real-World exempel

  • Klassificering: Varje rad innehåller ett exempel som består av en etikett och funktioner. Inget sekvens-ID behövs, eftersom varje rad är sin egen "sekvens" med längd 1.
|class 23:1 |features 2 3 4 5 6
|class 13:1 |features 1 2 0 2 3
...
  • DSSM: Varje rad innehåller ett dokumentpar med källmål uttryckta i en påse med ord, kodade som glesa vektorer.
|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
  • Del av taltaggning: Sekvenser mappar varje element till en motsvarande etikett. Sekvenserna justeras lodrätt (ett ord + en tagg per rad).
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
...
  • Sekvensklassificering: Sekvenser mappade till en enda etikett. Sekvenser justeras lodrätt; Etiketten "class" kan förekomma på alla rader som har samma sequenceId.

Anteckning

För tillfället får antalet rader inte överskrida längden på den längsta sekvensen. Det innebär att etiketten inte kan visas på en rad på egen hand. Detta är en implementeringsdetalj som kommer att hävas i framtiden.

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
  • Sekvens till sekvens: Mappa en källsekvens till en målsekvens. De två sekvenserna justeras lodrätt och skrivs i det enklaste fallet ut efter en annan. De ansluts genom att ha samma övergripande "sekvens-ID" (som sedan blir ett "arbetsenhets-ID" i det här fallet).

Anteckning

För tillfället får antalet rader inte överskrida längden på den längsta sekvensen. Det innebär att sekvenser måste justeras vågrätt. Detta är en implementeringsdetalj som kommer att hävas i framtiden.

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 till Rankning: En "sekvens" representerar en fråga, varje exempel på ett dokument med en handetiketterad klassificering. I det här fallet är "sekvensen" bara en multiset som (i samband med en inlärning-till-rang-förlustfunktion) inte har någon ordning.
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
...

Konfigurationsparametrar

Parameter Beskrivning
precision Anger flyttalsprecisionen (double eller float) för indatavärdena. Valfritt, standardvärdet är float.

reader Avsnitt

Parameter Beskrivning
readerType Anger en av de CNTK läsare som ska läsas in (t.ex. CNTKTextFormatReader). Krävs.
file Sökväg till filen som innehåller indatauppsättningen (Windows eller Linux-format). Krävs.
randomize Anger om indata ska randomiseras (true, false). Valfritt, standardvärdet trueär .
randomizationSeed Initialt randomiseringsvärde (inkrementellt varje svep när indata åter randomiseras). Valfritt, standardvärdet 0är .
randomizationWindow Anger storleken (positivt heltal) för randomiseringsfönstret (t.ex. randomiseringsintervall). Den här parametern påverkar hur mycket av datauppsättningen som måste finnas i minnet samtidigt. Valfritt, beroende på värdet, är standard antingen storleken på sampleBasedRandomizationWindow hela datamängden i exempel (dvs. indata randomiseras över hela datauppsättningen) eller 4 GB diskutrymme med segment (dvs. 128 när segmentstorleken är lika med 32 MB). Den här parametern ignoreras när randomize är false.
sampleBasedRandomizationWindow Om truetolkas storleken på randomiseringsfönstret som ett visst antal exempel, annars – som ett antal segment. Valfritt, standardvärdet falseär . randomizationWindowPå samma sätt ignoreras den här parametern när randomize är false.
skipSequenceIds Om trueignorerar läsaren sekvens-ID:t i indatafilen och tolkar varje separat rad som en oberoende sekvens av storlek 1 (se avsnittet om sekvens-ID:t). Valfritt, standardvärdet falseär .
maxErrors Antal indatafel varefter ett undantag ska aktiveras. Valfritt, standardvärdet 0är , vilket innebär att det första felaktiga värdet utlöser ett undantag.
traceLevel Utdataverositetsnivå. 0 – visa endast fel. 1 – visa fel och varningar. 2 – visa alla utdata. Valfritt, standardvärdet 1är .
chunkSizeInBytes Antal på varandra följande byte som ska läsas från disken i en enda läsåtgärd. Valfritt, standardvärdet 33554432 (32 MB).
keepDataInMemory Om truecachelagras hela datauppsättningen i minnet. Valfritt, standardvärdet falseär .
frameMode true signalerar läsaren att använda en förpackningsmetod som är optimerad för ramar (sekvenser som bara innehåller ett enda exempel). Valfritt, standardvärdet falseär .
cacheIndex Anger om metadata som skapats under förbearbetningssteget ska skrivas ut till disken och läsas in från disken om det är tillgängligt (true, false). Valfritt, standardvärdet falseär . Mer information finns i avsnittet nedan. Nytt i CNTK version 2.1.
Cachelagring av index

Anteckning

Nytt i CNTK version 2.1.

Indexcachelagring gör det möjligt att avsevärt (med en faktor på 2–3 x) minska starttiden, särskilt när du arbetar med stora indatafiler. cacheIndex Om du anger flaggan till true kommer läsaren att skriva indexeringsmetadata till disk (samma katalog som indatafilen) om cachefilen inte är tillgänglig eller om den är inaktuell (äldre än indatafilen). Skrivandet är bäst och utförs på en separat tråd för att inte påverka läsarens prestanda. Om cachefilen finns och är uppdaterad kommer läsaren inte längre att skumma indatafilen för att skapa indexet. I stället läses indexet in från cachefilen. Observera att vissa konfigurationsparametrar för läsare har en direkt inverkan på indexering (till exempel kan olika värden frameMode för potentiellt resultera i index som har olika antal sekvenser). Därför kan en cachefil ignoreras av en läsare med en annan konfiguration än den som skapade cachen. Om du vill se den fullständiga fördelen med cachelagring bör konfigurationen inte ändras vid efterföljande omkörningar.

input underavsnitt

input kombinerar ett antal enskilda indata, var och en med ett lämpligt underavsnitt för konfiguration. Alla parametrar som beskrivs nedan är specifika för ett underavsnitt för indatanamn som är associerat med en viss indata.

Parameter Beskrivning
alias Ett alternativt kortnamn (sträng) som används för att identifiera indata i datauppsättningen. Valfritt
format Anger indatatyp (dense, sparse). Krävs.
dim Dimension (positivt heltal) för indatavärdet (dvs. antalet indatavärden i ett exempel för tät indata, den övre gränsen för indexintervallet för glesa indata). Krävs.
definesMBSize Flagga (standard falskt) som anger om minibatchstorleken ska räknas i exempel från den här dataströmmen Valfri.

Du hittar fullständiga nätverksdefinitioner och motsvarande datauppsättningsexempel i CNTK-lagringsplatsen. Där hittar du också ett slutpunkt-till-slutpunkt-test som använder CNTKTextFormat-läsaren.