BrainScript tramite regole di analisi della riga di comando

Di seguito vengono descritte le regole di analisi della riga di comando CNTK. CNTK è costituito da un numero di componenti per completare un'attività. La maggior parte di questi componenti richiede alcune informazioni di configurazione disponibili per funzionare e questi parametri di configurazione vengono forniti tramite i file di configurazione in CNTK.

I file di configurazione sono raccolte di coppie nome-valore. I dati di configurazione possono essere uno dei tipi seguenti:

  • Semplice: un singolo valore viene assegnato al parametro di configurazione. Ad esempio: deviceId = "Auto".
  • Matrice: a un parametro di configurazione viene assegnata una matrice di valori che non devono essere di un tipo uniforme. : è il separatore predefinito per le matrici. Il separatore può essere modificato racchiudendo i valori della matrice tra parentesi e inserendo il nuovo carattere separatore immediatamente dopo la parentesi aperta. Il * carattere consente di ripetere più volte un valore specifico nella matrice. Ad esempio, minibatchSize = 256:512:512:512:1024 è uguale a minibatchSize = 256:512*3:1024.
  • Set: i set di parametri contengono set di parametri di configurazione di qualsiasi tipo. I set di parametri possono essere annidati. Il separatore predefinito per i set di parametri è ; se più elementi sono inclusi in una riga. I separatori di riga fungono anche da separatori per gli elementi. Ad esempio:

block1 = [id=1;size=256]

block2 = [
    subblock = [string="hi";num=5]
    value = 1e-10
    array = 10:"this is a test":1.25
]

In CNTK, i file di configurazione sono organizzati in modo gerarchico. I valori dei dati effettivi non vengono valutati fino a quando un componente CNTK richiede il valore. Quando un valore viene richiesto da un componente, CNTK eseguirà prima la ricerca all'interno del blocco del componente. Se il valore non viene trovato, continuerà a cercare il parametro padre e nonno impostato fino a quando non viene trovato il parametro oppure il livello superiore della gerarchia di configurazione viene raggiunto senza una corrispondenza. In questo modo la condivisione degli stessi valori dei parametri risulta più semplice tra blocchi diversi. Come illustrato in precedenza, per eseguire CNTK è necessario specificare il file di configurazione nella riga di comando perché cntk configFile=yourExp.cntk caricherà il file di configurazione richiesto ed eseguirà qualsiasi blocco di comando elencato nei parametri di comando nel file di configurazione.

Comandi e azioni

Deve essere presente un parametro di comando di primo livello, che definisce i comandi (separati con :) che verranno eseguiti nel file di configurazione. Ogni comando fa riferimento a un blocco di comandi nel file, che deve contenere un parametro di azione che definisce l'operazione che verrà eseguita dal blocco. Ad esempio, il comando seguente eseguirà il mnistTrain blocco , che esegue l'azione di training, seguita dal mnistTest blocco , che valuta il modello.

command = mnistTrain:mnistTest

mnistTrain = [
    action = "train"
    ...
]

mnistTest = [
    action = "eval"
    ...
]

Overload di configurazione nella riga di comando

È comune avere una configurazione che può essere usata come configurazione di base e modificare solo alcuni parametri per ogni esecuzione sperimentale. Questa operazione può essere eseguita in diversi modi, uno dei quali consiste nell'eseguire l'override delle impostazioni nella riga di comando. Ad esempio, per eseguire l'override del percorso del file del modello, è sufficiente modificare la riga di comando come indicato di seguito:

cntk configFile=yourExp.cntk stderr="c:\temp\newpath"

Verrà eseguito l'override dell'impostazione corrente per stderr, definita a livello radice del file di configurazione, con il nuovo valore. Se è necessario modificare un parametro all'interno di un blocco di comandi, è necessario specificare anche il blocco. Ad esempio, è possibile modificare per minibatchSize un esperimento nella riga di comando come

cntk configFile=yourExp.cntk mnistTrain=[minibatchSize=256]

oppure modificare il file di dati usato per un esperimento come

cntk configFile=yourExp.cntk mnistTrain=[reader=[file="mynewfile.txt"]]

File di configurazione a più livelli

Anziché eseguire l'override di alcune parti di un file di configurazione usando i parametri della riga di comando, è anche possibile specificare più file di configurazione, in cui questi ultimi file sostituiscono quelli precedenti. In questo modo un utente può avere un file di configurazione master e quindi specificare, in un file di configurazione separato, i parametri del master di cui desidera eseguire l'override per una determinata esecuzione di CNTK. A tale scopo, è possibile specificare un elenco separato "+" di file di configurazione o usando il configFile= tag più volte. Le righe che seguono sono pertanto equivalenti:

cntk configFile=yourExp1.cntk+yourExp2.cntk

cntk configFile=yourExp1.cntk configFile=yourExp2.cntk

Se yourExp2.cntk contiene solo la stringa mnistTrain=[reader=[file=mynewfile.txt]], entrambi questi comandi saranno equivalenti a:

cntk configFile=yourExp1.cntk mnistTrain=[reader=[file="mynewfile.txt"]]

Si noti che il valore di una variabile viene sempre determinato dall'ultima assegnazione. È anche possibile combinare parametri della riga di comando e file di configurazione a più livelli, in combinazioni arbitrarie. Ad esempio,

cntk configFile=yourExp1.cntk+yourExp2.cntk var1=value configFile=yourExp3.cntk

elabora questi parametri di configurazione nell'ordine in cui vengono visualizzati nella riga di comando e qualsiasi valore assegnato per ultimo sia il valore usato.

Oltre a poter specificare più file di configurazione nella riga di comando, un utente può includere un file di configurazione all'interno di un altro. Ad esempio, se la prima riga di yourExp2.cntk è stata

include=yourExp1.cntk

quindi semplicemente in esecuzione

cntk configFile=yourExp2.cntk

equivale all'esecuzione

cntk configFile=yourExp1.cntk+yourExp2.cntk

dove in questo secondo caso, yourExp2.cntk non contiene l'istruzione include. Si noti che queste istruzioni di inclusione possono essere visualizzate ovunque all'interno di un file di configurazione; ovunque venga visualizzata l'istruzione include, ovvero la posizione in cui verrà incluso il file di configurazione specificato. L'inclusione di un file di configurazione equivale a incollare il contenuto del file nel percorso dell'istruzione include. Le istruzioni di inclusione vengono risolte in modo ricorsivo (usando una ricerca depth-first), vale a dire che se include e include yourExpC.cntk, la catena completa verrà risolta e yourExpC.cntk verrà effettivamente inclusa in yourExpA.cntk.yourExpB.cntkyourExpB.cntkyourExpA.cntk Se un file di configurazione viene incluso più volte (ad esempio, 'A' include 'B' e 'C' e 'B' include anche 'C'), verrà effettivamente incluso solo la prima volta che viene rilevato.

Stringize Variables

Anche se i file di configurazione a più livelli consentono agli utenti di riutilizzare i file di configurazione tra gli esperimenti, questo può comunque essere un processo complesso. Per ogni esperimento, un utente potrebbe dover eseguire l'override di diversi parametri, alcuni dei quali potrebbero essere percorsi di file lunghi, ad esempio stderr, , modelPathfile. La funzionalità "stringize" può rendere molto più semplice questo processo. Consente a un utente di specificare una configurazione simile alla seguente:

command = SpeechTrain
stderr = "$Root$\$RunName$.log"
speechTrain = [
    modelPath = "$Root$\$RunName$.cn"
    SGD = [
        reader = [
            features = [
                type = "real"
                dim = "$DataSet1_Dim$"
                file = "$DataSet1_Features$"
            ]
        ]
    ]
]

In questo caso, Root,RunNameDataSet1_Dim e DataSet1_Features sono variabili specificate altrove nella configurazione (in corrispondenza di un ambito visibile dal punto in cui vengono usate). Quando si interpreta questo file di configurazione, il parser sostituirà ogni stringa del form $VarName$ con la stringa VarValue, dove VarValue rappresenta il valore della variabile denominata VarName. Il processo di risoluzione delle variabili è ricorsivo; Ad esempio, se A=$B$, B=$C$, e C=HelloWorld.txt, A verrà risolto come "HelloWorld.txt". Assicurarsi che nel file di configurazione non sia presente alcun ciclo di riferimento. In caso contrario, il parser passerà al ciclo infinito in questo momento.

Si noti che poiché per un utente è equivalente specificare il valore di una variabile in un file di configurazione e nella riga di comando, i valori per queste variabili possono essere specificati in entrambe le posizioni. Tenere presente che il valore di una variabile è determinato dall'ultima volta che viene assegnata, indipendentemente dal fatto che si tratti di un file di configurazione o della riga di comando. Pertanto, se Root è definito in config1.txt, ma sottoposto a override nella riga di comando, il valore specificato nella riga di comando sarà quello usato per risolvere le istanze di $Root$ in configFile1.txt. Una funzionalità utile è che se stderr o modelPath puntano a directory che non esistono, queste directory verranno create da CNTK. Ciò consente di specificare qualcosa come stderr = $Root$\$RunName$\$RunName$.log, anche se la directory $Root$\$RunName$ non esiste.

Valori predefiniti, valori ripetuti e commenti

La maggior parte dei parametri nei file di configurazione ha un valore predefinito che verrà usato se non viene specificato alcun valore di configurazione. Se non è presente alcun valore predefinito e non è possibile trovare il valore in una ricerca, verrà visualizzata un'eccezione e il programma verrà chiuso. Se un nome di parametro viene specificato più volte, l'ultimo valore impostato su tale valore è quello che verrà mantenuto. L'unica eccezione è nei set di parametri, che sono racchiusi tra [ parentesi graffe ]quadrate, in questi casi i valori all'interno delle parentesi graffe vengono considerati un set di parametri e verranno aggiunti al set di parametri attualmente esistente. Ad esempio:

params=[a=1;b=2;c=3]
params=[c=5;d=6;e=7]

è effettivamente uguale a:

params=[a=1;b=2;c=5;d=6;e=7]

Si noti che questa elaborazione di accodamento non viene usata per gli elementi della matrice e l'intera matrice verrà sostituita se viene impostata più volte. Il # carattere indica l'inizio di un commento, tutto ciò che si verifica dopo che viene # ignorato. Deve # essere preceduto da spazi vuoti o deve essere all'inizio della riga da interpretare come commento. Di seguito è riportato un commento valido

stderr="c:\cntk\log\cntk" # "_mnistTrain_mnistTest.log"

Di seguito è riportato un esempio di valore che non verrà interpretato come commento. Imposta un parametro var su infinito perché in #1#INF non è un marcatore di commento

var=1#INF