Sdílet prostřednictvím


BrainScript a Python: Principy a rozšíření čtenářů

Od verze 1.5 se CNTK přesouvá od monolitického návrhu čtečky směrem k kompozovatelnému modelu, který umožňuje zadat a vytvářet vstupní data různých formátů.

Před každým čtenářem zodpovídá za různé aspekty čtení dat, mimo jiné:

  • Deserializace dat z externího úložiště do reprezentace v paměti
  • Randomizace celého korpusu
  • Různé transformace vstupních sekvencí/ukázek (tj. oříznutí nebo škálování obrázků)
  • Vytvoření minibatch pro různé režimy (tj. rám, posloupnost nebo zkrácený BPTT) s rozložením, které může gpu využívat
  • Předběžné načtení na úrovni minibatch a vstupně-výstupních bloků dat

Ve verzi 1.5 byly hlavní části výše uvedené funkce zohledněny a přesunuty do jádra CNTK, které se mají sdílet mezi různými čtenáři. Tato verze také zavádí dvě hlavní abstrakce, které je možné rozšířit, aby podporovaly nové formáty dat:

  • deserializátor - zodpovídá za deserializaci vstupu z externího úložiště do sekvencí v paměti.
  • transformace – transformuje vstupní sekvenci na výstupní sekvenci.

V dalších částech probereme tyto abstrakce podrobněji.

Konfigurace čtečky (zdroj minibatch) v Pythonu

Tato část obsahuje několik příkladů konfigurace složené čtečky (neboli MinibatchSource) v Pythonu.

Následující příklad byl upraven z AlexNet_ImageNet_Distributed.py, ukazuje ekvivalent Pythonu čtečky AlexNet z části Transformace .

import cntk.io

mean_file = ...
map_file = ...

# model dimensions
image_height = 227
image_width  = 227
num_channels = 3  # RGB
num_classes  = 1000

transforms = [
     ImageDeserializer.crop(crop_type='randomside', 
                            side_ratio=0.88671875, 
                            jitter_type='uniratio'),
     ImageDeserializer.scale(width=image_width, 
                            height=image_height, 
                            channels=num_channels, 
                            interpolations='linear'),
     ImageDeserializer.mean(mean_file)
]

reader = MinibatchSource(
    ImageDeserializer(map_file, StreamDefs(
        # first column in map file is referred to as 'image'
        features = StreamDef(field='image', transforms=transforms),
        # and second as 'label' 
        labels   = StreamDef(field='label', shape=num_classes)))) 

Následující příklad (přizpůsobený z A2_RunCntk_py3.py) ukazuje, jak se dá zkombinovat několik deserializérů.

n_rois = 100
n_classes = 17
rois_dim = 4 * n_rois
label_dim = n_classes * n_rois

map_file = ...
roi_file = ...
label_file = ...

# read images
scale = ImageDeserializer.scale(width=1000, 
                                height=1000, 
                                channels=3,
                                scale_mode="pad", 
                                pad_value=114, 
                                interpolations='linear')
image_source = ImageDeserializer(map_file)
image_source.ignore_labels()
image_source.map_features('features', [scale])

# read rois and labels
roi_source = CTFDeserializer(roi_file)
roi_source.map_input('rois', dim=rois_dim, format="dense")
label_source = CTFDeserializer(label_file)
label_source.map_input('roiLabels', dim=label_dim, format="dense")

# define a composite reader
reader = MinibatchSource([image_source, roi_source, label_source])

...

# define mapping from reader streams to network inputs
input_map = {
    image_input: reader.streams.features,
    roi_input: reader.streams.rois,
    label_input: reader.streams.roiLabels
}

BrainScript

Deserializers

Pojďme se podívat na následující fragment konfigurace pro HTKMLFReader z kompletního testu LSTM/FullUtterance ( úplná konfigurace zde):

...
# Old reader config. For illustration only.
reader = [
    readerType = "HTKMLFReader"
    readMethod = "blockRandomize"
    nbruttsineachrecurrentiter = 32
    randomize = "auto"
    verbosity = 0

    features = [
        dim = 363
        type = "real"
        scpFile = "$DataDir$/glob_0000.scp"
    ]

    labels = [
        mlfFile = "$DataDir$/glob_0000.mlf"
        labelMappingFile = "$DataDir$/state.list"

        labelDim = 132
        labelType = "category"
    ]
]

Tento fragment konfigurace deklaruje čtenáře, který vytváří dva datové proudy s názvy "features" a "labels". Přebírá jako vstup dva typy souborů:

  • seznam souborů funkcí známých v analyzátoru HTK jako scp soubor ("skript" soubor)
  • soubor popisku známý jako mlf soubor ("hlavní soubor popisku")

Ve výše uvedeném fragmentu konfigurace neexistují žádné explicitní entity, které by definovaly způsob scp deserializace formátů mlf . Všechno je zapouzdřené v konfiguraci HTKMLFReader . Takže pokud potřebujete zveřejnit další vstupní stream různých formátů dat společně s scp a mlf, budete muset změnit HTKMLFReader a přidat podporu tam.

Pokud chcete zvýšit kompozitnost a opakované použití, nová konfigurace pro stejný vstup explicitně definuje deserializátory a vstupní datové proudy, které vytvářejí:

reader = [
    verbosity = 0
    randomize = true

    # A list of deserializers the reader uses.
    deserializers = (
        [
            # Type of deserializer, in this case the one that knows
            # how to deserialize HTK feature files.
            type = "HTKFeatureDeserializer"
            # Module (.dll or .so) where this deserializer is implemented
            module = "HTKDeserializers"

            # Description of input streams the deserializer provides,
            # can be one or many, depending on a particular
            # deserializer implementation
            # For HTKFeatureDeserializer, just one stream can be described.
            input = [
                # Description of input stream to feed the Input node named "features"
                features = [
                    dim = 363
                    scpFile = "$DataDir$/glob_0000.scp"
                ]
            ]
        ]:
        [
            # Type of deserializer, in this case the one
            # that knows how to deserialize mlf files.
            type = "HTKMLFDeserializer"
            module = "HTKDeserializers"
            # Description of input streams the deserializer provides,
            # For HTKMLFDeserializer, just one stream can be described.
            input = [
                # Description of input stream to feed the Input node named "labels"
                labels = [
                    dim = 132
                    mlfFile = "$DataDir$/glob_0000.mlf"
                    labelMappingFile = "$DataDir$/state.list"
                    # whether phone boundary information should be encoded
                    # set to true in CTC-type training
                    phoneBoundaries=false
                ]
            ]
        ]
    )
]

Sekvence vytvořené mlf a htk deserializery se zkombinují na základě jejich logického klíče (což je řetězec, který jednoznačně identifikuje řečovou promluvu a nachází se v obou scp i mlf souborech). Pokud potřebujete další datový proud jiného formátu, můžete jednoduše přidat odpovídající deserializátor do konfigurace (není to možné s funkcí HTK a HTK MLF deserializery právě teď zpřístupnit více než jeden vstupní stream každý).

Poznámka

V současné době se podporují staré i nové konfigurace čtečky. Při použití klíče deserializers v konfiguraci čtečky je typ čtečky implicitně nastaven na "CompositeDataReader". Chcete-li zajistit, aby byl modul CompositeDataReader načten ve Windows, Cntk.Composite.dll měl by být umístěn ve stejném adresáři jako spustitelný soubor CNTK. V Linuxu Cntk.Composite.solib by měl být ve složce, která se nachází vedle bin složky obsahující spustitelný soubor CNTK.

V současné době CNTK podporuje následující deserializátory:

Typ deserializátoru Modul Description
HTKFeatureDeserializer HTKDeserializers Deserializer pro soubory funkcí HTK
HTKMLFDeserializer HTKDeserializers Deserializer pro soubory HTK MLF
ImageDeserializer ImageReader Deserializátor pro obrázky kódované jako prosté soubory nebo v archivu zip.
Base64ImageDeserializer ImageReader Deserializer pro obrázky kódované jako řetězce base64 v souboru mapování.
CNTKTextFormatDeserializer CNTKTextFormatReader Deserializer pro soubory textového formátu CNTK
CNTKBinaryFormatDeserializer CNTKBinaryReader Deserializer pro soubory binárního formátu CNTK

Úplný popis parametrů konfigurace najdete v následujících tabulkách.

Transformace

Transformace je jednoduchá abstrakce, která vezme posloupnost jako vstup, provede některé transformace ukázek v sekvenci a vrátí výstupní sekvenci. Typické příklady transformací jsou různé transformace obrázků, jako jsou oříznutí, měřítko nebo transponace. Transformace je možné nakonfigurovat na základě vstupu.

Pojďme se podívat, jak se dají transformace použít na vstup (konfigurace se používá z testu Tests/EndToEndTests/Image/AlexNet ):

deserializers = ([
    type = "ImageDeserializer"
    module = "ImageReader"

    # Map file which maps images to labels
    file = "$ConfigDir$/train_map.txt"

    # Description of input streams
    input = [
            # Description of input stream to feed the Input node named "features"
            features = [
                transforms = (
                    [
                        type = "Crop"
                        # Possible values: Center, RandomSide, RandomArea, Multiview10. Default: Center
                        cropType = "RandomSide"
                        # Crop scale side ratio.
                        sideRatio = 0.875
                        # Crop scale ratio jitter type
                        jitterType = "UniRatio"
                    ]:[
                        type = "Scale"
                        width = 224
                        height = 224
                        channels = 3
                        # Interpolation to use when scaling image to width x height size.
                        interpolations = "linear"
                    ]:[
                        type = "Mean"
                        # Stores mean values for each pixel in OpenCV matrix XML format.
                        meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
                    ]:[
                        # Changes the image layout from HWC to CHW
                        type = "Transpose"
                    ]
                )
            ]
            # Description of input stream to feed the Input node named "labels"
            labels = [
                labelDim = 1000
            ]
        ]
    ]
])

V této konfiguraci se na vstupní datový proud featurespoužijí čtyři transformace . Zpočátku deserializátor dat obrázku vytváří sekvence skládající se z jednoho obrázku v reprezentaci HWC. Potom se na obrázek použije seřazený seznam transformací: nejprve transformace Oříznutí následovaný měřítkem a průměrem. Poslední transformací je Transpozice , která změní rozložení obrázku z HWC na CHW.

V současné době se implementují následující transformace. Podrobný popis naleznete v tématu ImageReader.

Typ transformace Modul
Oříznout ImageReader
Měřítko ImageReader
Barva ImageReader
Mean ImageReader
Transponovat ImageReader

Popis nového formátu konfigurace čtečky

Oddíl konfigurace čtenáře, který vytvoří několik deserializérů dat, vypadá takto:

reader = [
    randomize = true|false
    verbosity = 0|1|2
    ...

    deserializers = (
        [<deserializerConfiguration1>]:
        [<deserializerConfiguration2>]:
        ...
        [<deserializerConfigurationN>]
    )
]

Každá konfigurace deserializátoru je zadána takto:

[
    module = "<readerModuleName>"   # Name of the external module (.dll or .so) where this particular deserializer is implemented
    type = "<deserializerType>"     # The type of the deserializer

    # There could be more deserializer-specific options in this section

    # Date deserializer input - describes a set of streams this deserializer produces.
    # It can be one (as in HTK) or many (as in CNTKTextFormat)
    input = [
        # Replace 'InputNameN' by the name of the corresponding input node in the network.
        InputName1 = [<inputConfiguration>]
        InputName2 = [<inputConfiguration>]
        ...
    ]
]

Vstupní konfigurace obsahuje možnosti specifické pro vstup a volitelně uspořádaný seznam transformací, které by se měly použít pro vstup:

[
    # Per-input data deserializer-specific options

    # Optionally a pipeline of transformations, to be implemented by data deserializer's reader module:
    transforms = (
       [<transformationConfiguration1>]:
       [<transformationConfiguration2>]:
       ...
       [<transformationConfigurationN>]
    )
]

Konfigurace transformace identifikuje typ transformace a všechny možnosti specifické pro transformaci:

[
    type = "<transformName>"
    # Transform-specific options
]

Možnosti konfigurace

Obecná konfigurace čtečky

Parametr Popis
verbosity Úroveň podrobností (0, 1, 2), řídí diagnostický výstup různých komponent (Randomizer, Deserializer, Bundler atd.) Volitelné, výchozí hodnota je 0.
randomize Určuje, zda má být vstup randomizován ( true, false). Metoda randomizace je stejná jako blockRandomize HTKMLFReader. Volitelné, výchozí hodnota je true.
randomizationSeed Počáteční hodnota seed randomizace (zvýší se při opětovném náhodném přemíscení vstupních dat). Volitelné, výchozí hodnota je 0.
randomizationWindow Určuje velikost (kladné celé číslo) okna randomizace (tj. rozsah randomizace). Tento parametr ovlivňuje, kolik datové sady se musí najednou nacházet v paměti. Volitelné, výchozí hodnota je velikost celé datové sady (v ukázkách nebo v blocích v závislosti na sampleBasedRandomizationWindow hodnotě). Pokud je CNTKTextFormatDeserializer ale jeden z deserializerů a sampleBasedRandomizationWindownebyl explicitně nastaven na true, randomizationWindow ve výchozím nastavení se nastaví 128 (což je přibližně 4 GB místa na disku, které stojí za bloky dat). Tento parametr je ignorován, pokud randomize je false.
sampleBasedRandomizationWindow Pokud trueje velikost okna randomizace interpretována jako určitý počet vzorků a jako počet bloků jinak. Volitelné, výchozí nastavení true , pokud CNTKTextFormatDeserializer není v seznamu deserializerů, a jinak false . Podobně jako randomizationWindowtento parametr je ignorován, pokud randomize je false.
truncationLength Určuje délku zkrácení ve vzorcích pro BPTT (kladné celé číslo). Povinné pouze v případě, že truncated je true, ignorováno jinak.
multiThreadedDeserialization Určuje, jestli se má použít více vláken při shromažďování sekvencí pro minibatch z deserializerů (true, false). Volitelné.
frameMode Určuje, jestli mají být data randomizována a vrácena na úrovni rámce nebo sekvence. Když truese vstupní sekvence rozdělí na rámce. Volitelné. Obě frameMode a truncated nesmí být nastaveny na true stejnou dobu.
truncated Když truepovolí zkrácení zpětného šíření v čase (BPTT). Volitelné. Obě frameMode a truncated nesmí být nastaveny na true stejnou dobu.
useNumericSequenceKeys Klíče posloupnosti slouží ke korelaci sekvencí mezi různými deserializery. U některých deserializerů (tj. HTK a MLF) jsou klíče sekvence libovolnými řetězci. Ukládání je vyžaduje hodně paměti na velkém korpusu. Pokud máte jistotu, že jsou klíče sekvence číselné, nastavte tento parametr na true, v takovém případě se všechny řetězce klíče převedou na celá čísla, která snižují zatížení paměti. Volitelné, výchozí false.
hashSequenceKeys Z výše popsaných důvodů paměti mohou být klíče řetězců také hashovány nastavením tohoto parametru na true. Použijte ho pouze pro deserializery, které podporují klíče sekvence řetězců (HTK, MLF). Volitelné, výchozí false.
cacheIndex Určuje, zda by se meta-data vytvořená během fáze předběžného zpracování měla zapsat na disk a načíst je z disku, pokud je k dispozici (true, false). Volitelné, výchozí hodnoty .false Další podrobnosti najdete v následující části. Novinka v CNTK verze 2.1.
Ukládání indexů do mezipaměti

Poznámka

Novinka v CNTK verze 2.1.

Ukládání indexů do mezipaměti umožňuje výrazně (faktorem 2–3x) snížit časy spuštění, zejména při práci s velkými vstupními soubory. Pokud soubor mezipaměti není dostupný nebo pokud není soubor mezipaměti zastaralý (starší než vstupní soubor), nastavíte cacheIndex příznak tak, aby true čtečka signalizovala zápis meta-dat na disk (stejný adresář jako vstupní soubor). Psaní je nejlepší a provádí se na samostatném vlákně, aby to nemělo vliv na výkon čtenáře. Pokud soubor mezipaměti existuje a je aktuální, čtečka už nebude přeskočovat vstupní soubor k sestavení indexu, místo toho index načte ze souboru mezipaměti. Upozorňujeme, že některé parametry konfigurace čtenáře mají přímý dopad na indexování (například různé hodnoty frameMode by mohly vést k indexům, které mají různý počet sekvencí). Z tohoto důvodu může soubor mezipaměti ignorovat čtenář s konfigurací jinou než ten, který mezipaměť vytvořil. Pokud chcete zobrazit úplnou výhodu ukládání do mezipaměti, konfigurace by se neměla upravovat při následných opakovaných spuštěních.

cacheIndex nemá žádný vliv na ImageDeserializer a CNTKBinaryFormatDeserializer, protože bývalý neindexuje vstupní data a později obsahuje informace o indexu vložené do samotného formátu.

Obecná konfigurace deserializátoru

Parametr Popis
module Určuje název modulu čtenáře, který implementuje deserializátor dat. Povinné.
type Určuje název deserializátoru dat vystavený daným modulem čtenáře. Povinné.

Obecná konfigurace transformace

Parametr Popis
type Určuje název transformace vystavený modulem čtenáře, který implementuje deserializátor dat. Povinné.

Možnosti HTKFeatureDeserializer

Parametr Popis
scpFile Seznam cest k souborům SCP, které se mají zpracovat. Soubory by měly být kompatibilní se soubory HTK a musí být zadány ve formátu "archiv". Podrobnosti použití archivu jsou popsány v nástroji HTKMLF Reader. Povinné.
dim Celé číslo, které určuje úplnou dimenzi vektoru funkce s požadovaným kontextovým oknem. 1Povinné
contextWindow Je možné zadat buď jako dvojici kladných celých čísel, nebo jako jedno kladné celé číslo (v takovém případě se interpretuje jako pár se stejným číslem, který se opakuje dvakrát). Určuje velikost vlevo a vpravo (první a druhé celé číslo páru) kontextového okna v ukázkách. Volitelné, výchozí hodnoty .1
prefixPathInSCP Řetězec předpony, který se má použít u cest zadaných v souborech SCP. Volitelné.

1 Pokud jste například měli 72rozměrné funkce (24rozměrné funkce filterbank plus rozdílové a rozdílové koeficienty) a síť je navržená tak, aby zpracovávala kontextové okno s 11 snímky, zadaný rozměr by měl být 792.

Možnosti HTKMLFDeserializer

Parametr Popis
mlfFile Cesta k souboru stylu mlf HTK, který obsahuje popisky všech promluv zadaných v scp souborech. Povinné , pokud mlfFileList není zadáno.
mlfFileList Pole cest k souborům ve stylu mlf HTK, které obsahují popisky pro všechny promluvy zadané v scp souborech. Povinné , pokud mlfFile není zadáno.
dim Celková kardinalita sady popisků (kladné celé číslo). Povinné.
labelMappingFile Cesta k souboru, který obsahuje všechny popisky zobrazené v mlf souboru, jeden na řádek. Povinné.

labelDim se dá použít jako synonymum pro dim.

Možnosti CNTKTextFormatDeserializer

Stejné možnosti, které lze použít s CNTKTextFormatReader

Možnosti imageDeserializátoru

  • file: jednoduchý textový soubor, ve kterém každý řádek obsahuje mapování oddělené tabulátorem mezi logickým klíčem sekvence, souborem obrázku (např. JPEG, PNG atd.) a 0 popiskem.

Další informace naleznete v tématu ImageReader.

Možnosti base64ImageDeserializer

Tento deserializátor podporuje stejné možnosti, které lze použít s ImageDeserializer. Jediný rozdíl je ve formátu souboru mapování:

  • file: Jednoduchý textový soubor, kde každý řádek obsahuje mapování oddělené tabulátorem mezi logickým klíčem sekvence (volitelné, lze vynechat), popisek kategorie 0 a základní soubor obrázku s kódováním 64 (např. JPEG, PNG atd.).

Příklady konfigurací a testů

V úložišti CNTK najdete kompletní definice sítě a odpovídající příklady sady dat. Najdete zde také testy jednotek a end-to-end, které používají deserializery, tj.