BrainScript e Python: Informazioni ed estensione dei lettori
A partire dalla versione 1.5, CNTK si allontana dalla progettazione del lettore monolitico verso un modello più componibile che consente di specificare e comporre dati di input di formati diversi.
In precedenza, ogni lettore era responsabile di diversi aspetti della lettura dei dati, tra cui, a titolo esemplificativo:
- Deserializzazione dei dati dall'archiviazione esterna nella rappresentazione in memoria
- Randomizzazione dell'intero corpus
- Trasformazioni diverse di sequenze/campioni di input (ad esempio ritaglio o ridimensionamento delle immagini)
- Creazione di minibatches per diverse modalità (ad esempio frame, sequenza o troncato BPTT) con un layout che può essere utilizzato dalla GPU
- Prelettura sul livello di minibatches e blocchi di I/O
Nella versione 1.5, i componenti principali della funzionalità precedente sono stati inseriti in fattori e spostati in CNTK core per essere condivisi tra lettori diversi. Questa versione introduce anche due astrazioni principali che possono essere estese per supportare nuovi formati di dati:
- deserializzatore: è responsabile della deserializzazione dell'input dall'archiviazione esterna in sequenze in memoria
- trasformare: trasforma una sequenza di input in una sequenza di output
Nelle sezioni successive queste astrazioni vengono illustrate in modo più dettagliato.
Configurazione di un lettore (origine minibatch) in Python
Questa sezione fornisce diversi esempi su come è possibile configurare un lettore composito (noto anche come MinibatchSource) in Python.
L'esempio seguente è stato adattato da AlexNet_ImageNet_Distributed.py, mostra l'equivalente Python del lettore AlexNet dalla sezione Transforms.
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))))
Nell'esempio seguente (adattato da A2_RunCntk_py3.py) viene illustrato come combinare diversi deserializzatori.
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
Deserializzatori
Di seguito è riportato il frammento di configurazione seguente per il HTKMLFReader
...
# 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"
]
]
Questo frammento di configurazione dichiara un lettore che produce due flussi di dati con nomi "features"
e "labels"
. Accetta come input due tipi di file:
- un elenco di file di funzionalità noti in HTK parlance come file
scp
("file script") - un file di etichetta noto come file di
mlf
("file etichetta master")
Nel frammento di configurazione precedente non sono presenti entità esplicite che definiscono come scp
o mlf
formati vengono deserializzati.
Tutto è incapsulato nella configurazione di HTKMLFReader scp
e mlf
, è necessario modificare HTKMLFReader e aggiungere il supporto.
Per aumentare la componibilità e il riutilizzo, la nuova configurazione di per lo stesso input definisce in modo esplicito i deserializzatori e i flussi di input che producono:
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
]
]
]
)
]
Le sequenze prodotte dall'mlf
e htk
deserializer vengono combinate in base alla relativa chiave logica (ovvero una stringa che identifica in modo univoco un'espressione vocale ed è presente sia in scp
che nei file di mlf
).
Quando è necessario un altro flusso di formato diverso, è sufficiente aggiungere il deserializzatore corrispondente alla configurazione (non è possibile con la funzionalità HTK e i deserializzatori MLF HTK in questo momento per esporre più di un flusso di input ciascuno).
Nota
Attualmente sono supportate entrambe le configurazioni dei lettori precedenti e nuove. Quando la chiave "deserializers" viene usata nella configurazione del lettore, il tipo di lettore viene impostato in modo implicito su "CompositeDataReader". Per assicurarsi che il modulo CompositeDataReader possa essere caricato in Windows, il Cntk.Composite.dll
deve trovarsi nella stessa directory dell'eseguibile CNTK. In Linux Cntk.Composite.so
deve trovarsi nella cartella lib
affiancata alla cartella bin
contenente l'eseguibile CNTK.
Attualmente CNTK supporta i deserializzatori seguenti:
Tipo deserializzatore | Modulo | Descrizione |
---|---|---|
HTKFeatureDeserializer | HTKDeserializers | Deserializzatore per i file di funzionalità HTK |
HTKMLFDeserializer | HTKDeserializers | Deserializzatore per i file MLF HTK |
ImageDeserializer | ImageReader | Deserializzatore per le immagini codificate come file semplici o in archivio ZIP. |
Base64ImageDeserializer | ImageReader | Deserializzatore per le immagini codificate come stringhe base64 nel file di mapping. |
CNTKTextFormatDeserializer | CNTKTextFormatReader | Deserializzatore per i file di formato di testo CNTK |
CNTKBinaryFormatDeserializer | CNTKBinaryReader | Deserializzatore per i file in formato binario CNTK |
Per la descrizione completa dei parametri di configurazione, vedere le tabelle seguenti.
Trasforma
Una trasformazione è una semplice astrazione che accetta una sequenza come input, esegue alcune trasformazioni di campioni nella sequenza e restituisce la sequenza di output. Esempi tipici di trasformazioni sono trasformazioni diverse di immagini, ad esempio ritaglio, scala o trasposizione. Le trasformazioni possono essere configurate in base all'input.
Di seguito viene illustrato come applicare le trasformazioni all'input (la configurazione viene ricavata dal test Test/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
]
]
]
])
In questa configurazione vengono applicate quattro trasformazioni al flusso di input features
.
Inizialmente, il deserializzatore di dati immagine produce sequenze costituite da una singola immagine nella rappresentazione HWC.
Dopo che l'elenco ordinato di trasformazioni viene applicato all'immagine: in primo luogo la trasformazione ritaglio
Attualmente vengono implementate le trasformazioni seguenti. Per la descrizione dettagliata, vedere ImageReader.
Tipo di trasformazione | Modulo |
---|---|
Raccolto | ImageReader |
Scala | ImageReader |
Colore | ImageReader |
Significare | ImageReader |
Trasporre | ImageReader |
Nuova descrizione del formato di configurazione lettore
Una sezione di configurazione del lettore per comporre diversi deserializzatori di dati è simile alla seguente:
reader = [
randomize = true|false
verbosity = 0|1|2
...
deserializers = (
[<deserializerConfiguration1>]:
[<deserializerConfiguration2>]:
...
[<deserializerConfigurationN>]
)
]
Ogni configurazione deserializzatore viene specificata come:
[
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>]
...
]
]
Una configurazione di input contiene opzioni specifiche dell'input e, facoltativamente, un elenco ordinato di trasformazioni che devono essere applicate all'input:
[
# Per-input data deserializer-specific options
# Optionally a pipeline of transformations, to be implemented by data deserializer's reader module:
transforms = (
[<transformationConfiguration1>]:
[<transformationConfiguration2>]:
...
[<transformationConfigurationN>]
)
]
La configurazione della trasformazione identifica il tipo di trasformazione e le opzioni specifiche della trasformazione:
[
type = "<transformName>"
# Transform-specific options
]
Opzioni di configurazione
Configurazione del lettore generale
Parametro | Descrizione |
---|---|
verbosity |
Livello di dettaglio (0 , 1 , 2 ), controlla l'output diagnostico di componenti diversi (Randomizer, Deserializer, Bundler e così via) Facoltativo, per impostazione predefinita 0 . |
randomize |
Specifica se l'input deve essere casuale ( true , false ). Il metodo di randomizzazione è identico a blockRandomize di HTKMLFReader.
Facoltativo, per impostazione predefinita true . |
randomizationSeed |
Valore di inizializzazione casuale (incrementato ogni sweep quando i dati di input vengono ri-casualizzati).
Facoltativo, per impostazione predefinita 0 . |
randomizationWindow |
Specifica le dimensioni (numero intero positivo) della finestra di casualizzazione (ad esempio, intervallo di casualizzazione). Questo parametro influisce sulla quantità di set di dati che deve risiedere in memoria contemporaneamente. CNTKTextFormatDeserializer e sampleBasedRandomizationWindow non è stato non impostato in modo esplicito su true , randomizationWindow verrà impostato per impostazione predefinita su 128 (ovvero circa 4 GB di spazio su disco di blocchi). Questo parametro viene ignorato quando randomize è false . |
sampleBasedRandomizationWindow |
Se true , le dimensioni della finestra di casualizzazione sono interpretate come un determinato numero di campioni e come numero di blocchi in caso contrario.
Facoltativo, per impostazione predefinita true se CNTKTextFormatDeserializer non è presente nell'elenco di deserializer e per false in caso contrario. Analogamente a randomizationWindow , questo parametro viene ignorato quando randomize è false . |
truncationLength |
Specifica la lunghezza del troncamento nei campioni per BPTT (numero intero positivo).
obbligatorio solo se truncated è true , ignorato in caso contrario. |
multiThreadedDeserialization |
Specifica se devono essere usati più thread durante la raccolta di sequenze per un minibatch dai deserializzatori (true , false ).
facoltativo . |
frameMode |
Specifica se i dati devono essere casuali e restituiti a livello di frame o sequenza. Quando true , la sequenza di input viene suddivisa in fotogrammi.
facoltativo . Non è possibile impostare sia frameMode che truncated su true contemporaneamente. |
truncated |
Quando true , abilita la propagazione back-end troncata nel tempo (BPTT).
facoltativo . Non è possibile impostare sia frameMode che truncated su true contemporaneamente. |
useNumericSequenceKeys |
Le chiavi di sequenza vengono usate per correlare le sequenze tra deserializzatori diversi. Per alcuni deserializzatori (ad esempio HTK e MLF), le chiavi di sequenza sono stringhe arbitrarie. L'archiviazione richiede molta memoria su grandi corpus. Se si è certi che le chiavi di sequenza siano numeriche, impostare questo parametro su true, in tal caso tutte le chiavi stringa verranno convertite in numeri interi che riducono la pressione di memoria.
Facoltativo, impostazione predefinita false . |
hashSequenceKeys |
Per i motivi di memoria descritti in precedenza, è anche possibile eseguire l'hashing delle chiavi stringa impostando questo parametro su true. Usare solo per deserializzatori che supportano chiavi di sequenza di stringhe (HTK, MLF).
Facoltativo, impostazione predefinita false . |
cacheIndex |
Specifica se i metadati compilati durante la fase di pre-elaborazione devono essere scritti su disco e caricati dal disco, se disponibili (true , false ).
Facoltativo, per impostazione predefinita false . Per altri dettagli, vedere la sezione seguente.
Novità in CNTK versione 2.1. |
Memorizzazione nella cache degli indici
Nota
Novità di CNTK versione 2.1.
La memorizzazione nella cache degli indici consente di ridurre significativamente (per un fattore di 2-3 volte) i tempi di avvio, soprattutto quando si lavora con file di input di grandi dimensioni. L'impostazione del flag cacheIndex
su true
segnalerà al lettore di scrivere i metadati di indicizzazione su disco (stessa directory del file di input) se il file della cache non è disponibile o se è obsoleto (precedente al file di input). La scrittura è il miglior sforzo e viene eseguita su un thread separato per non influire sulle prestazioni del lettore. Se il file della cache è presente ed è up-to-date, il lettore non scaricherà più il file di input per compilare l'indice, ma caricherà l'indice dal file della cache. Si noti che alcuni parametri di configurazione del lettore hanno un impatto diretto sull'indicizzazione (ad esempio, valori diversi di frameMode
potrebbero causare indici con un numero diverso di sequenze). Per questo motivo, un file di cache potrebbe essere ignorato da un lettore con una configurazione diversa da quella che ha generato la cache. Per visualizzare il vantaggio completo della memorizzazione nella cache, la configurazione non deve essere modificata nelle riesecuzioni successive.
cacheIndex
non ha alcun effetto su ImageDeserializer e CNTKBinaryFormatDeserializer, perché il primo non indicizza i dati di input e successivamente include le informazioni sull'indice incorporate nel formato stesso.
Configurazione generale del deserializzatore
Parametro | Descrizione |
---|---|
module |
Specifica il nome del modulo lettore che implementa il deserializzatore di dati. obbligatorio. |
type |
Specifica un nome di deserializzatore dati esposto dal modulo lettore specificato. obbligatorio. |
Configurazione della trasformazione generale
Parametro | Descrizione |
---|---|
type |
Specifica un nome di trasformazione esposto dal modulo reader che implementa il deserializzatore di dati. obbligatorio. |
Opzioni HTKFeatureDeserializer
Parametro | Descrizione |
---|---|
scpFile |
Elenco dei percorsi dei file SCP da elaborare. I file devono essere compatibili con HTK e devono essere specificati nel formato "archivio". I dettagli dell'uso di un archivio sono descritti in lettore HTKMLF. obbligatorio. |
dim |
Intero che specifica la dimensione del vettore di funzionalità completa con la finestra di contesto desiderata.1obbligatorio |
contextWindow |
Può essere specificato come coppia di numeri interi positivi o come singolo numero intero positivo (nel qual caso viene interpretato come coppia con lo stesso numero ripetuto due volte). Specifica le dimensioni sinistra e destra (primo e secondo intero della coppia) della finestra di contesto negli esempi.
Facoltativo, per impostazione predefinita 1 . |
prefixPathInSCP |
Stringa di prefisso da applicare ai percorsi specificati all'interno dei file SCP. facoltativo . |
1 Ad esempio, se si dispone di caratteristiche 72 dimensionali (caratteristiche di filtro 24 dimensionali più coefficienti delta e delta-delta) e la rete è progettata per elaborare una finestra di contesto di 11 fotogrammi, la dimensione specificata deve essere 792.
Opzioni di HTKMLFDeserializer
Parametro | Descrizione |
---|---|
mlfFile |
Percorso di un file di mlf di tipo HTK che contiene le etichette per tutte le espressioni specificate nei file di scp .
obbligatorio se non è specificato mlfFileList . |
mlfFileList |
Matrice di percorsi di file di mlf in stile HTK che contiene le etichette per tutte le espressioni specificate nei file di scp .
obbligatorio se non è specificato mlfFile . |
dim |
Cardinalità totale del set di etichette (numero intero positivo). obbligatorio. |
labelMappingFile |
Percorso di un file che elenca tutte le etichette visualizzate nel file mlf , una per riga.
obbligatorio. |
labelDim può essere usato come sinonimo dim.
Opzioni CNTKTextFormatDeserializer
Stesse opzioni che possono essere usate con CNTKTextFormatReader
Opzioni imageDeserializer
-
file
: file di testo semplice in cui ogni riga contiene un mapping separato da tabulazioni tra chiave di sequenza logica, file di immagine (e.g. JPEG, PNG e così via) e etichetta basata su 0.
Per altre informazioni, vedere ImageReader.
Opzioni base64ImageDeserializer
Questo deserializzatore supporta le stesse opzioni che possono essere usate con ImageDeserializer. L'unica differenza è nel formato del file di mapping:
-
file
: file di testo semplice in cui ogni riga contiene un mapping delimitato da tabulazioni tra la chiave di sequenza logica (facoltativa, può essere omessa), l'etichetta di categoria basata su 0 e il file di immagine con codifica base 64 (e.g. JPEG, PNG e così via).
Esempi di configurazioni e test
Sono disponibili definizioni di rete complete e gli esempi di set di dati corrispondenti nel repository CNTK. Qui troverete anche unit test e end-to-end che usano deserializer, ad esempio
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/EndToEndTests/Speech/HTKDeserializers/LSTM/FullUtterance
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/EndToEndTests/Image/AlexNet
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/UnitTests/ReaderTests/Config/ImageAndTextReaderSimple_Config.cntk
- https://github.com/Microsoft/CNTK/tree/release/latest/Tests/UnitTests/ReaderTests/Config/CNTKTextFormatReader/dense.cntk