BrainScript et Python : Présentation et extension des lecteurs
À partir de la version 1.5, CNTK s’éloigne de la conception de lecteur monolithique vers un modèle plus composable qui vous permet de spécifier et de composer des données d’entrée de différents formats.
Avant, chaque lecteur était responsable de différents aspects de la lecture des données, y compris, mais pas limité à :
- Désérialisation des données du stockage externe en représentation en mémoire
- Randomisation de l’ensemble du corpus
- Différentes transformations de séquences/exemples d’entrée (par exemple, rognage ou mise à l’échelle d’images)
- Création de minibatches pour différents modes (par exemple, frame, séquence ou BPTT tronqué) avec une disposition qui peut être consommée par GPU
- Prérécupération au niveau des minibatches et des blocs d’E/S
Dans la version 1.5, les principaux éléments de la fonctionnalité ci-dessus ont été pris en compte et déplacés vers le CNTK principal pour être partagés entre différents lecteurs. Cette version introduit également deux abstractions principales qui peuvent être étendues afin de prendre en charge les nouveaux formats de données :
- désérialiseur : il est responsable de la désérialisation de l’entrée à partir d’un stockage externe dans des séquences en mémoire
- transformation : elle transforme une séquence d’entrée en séquence de sortie
Dans les sections suivantes, nous abordons plus en détail ces abstractions.
Configuration d’un lecteur (source minibatch) dans Python
Cette section fournit plusieurs exemples sur la façon dont un lecteur composite (également appelé MinibatchSource) peut être configuré dans Python.
L’exemple suivant a été adapté à partir de AlexNet_ImageNet_Distributed.py, il montre l’équivalent Python du lecteur AlexNet de la section Transformations .
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))))
L’exemple suivant (adapté à partir de A2_RunCntk_py3.py) montre comment plusieurs désérialiseurs peuvent être combinés.
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
Désérialiseurs
Examinons le fragment de configuration suivant pour HTKMLFReader du test LSTM/FullUtterance de bout en bout (configuration complète ici) :
...
# 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"
]
]
Ce fragment de configuration déclare un lecteur qui produit deux flux de données avec des noms "features"
et "labels"
. Il prend comme entrée deux types de fichiers :
- une liste de fichiers de fonctionnalités connus dans l’analyseur HTK sous la forme d’un
scp
fichier (« fichier de script ») - un fichier d’étiquette appelé
mlf
fichier (« fichier d’étiquette principale »)
Dans le fragment de configuration ci-dessus, il n’existe aucune entité explicite qui définirait comment scp
ou mlf
les formats sont désérialisés.
Tout est encapsulé dans la configuration HTKMLFReader .
Par conséquent, si vous devez exposer un autre flux d’entrée de différents formats de données avec scp
et mlf
, vous devez modifier HTKMLFReader et y ajouter la prise en charge.
Pour augmenter la composabilité et la réutilisation, la nouvelle configuration pour la même entrée définit explicitement les désérialiseurs et les flux d’entrée qu’ils produisent :
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
]
]
]
)
]
Les séquences produites par les mlf
désérialiseurs et htk
les désérialiseurs sont combinées en fonction de leur clé logique (qui est une chaîne qui identifie de manière unique un énoncé vocal et est présente dans les deux scp
fichiers et mlf
les fichiers).
Lorsque vous avez besoin d’un autre flux de différents formats, vous pouvez simplement ajouter le désérialiseur correspondant à la configuration (il n’est pas possible avec la fonctionnalité HTK et les désérialiseurs HTK MLF pour exposer plusieurs flux d’entrée chacun).
Notes
Actuellement, les configurations des lecteurs anciennes et nouvelles sont prises en charge. Lorsque la clé « désérialiseurs » est utilisée dans la configuration du lecteur, le type de lecteur est implicitement défini sur « CompositeDataReader ». Pour vous assurer que le module CompositeDataReader peut être chargé sur Windows, il Cntk.Composite.dll
doit se trouver dans le même répertoire que l’exécutable CNTK. Sur Linux Cntk.Composite.so
, il doit se trouver dans le lib
dossier qui se trouve côte à côte dans le bin
dossier contenant l’exécutable CNTK.
Actuellement, CNTK prend en charge les désérialiseurs ci-dessous :
Type de désérialiseur | Module | Description |
---|---|---|
HTKFeatureDeserializer | HTKDeserializers | Désérialiseur pour les fichiers de fonctionnalités HTK |
HTKMLFDeserializer | HTKDeserializers | Désérialiseur pour les fichiers MLF HTK |
ImageDeserializer | ImageReader | Désérialiseur pour les images encodées sous forme de fichiers bruts ou dans l’archive zip. |
Base64ImageDeserializer | ImageReader | Désérialiseur pour les images encodées en base64 dans le fichier de mappage. |
CNTKTextFormatDeserializer | CNTKTextFormatReader | Désérialiseur pour les fichiers de format texte CNTK |
CNTKBinaryFormatDeserializer | CNTKBinaryReader | Désérialiseur pour les fichiers de format binaire CNTK |
Reportez-vous aux tableaux ci-dessous pour obtenir la description complète des paramètres de configuration.
Transformations
Une transformation est une abstraction simple qui prend une séquence en tant qu’entrée, effectue une transformation d’exemples dans la séquence et retourne la séquence de sortie. Les exemples typiques de transformations sont des transformations différentes d’images telles que rognage, mise à l’échelle ou transposer. Les transformations peuvent être configurées par entrée.
Voyons comment les transformations peuvent être appliquées à l’entrée (la configuration est extraite du test 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
]
]
]
])
Dans cette configuration, quatre transformations sont appliquées au flux features
d’entrée.
Initialement, le désérialiseur de données d’image produit des séquences composées d’une seule image dans la représentation HWC.
Après cela, la liste triée des transformations est appliquée à l’image : premièrement, la transformation Rogner , suivie de Scale and Mean.
La dernière transformation est Transposer qui modifie la disposition de l’image de HWC en CHW.
Actuellement, les transformations suivantes sont implémentées. Pour obtenir une description détaillée, consultez ImageReader.
Type de transformation | Module |
---|---|
Rogner | ImageReader |
Scale | ImageReader |
Couleur | ImageReader |
Moyenne | ImageReader |
Transposer | ImageReader |
Description du nouveau format de configuration du lecteur
Une section de configuration de lecteur pour composer plusieurs désérialiseurs de données ressemble à ceci :
reader = [
randomize = true|false
verbosity = 0|1|2
...
deserializers = (
[<deserializerConfiguration1>]:
[<deserializerConfiguration2>]:
...
[<deserializerConfigurationN>]
)
]
Chaque configuration du désérialiseur est spécifiée comme suit :
[
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>]
...
]
]
Une configuration d’entrée contient des options spécifiques aux entrées et, éventuellement, une liste ordonnée de transformations qui doivent être appliquées à l’entrée :
[
# 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 configuration de transformation identifie le type de transformation et toutes les options spécifiques à la transformation :
[
type = "<transformName>"
# Transform-specific options
]
Options de configuration
Configuration générale du lecteur
Paramètre | Description |
---|---|
verbosity |
Niveau de détail (0 , 1 , 2 ), contrôle la sortie de diagnostic de différents composants (Randomr, Désérialiseur, Bundler, etc.) Facultatif, la valeur par défaut est 0 . |
randomize |
Spécifie si l’entrée doit être aléatoire ( true , false ). La méthode de randomisation est identique à blockRandomize du HTKMLFReader. Facultatif, la valeur par défaut est true . |
randomizationSeed |
Valeur initiale de randomisation initiale (incrémentée chaque balayage lorsque les données d’entrée sont réécrites aléatoires). Facultatif, la valeur par défaut est 0 . |
randomizationWindow |
Spécifie la taille (entier positif) de la fenêtre de randomisation (par exemple, plage de randomisation). Ce paramètre affecte la quantité de jeu de données qui doit résider en mémoire à la fois. Facultatif, la taille par défaut du jeu de données entier (dans les exemples ou en blocs, en fonction de la sampleBasedRandomizationWindow valeur). Toutefois, si l’un des désérialiseurs est CNTKTextFormatDeserializer et sampleBasedRandomizationWindow n’a pas été défini true explicitement sur , randomizationWindow est défini par défaut 128 (ce qui représente environ 4 Go d’espace disque de blocs). Ce paramètre est ignoré quand randomize est false . |
sampleBasedRandomizationWindow |
Si true , la taille de la fenêtre de randomisation est interprétée comme un certain nombre d’exemples, et comme un certain nombre de blocs sinon. Facultatif, par défaut true , s’il CNTKTextFormatDeserializer n’est pas présent dans la liste des désérialiseurs, et dans false le cas contraire. De la même façon que randomizationWindow , ce paramètre est ignoré, quand randomize est false . |
truncationLength |
Spécifie la longueur de troncation dans les exemples pour BPTT (entier positif). Obligatoire uniquement si truncated c’est true , ignoré sinon. |
multiThreadedDeserialization |
Spécifie si plusieurs threads doivent être utilisés lors de la collecte de séquences pour un minibatch à partir des désérialiseurs (,true false ). Facultatif. |
frameMode |
Spécifie si les données doivent être aléatoires et retournées au niveau de la trame ou de la séquence. Quand true , la séquence d’entrée est divisée en images. Facultatif. Les deux frameMode et truncated ne peuvent pas être définis true en même temps. |
truncated |
Quand true , active la propagation back-propagation tronquée par le temps (BPTT). Facultatif. Les deux frameMode et truncated ne peuvent pas être définis true en même temps. |
useNumericSequenceKeys |
Les clés de séquence sont utilisées pour mettre en corrélation des séquences entre différents désérialiseurs. Pour certains désérialiseurs (c’est-à-dire HTK et MLF), les clés de séquence sont des chaînes arbitraires. Les stocker nécessite beaucoup de mémoire sur le big corpus. Si vous êtes sûr que vos clés de séquence sont numériques, définissez ce paramètre sur true, dans ce cas, toutes les clés de chaîne seront converties en entiers réduisant la pression de la mémoire. Facultatif, valeur par défaut false . |
hashSequenceKeys |
Pour les raisons de mémoire décrites ci-dessus, les clés de chaîne peuvent également être hachées en définissant ce paramètre sur true. Utilisez-le uniquement pour les désérialiseurs qui prennent en charge les clés de séquence de chaînes (HTK, MLF). Facultatif, valeur par défaut false . |
cacheIndex |
Spécifie si les métadonnées créées au cours de la phase de prétraitement doivent être écrites sur le disque et chargées à partir du disque si disponibles (,true false ). Facultatif, valeur par défaut .false Pour plus d’informations, consultez la section ci-dessous. Nouveautés de CNTK version 2.1. |
Mise en cache d’index
Notes
Nouveautés de CNTK version 2.1.
La mise en cache d’index permet de réduire considérablement (par un facteur de 2 à 3x) les temps de démarrage, en particulier lors de l’utilisation de fichiers d’entrée volumineux. La définition de l’indicateur cacheIndex
pour true
signaler au lecteur d’écrire les métadonnées d’indexation sur le disque (même répertoire que le fichier d’entrée) si le fichier cache n’est pas disponible ou s’il est obsolète (plus ancien que le fichier d’entrée). L’écriture est le meilleur effort et est effectuée sur un thread distinct afin de ne pas affecter les performances du lecteur. Si le fichier de cache est présent et est à jour, le lecteur n’écrémera plus le fichier d’entrée pour générer l’index, mais il chargera l’index à partir du fichier de cache. Notez que certains paramètres de configuration de lecteur ont un impact direct sur l’indexation (par exemple, différentes valeurs frameMode
peuvent entraîner des index qui ont un nombre différent de séquences). Pour cette raison, un fichier de cache peut être ignoré par un lecteur avec une configuration différente de celle qui a produit le cache. Pour voir l’avantage complet de la mise en cache, la configuration ne doit pas être modifiée lors des réexécutions suivantes.
cacheIndex
n’a aucun effet sur ImageDeserializer et CNTKBinaryFormatDeserializer, car l’ancien n’indexe pas les données d’entrée et les informations d’index ultérieures sont incorporées dans le format lui-même.
Configuration générale du désérialiseur
Paramètre | Description |
---|---|
module |
Spécifie le nom du module lecteur qui implémente le désérialiseur de données. Requis. |
type |
Spécifie un nom de désérialiseur de données exposé par le module lecteur donné. Requis. |
Configuration générale de la transformation
Paramètre | Description |
---|---|
type |
Spécifie un nom de transformation exposé par le module lecteur implémentant le désérialiseur de données. Requis. |
Options htKFeatureDeserializer
Paramètre | Description |
---|---|
scpFile |
Liste des chemins d’accès aux fichiers SCP à traiter. Les fichiers doivent être compatibles HTK et doivent être spécifiés au format « archive ». Les détails de l’utilisation d’une archive sont décrits dans le lecteur HTKMLF. Requis. |
dim |
Entier qui spécifie la dimension de vecteur de fonctionnalité complète avec la fenêtre de contexte souhaitée. 1Obligatoire |
contextWindow |
Peut être spécifié sous la forme d’une paire d’entiers positifs ou d’un entier positif unique (dans ce cas, il est interprété comme une paire avec le même nombre répété deux fois). Spécifie la taille gauche et droite (premier et deuxième entier de la paire) de la fenêtre de contexte dans les exemples. Facultatif, valeur par défaut .1 |
prefixPathInSCP |
Chaîne de préfixe à appliquer aux chemins spécifiés dans les fichiers SCP. Facultatif. |
1 Par exemple, si vous avez des caractéristiques 72 dimensions (caractéristiques de la banque de filtres 24 dimensions plus delta et delta-delta coefficients) et que le réseau est conçu pour traiter une fenêtre de contexte de 11 images, la dimension spécifiée doit être 792.
Options htKMLFDeserializer
Paramètre | Description |
---|---|
mlfFile |
Chemin d’accès à un fichier de style mlf HTK qui contient les étiquettes pour tous les énoncés spécifiés dans le ou les scp fichiers. Obligatoire s’il mlfFileList n’est pas spécifié. |
mlfFileList |
Tableau de chemins d’accès aux fichiers de style mlf HTK qui contient les étiquettes pour tous les énoncés spécifiés dans le scp ou les fichiers. Obligatoire s’il mlfFile n’est pas spécifié. |
dim |
Cardinalité totale du jeu d’étiquettes (entier positif). Requis. |
labelMappingFile |
Chemin d’accès à un fichier qui répertorie toutes les étiquettes affichées dans le mlf fichier, une par ligne. Requis. |
labelDim peut être utilisé comme synonyme de dim.
Options CNTKTextFormatDeserializer
Mêmes options qui peuvent être utilisées avec CNTKTextFormatReader
Options ImageDeserializer
file
: fichier texte simple où chaque ligne contient un mappage séparé par des onglets entre une clé de séquence logique, un fichier image (par exemple JPEG, PNG, etc.) et une étiquette basée sur 0.
Pour plus d’informations, consultez ImageReader.
Options de Base64ImageDeserializer
Ce désérialiseur prend en charge les mêmes options que celles qui peuvent être utilisées avec ImageDeserializer. La seule différence est au format du fichier de mappage :
file
: fichier texte simple où chaque ligne contient un mappage séparé par onglet entre une clé de séquence logique (facultatif, peut être omis), une étiquette de catégorie basée sur 0 et un fichier image codé en base 64 (par exemple JPEG, PNG, etc.).
Exemples de configurations et de tests
Vous trouverez des définitions réseau complètes et des exemples de jeu de données correspondants dans le référentiel CNTK. Vous trouverez également des tests unitaires et de bout en bout qui utilisent des désérialiseurs, c’est-à-dire des tests unitaires et finaux.
- 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