Riferimento ai livelli con BrainScript
CNTK predefinito un numero di "livelli comuni", che semplifica la scrittura di reti semplici costituite da livelli standard sovrapposti tra loro.
I livelli sono oggetti funzione che possono essere usati come le normali funzioni BrainScript, ma contengono parametri imparabili e hanno una coppia aggiuntiva di {}
per passare parametri di costruzione o attributi.
Ad esempio, questa è la descrizione di rete per un semplice modello di livello nascosto a 1 usando il DenseLayer{}
livello:
h = DenseLayer {1024, activation=ReLU} (features)
p = DenseLayer {9000, activation=Softmax} (h)
che può quindi essere usato per l'addestramento in base a un criterio di entropia incrociata:
ce = CrossEntropy (labels, p)
Se la rete è una concatenazione diretta delle operazioni (molti sono), è possibile usare l'alternativa
Sequential()
Notazione:
myModel = Sequential (
DenseLayer {1024, activation=ReLU} :
DenseLayer {9000, activation=Softmax}
)
e richiamarlo come segue:
p = myModel (features)
Modelli di esempio
Di seguito viene illustrato un tagger slot che incorpora una sequenza di parole, lo elabora con un LSTM ricorrente e quindi classifica ogni parola:
taggingModel = Sequential (
EmbeddingLayer {150} : # embed into a 150-dimensional vector
RecurrentLSTMLayer {300} : # forward LSTM
DenseLayer {labelDim} # word-wise classification
)
Di seguito è riportata una semplice rete convoluzionale per il riconoscimento delle immagini:
convNet = Sequential (
# 3 layers of convolution and dimension reduction by pooling
ConvolutionalLayer {32, (5:5), pad=true, activation=ReLU} :
MaxPoolingLayer {(3:3), stride=(2:2)} :
ConvolutionalLayer {32, (5:5), pad=true, activation=ReLU} :
MaxPoolingLayer {(3:3), stride=(2:2)} :
ConvolutionalLayer {64, (5:5), pad=true, activation=ReLU} :
MaxPoolingLayer {(3:3), stride=(2:2)} :
# 2 dense layers for classification
DenseLayer {64, activation=ReLU} :
LinearLayer {10}
)
Condivisione dei parametri
Se si assegna un livello a una variabile e lo si usa in più posizioni, i parametri verranno condivisi. Se si dice
lay = DenseLayer {1024, activation=Sigmoid}
h1 = lay (x)
h2 = lay (h1) # same weights as `h1`
h1
e h2
condividerà gli stessi parametri, come lay()
è la stessa funzione in entrambi i casi.
Nel caso precedente questo probabilmente non è quello desiderato, quindi essere consapevoli.
Se entrambe le chiamate di lay()
sopra sono destinate ad avere parametri diversi, ricordare di definire due istanze separate, ad esempio lay1 = DenseLayer{...}
e lay2 = DenseLayer{...}
.
Perché questo comportamento?
I livelli consentono di condividere i parametri tra le sezioni di un modello.
Si consideri un modello DSSM che elabora due immagini di input, ad esempio doc
e identicamente alla stessa catena di elaborazione, e query
confronta i vettori nascosti risultanti:
imageToVec = Sequential (
ConvolutionalLayer {32, (5:5), pad = true, activation = ReLU} :
MaxPoolingLayer {(3:3), stride = (2:2)} :
ConvolutionalLayer {64, (5:5), pad = true, activation = ReLU} :
MaxPoolingLayer {(3:3), stride = (2:2)} :
DenseLayer {64, activation = ReLU} :
LinearLayer {10}
)
zDoc = imageToVec (doc)
zQuery = imageToVec (query) # same model as for zDoc
sim = CosDistance (zdoc, zQuery)
dove imageToVec
fa parte del modello che converte le immagini in vettore flat.
imageToVec
è un oggetto funzione che a sua volta contiene diversi oggetti funzione (ad esempio tre istanze di ConvolutionalLayer{}
).
imageToVec
viene creata un'istanza una sola volta e questa istanza contiene i parametri appresi di tutti gli oggetti funzione inclusi. Entrambe le chiamate di model()
condivideranno questi parametri nell'applicazione e le relative sfumature saranno la somma di entrambe le chiamate.
Infine, si noti che se nell'esempio query
precedente e doc
deve avere le stesse dimensioni, poiché vengono elaborate tramite lo stesso oggetto funzione e che il primo livello dell'oggetto funzione ha la dimensione di input dedotto per corrispondere a quello di entrambi query
e doc
.
Se le dimensioni differiscono, questa rete non è corretta e l'inferenza/convalida delle dimensioni avrà esito negativo con un messaggio di errore.
Nota di implementazione
Molti livelli sono wrapper intorno alle primitive CNTK sottostanti, insieme ai rispettivi parametri appresi necessari. Ad esempio, ConvolutionalLayer{}
esegue il wrapping della Convolution()
primitiva.
I vantaggi dell'uso dei livelli sono:
- i livelli contengono parametri appresi della dimensione corretta
- i livelli sono componibili (cf.
Sequential()
)
DenseLayer, LinearLayer{}{}
Funzione Factory per creare un livello completamente connesso.
DenseLayer{}
accetta con una non linearità facoltativa.
DenseLayer {outDim, activation=Identity, init='glorotUniform', initValueScale=1, bias=true}
LinearLayer {outDim, init='glorotUniform', initValueScale=1, bias=true}
Parametri
-
outDim
: dimensione di output di questo livello -
activation
(DenseLayer{}
solo): passare una funzione qui da usare come funzione di attivazione, ad esempioactivation=ReLU
-
init
('heNormal'
|'glorotUniform'
|...): tipo di inizializzazione per i pesi. Per un elenco completo delle opzioni di inizializzazione, vedere qui. -
initValueScale
: l'inizializzazione casuale della varianza viene moltiplicata con questa -
bias
: se false, non includere un parametro di pregiudizio
Valore restituito
Funzione che implementa il livello completamente connesso desiderato. Vedere la descrizione.
Descrizione
Usare queste funzioni factory per creare un livello completamente connesso.
Usare DenseLayer{}
se si vuole includere una funzione di attivazione, in caso contrario LinearLayer{}
.
Ognuna di queste funzioni factory crea un oggetto funzione che contiene una matrice di peso appresa e, a meno bias=false
che non venga usato un pregiudizio appreso. L'oggetto funzione può essere usato come una funzione, che implementa una di queste formule:
DenseLayer{...} (v) = activation (W * v + b)
LinearLayer{...} (v) = W * v + b
dove W
è una matrice di peso della dimensione , b
è la distorsione della dimensione [outDim x (dimension of v)]
[outdim]
e il valore risultante ha dimensione (o dimensioni tensore) come indicato da outDim
.
Supporto di Tensor
Se la funzione restituita viene applicata a un input di un tensore rango > 1, ad esempio un'immagine 2D, W
avrà la dimensione [outDim x (first dimension of input) x (second dimension of input) x ...]
.
D'altra parte, outDim
può essere un vettore che specifica le dimensioni del tensore, ad esempio (10:10)
.
In tal caso, W
avrà la dimensione [outDim[0] x outDim[1] x ... x (dimension of input)]
e b
avrà le dimensioni [outDim[0] x outDim[1] x ...]
del tensore .
CNTK prodotto matrice interpreterà queste dimensioni di output o di input aggiuntive come se fossero appiattite in un vettore lungo.
Per altre informazioni su questo, vedere la documentazione di Times()
Esempio:
h = DenseLayer {1024, activation=Sigmoid) (v)
o in alternativa:
Layer = DenseLayer {1024, activation=Sigmoid)
h = Layer (v)
ConvolutionalLayer{}
Crea un livello di convoluzione con non linearità facoltativa.
ConvolutionalLayer {numOutputChannels, filterShape,
activation = Identity,
init = 'glorotUniform', initValueScale = 1,
stride = 1, pad = false, lowerPad = 0, upperPad = 0,
bias = true}
Parametri
-
numOutputChannels
: numero di canali di output (numero di filtri) -
filterShape
: estensione spaziale del filtro, ad esempio(5:5)
per un filtro 2D. La dimensione del canale di input non deve essere inclusa qui. -
activation
: facoltativa non lineare, ad esempioactivation=ReLU
-
init
('heNormal'
|'glorotUniform'
|...): tipo di inizializzazione casuale per i pesi. Per un elenco completo delle opzioni di inizializzazione casuale, vedere qui. -
initValueScale
: l'inizializzazione casuale della varianza viene moltiplicata con questa -
stride
: incrementa quando si sposta il filtro sull'input. Ad esempio,(2:2)
per ridurre le dimensioni entro 2 -
pad
: se non è impostato (impostazione predefinita), il filtro verrà spostato sull'area di input "valida", ovvero nessun valore esterno all'area. Sepad
è impostato invece, il filtro verrà applicato a tutte le posizioni di input e i valori all'esterno dell'area valida verranno considerati zero. -
lowerPad
,upperPad
: specificare in modo esplicito margini diversi per la spaziatura interna. I filtri verranno spostati su un'area valida che è (virtualmente) aumentata con zero. Ad esempio,lowerPad=(1:2)
aggiungerà una colonna di zero e due righe di zero. La dimensione dell'output viene estesa di conseguenza. -
bias
: se false, non includere un parametro di pregiudizio
Valore restituito
Funzione che implementa il livello completamente connesso desiderato. Vedere la descrizione.
Descrizione
Usare queste funzioni factory per creare un livello di convoluzione.
Il livello risultante applica un'operazione di convoluzione su un tensore Ndimensionale.
Il chiamante specifica l'estensione spaziale del filtro.
Un set di filtri di un determinato extent spaziale (ad esempio ) è correlato a ogni posizione dell'input (ad esempio (5:5)
un'immagine [640 x 480]
di dimensioni).
Supponendo che la spaziatura interna sia abilitata (pad
) e gli stridi siano 1, verrà generata un'area di output della stessa dimensione ([640 x 480]
).
In genere, molti filtri vengono applicati contemporaneamente.
numOutputChannels
specifica il numero, quindi per ogni posizione di input, viene prodotto un intero vettore di numOutputChannels
.
Per il nostro esempio precedente, l'impostazione numOutputChannels
su 64 sarebbe in un [640 x 480 x 64]
tensore di dimensioni.
L'ultimo asse viene chiamato dimensione del canale.
Quando la convoluzione viene applicata a un input con una dimensione del canale, ogni filtro sarà costituito anche da vettori della dimensione del canale di input.
Ad esempio, quando si applica la convoluzione con un'estensione del filtro spaziale specificata di (5:5)
un'immagine [640 x 480 x 3]
di colore di dimensioni, ogni filtro sarà un [5 x 5 x 3]
tensore.
Tutti i numOutputChannels
filtri sovrapposti vengono chiamati kernel.
Nell'esempio la forma del kernel sarà [5 x 5 x 3 x 64]
.
Di seguito viene riepilogato la relazione tra le varie dimensioni e forme:
input shape : [ (spatial dims) x (#input channels) ]
spatial extent : [ (filterShape) ]
output shape : [ (spatial dims) x x numOutputChannels ]
kernel shape : [ (filterShape) x (#input channels) x numOutputChannels ]
che nell'esempio seguente:
input shape : [ 640 x 480 x 3 ]
spatial extent : [ 5 x 5 ]
output shape : [ 640 x 480 x x numOutputChannels ]
kernel shape : [ 5 x 5 x 3 x numOutputChannels ]
Riempimento
Se la spaziatura interna non è abilitata, l'area di output verrà ridotta in base alle posizioni limite a cui non è possibile applicare l'estensione di filtro completa. Ad esempio, l'applicazione di un filtro -extent a un'immagine (5:5)
senza spaziatura interna, le righe e le colonne più esterne di pixel causerebbero l'applicazione del filtro ai limiti.
Di conseguenza, ConvolutionalLayer{}
ridurrà le dimensioni di conseguenza.
Un'immagine [640 x 480]
convolved con un filtro senza spaziatura interna lascerà un'area (5:5)
[636 x 476]
di output di dimensioni.
Passi
I stride
parametri specificano l'incremento dei filtri.
I valori di stride maggiori di uno condurranno a un campionamento secondario dell'area di output.
Ad esempio, il filtro di un'immagine [640 x 480]
con uno stride di comporterà un'area [320 x 240]
di (2:2)
dimensioni con spaziatura interna e [318 x 238]
senza riempimento.
Note
Questo livello è un wrapper intorno alla Convolution()
primitiva.
Il nome dei parametri del kernel di filtro come illustrato nella sezione di convalida del log termina in .W
.
La dimensione attualmente non verrà visualizzata come [ (filterShape) x (#input channels) x numOutputChannels ]
descritto in precedenza, ma invece [ numOutputChannels x ((product over filter shape) * (#input canali)) ]'.
Esempio:
c = ConvolutionalLayer {64, (3:3), pad = true, stride = (1:1), bias=false} (x)
DeconvLayer{}
Crea un livello di deconvoluzione.
DeconvLayer {numOutputChannels,
filterShape, numInputChannels,
bias = true,
activation = (x=>x),
init = 'glorotUniform',
initValueScale = 0.001,
initBias = 0,
stride = 1, autoPadding = false,
lowerPad = 0, upperPad = 0,
maxTempMemSizeInSamples = 0}
Parametri
-
numOutputChannels
: numero di canali di output (numero di filtri) -
filterShape
: estensione spaziale del filtro, ad esempio(5:5)
per un filtro 2D. La dimensione del canale di input non deve essere inclusa qui. -
numInputChannels
: numero di canali di input (numero di filtri del volume di input) -
bias
: se false, non includere un parametro di pregiudizio -
activation
: facoltativa non lineare, ad esempioactivation=ReLU
-
init
('heNormal'
|'glorotUniform'
|...): tipo di inizializzazione casuale per i pesi. Per un elenco completo delle opzioni di inizializzazione casuale, vedere qui. -
initValueScale
: l'inizializzazione casuale della varianza viene moltiplicata con questa -
initBias
: valore iniziale per il pregiudizio -
stride
: incrementa quando si sposta il filtro sull'input. Ad esempio,(2:2)
per ridurre le dimensioni entro 2 -
autoPadding
: se non è impostato (impostazione predefinita), il filtro verrà spostato sull'area di input "valida", ovvero nessun valore esterno all'area. SeautoPadding
è impostato invece, il filtro verrà applicato a tutte le posizioni di input e i valori all'esterno dell'area valida verranno considerati zero. -
lowerPad
,upperPad
: specificare in modo esplicito margini diversi per il riempimento per il volume di output, ovvero quelli usati per l'input nel livello convoluzionale corrispondente. È importante impostarli in corrispondenza del livello convoluzionale per ottenere le stesse dimensioni del tensore.
Valore restituito
Funzione che implementa il livello completamente connesso desiderato. Vedere la descrizione.
Descrizione
Usare queste funzioni factory per creare un livello di deconvoluzione.
Il livello risultante applica un'operazione di deconvoluzione su un tensore Ndimensionale.
Questo livello è un wrapper intorno alla Convolution()
primitiva con deconv=true
.
Uno dei casi d'uso più diffusi per la deconvoluzione sta ricostruendo un'immagine (vedere ad esempio qui). Dove la convoluzione accetta un'area di campo 2D di input e calcola la correlazione con un filtro 2D, la deconvoluzione accetta un pixel e lo distribuisce in un'area 2D.
Prendere in considerazione un filtro p(.,.), un percorso pixel (x,y) e un filtro [3 x 3] con il contenuto seguente (nessuna dimensione di profondità mappa delle funzionalità per il momento, ad esempio un singolo canale):
[ . . c
a b .
. . . ]
In questo caso, un b e c sono pesi del filtro, '.' Corrisponde a un peso zero. Convolution() calcola il pixel di output q(x, y) in posizione (x, y) come:
q(x,y) = b * p(x,y) + a * p(x-1,y) + c * p(x+1,y-1)
La deconvoluzione accetta pixel q(x,y) e li distribuisce in un'area intorno (x,y). Se è stato usato lo stesso filtro, si apportano i contributi seguenti all'output r(x,y):
r(x,y) += b * q(x,y)
r(x-1,y) += a * q(x,y)
r(x+1,y-1) += c * q(x,y)
Sapendo che lo stesso vale per tutti x e y nel piano, possiamo esprimere questo per r(x,y):
r(x,y) += b * q(x,y)
r(x,y) += a * q(x+1,y)
r(x,y) += c * q(x-1,y+1)
o in totale,
r(x,y) = b * q(x,y) + a * q(x+1,y) + c * q(x-1,y+1)
Questo ha la stessa forma della convoluzione precedente, ad eccezione del fatto che il filtro viene mirrorato lungo entrambi gli assi.
Ora vengono introdotte le mappe delle funzionalità nella combinazione. È facile: invece di passare dalla profondità di input alla profondità di output, andiamo dall'altra direzione.
In riepilogo, Convolution (W, x) == Deconvolution (W', x), dove
W : [W x H x C x K]
e
W’ = W
con i relativi valori riorganizzati come: [(W mirrored) x (H mirrored) x K x C]
Ad esempio, ciò che Deconvolution() fa in modo implicito:
- scambiare le due dimensioni di profondità (trasposto)
- dimensioni spaziali (invertire l'ordine dei dati)
- Convoluzione() con queste
Esempio:
deconv_A = DeconvLayer {inputDim, (5:5), cMap1, lowerPad=(2:2:0), upperPad=(2:2:0)}(unpool_A)
Per un esempio dettagliato e una procedura dettagliata, vedere Codificatore automatico dell'immagine usando Deconvolution e Unpooling .
MaxPoolingLayer, AveragePoolingLayer{}{}
Funzioni factory per creare un livello massimo o medio di pooling.
MaxPoolingLayer {poolShape, stride = 1, pad = false, lowerPad = 0, upperPad = 0}
AveragePoolingLayer {poolShape, stride = 1, pad = false, lowerPad = 0, upperPad = 0} =
Parametri
-
poolShape
: la forma dell'area da pool, ad esempio(2:2)
-
stride
: incrementa quando si scorre il pool sull'input. Ad esempio,(2:2)
per ridurre le dimensioni entro 2 -
pad
: se non è impostato (impostazione predefinita), il pool verrà spostato sull'area di input "valida", ovvero nessun valore esterno all'area. Sepad
è impostato invece, il pool verrà applicato a tutte le posizioni di input e i valori all'esterno dell'area valida verranno considerati zero. Per il pooling medio, il conteggio per la media non include valori spaziati. -
lowerPad
,upperPad
: specificare in modo esplicito margini diversi per la spaziatura interna. I filtri verranno spostati su un'area valida che è (virtualmente) aumentata con zero. Ad esempio,lowerPad=(1:2)
aggiungerà una colonna di zero e due righe di zero. La dimensione dell'output viene estesa di conseguenza.
Valore restituito
Funzione che implementa il livello di pooling desiderato. Vedere la descrizione.
Descrizione
Usare questa funzione factory per creare un'operazione di pooling. Usare MaxPoolingLayer{}
per calcolare il valore massimo rispetto ai valori nell'area del pool e AveragePoolingLayer{}
prendere la media.
L'operazione di pooling scorre una "finestra del pool" su posizioni di un'area di input e calcola il valore massimo o la media dei valori nell'area del pool corrispondente.
Questa operazione è strutturalmente molto simile alla convoluzione, ad eccezione del fatto che l'operazione applicata alla finestra scorrevole è di natura diversa.
Tutte le considerazioni relative a dimensioni di input, spaziatura interna e passi si applicano in modo identico, quindi per altre informazioni, vedere ConvolutionalLayer{}
per altri dettagli.
Esempio:
p = MaxPoolingLayer {(3:3), stride=(2:2)} (c)
MaxUnpoolingLayer{}
Crea un livello max-unooling.
MaxUnpoolingLayer {poolShape,
stride = 1, pad = false,
lowerPad = 0, upperPad = 0}
Parametri
-
poolShape
: la forma dell'area da annullare (dimensione dell'area di output ), ad esempio(2:2)
-
stride
: incrementa quando si scorre il pool sull'output. Ad esempio,(2:2)
per aumentare le dimensioni entro 2 -
pad
: se non è impostato (impostazione predefinita), il pool verrà spostato sull'area di output "valida", ovvero nessun valore all'esterno dell'area. -
lowerPad
,upperPad
: specificare in modo esplicito margini diversi per la spaziatura interna. I filtri presuppongono un'area di output valida aumentata (virtualmente).
Valore restituito
Funzione che implementa il livello di unpooling desiderato. Vedere la descrizione.
Descrizione
Usare questa funzione factory per creare un'operazione di unpooling.
L'operazione di annullamento del pool è l'inverso di un'operazione di pooling. Richiede due input: l'output del livello di pooling corrispondente, ad esempio e l'input del relativo livello di pooling corrispondente, ad esempio p1
r1
, anche. Scorre una finestra "pool inversa" su posizioni del relativo input p1
e proietta il valore in tale posizione dell'area di output con il valore massimo nell'operazione di pooling corrispondente, ovvero in r1
. Il secondo input r1
è necessario in CNTK per determinare la destinazione dell'operazione di unpooling, poiché CNTK non archivia le variabili switch (vedere qui per informazioni dettagliate).
Esempio:
unpool_A = MaxUnpoolingLayer {(2:2), stride=(2:2)}(deconv_B, relu_A)
Per un esempio dettagliato e una procedura dettagliata, vedere Codificatore automatico di immagini con Deconvolution e Unpooling .
EmbeddingLayer{}
EmbeddingLayer {outDim,
init='glorotUniform', initValueScale=1,
embeddingPath = '', transpose = false}
Parametri
-
outDim
: dimensione del vettore di incorporamento desiderato -
init
('heNormal'
|'glorotUniform'
|...): tipo di inizializzazione per i pesi. Per un elenco completo delle opzioni di inizializzazione, vedere qui. -
initValueScale
: l'inizializzazione casuale della varianza viene moltiplicata con questa -
embeddingPath
: se specificato, gli incorporamenti non vengono appresi ma caricati da un file e non aggiornati ulteriormente durante il training -
transpose
: consente di caricare incorporamenti archiviati in formato trasposto
Valore restituito
Funzione che implementa il livello di incorporamento. Vedere la descrizione.
Descrizione
"Incorporamento" si riferisce alla rappresentazione di parole o altri elementi discreti da vettori continui densi. Questo livello presuppone che l'input sia in formato one-hot. Ad esempio, per una dimensione del vocabolario pari a 10.000, ogni vettore di input deve avere una dimensione pari a 10.000 e sono costituiti da zere, ad eccezione di una posizione che contiene un valore 1. L'indice di tale posizione è l'indice della parola o dell'elemento rappresentato.
In CNTK i vettori di incorporamento corrispondenti vengono archiviati come colonne di una matrice. Di conseguenza, il mapping di una parola di input alla relativa incorporazione viene implementato come prodotto matrice. Per essere molto efficiente, è importante che i vettori di input siano archiviati in formato sparse.
Curiosità: la sfumatura di una matrice di incorporamento ha la forma di vettori sfumatura che sono solo diversi da zero per le parole visualizzate in un minibatch. Poiché per i vocabolari realistici di decine o centinaia di migliaia, la maggior parte delle colonne sarebbe zero, CNTK implementa ha un'ottimizzazione specifica per rappresentare la sfumatura in formato "column-sparse".
Problema noto: il formato sfumato a colonne di tipo sparse menzionato in precedenza non è attualmente supportato dalla tecnica di parallelizzazione SGD a 1 bit . Usare invece la tecnica block-momentum .
Esempio
Incorporamento appreso che rappresenta le parole da un vocabolario di 87636 come vettore dimensionale 300:
input = Input{87636, sparse=true} # word sequence, as one-hot vector, sparse format
embEn = EmbeddingLayer{300} (input) # embed word as a 300-dimensional continuous vector
Oltre a sparse=true
, è necessario dichiarare anche un input come sparse nel reader
blocco di configurazione.
Ecco un esempio di lettura dell'input di testo sparse con :CNTKTextFormatReader
reader = {
readerType = "CNTKTextFormatReader"
file = "en2fr.txt"
randomize = true
input = {
input = { alias = "E" ; dim = 87636 ; format = "sparse" }
labels = { alias = "F" ; dim = 98624 ; format = "sparse" }
}
}
Se invece i vettori di incorporamento esistono già e devono essere caricati da un file, sarà simile al seguente:
input = Input{87636, sparse=true} # word sequence, as one-hot vector, sparse format
embEn = EmbeddingLayer{300, embeddingPath="embedding-en.txt", transpose=true} (w) # embedding from disk
dove il file "embedding-en.txt"
dovrebbe essere costituito da 87.636 righe di testo, ognuna delle quali costituita da 300 numeri separati da spazi.
Poiché questo file salva le incorporazioni come righe anziché come colonne, transpose=true
trasporrà la matrice in tempo reale.
RicorrenteLSTMLayer, RicorrenteLSTMLayerStack{}{}
Funzioni factory per creare un LSTM ricorrente a livello singolo o multili layer.
RecurrentLSTMLayer {outDim, cellShape = None,
goBackwards = false,
usePeepholes = false,
init = 'glorotUniform', initValueScale = 1,
enableSelfStabilization = false,
allowOptimizedEngine = false}
RecurrentLSTMLayerStack {layerDims,
cellShapes = None,
usePeepholes = false,
init = 'glorotUniform', initValueScale = 1,
enableSelfStabilization = false,
allowOptimizedEngine = false}
Parametri
-
outDim
(RecurrentLSTMLayer{}
): dimensione dell'output della rete. Per indicare un tensore di rango>1, può trattarsi di un vettore, ad esempio(40:2)
-
layerDims
(RecurrentLSTMLayerStack{}
): matrice di dimensioni dei livelli interni e dell'output della rete -
cellShape
( (RecurrentLSTMLayer{}
, facoltativo): dimensione della cella LSTM. In genere è identico aoutDim
. Se viene specificato un valore diverso, verrà inserita una proiezione lineare aggiuntiva per la conversione dalla dimensione della cella all'output. -
cellShapes
( (RecurrentLSTMLayerStack{}
, facoltativo): matrice di valori comecellShape
perRecurrentLSTMLayer()
indicare la proiezione -
goBackwards
(facoltativo): se true, la ricorrenza viene eseguita all'indietro -
usePeepholes
(facoltativo): se true, usare le connessioni peephole in LSTM -
init
('heNormal'
|'glorotUniform'
|...): tipo di inizializzazione per i pesi. Per un elenco completo delle opzioni di inizializzazione, vedere qui. -
initValueScale
: l'inizializzazione casuale della varianza viene moltiplicata con questa -
enableSelfStabilization
(facoltativo): se true, inserire un'operazione di "stabilizzatore" simile aStabilizerLayer{}
-
allowOptimizedEngine
(facoltativo, valore false predefinito): se true, usare il motore RNN ottimizzato di cuDNN, dove possibile
Valore restituito
Funzione che implementa i livelli desiderati che applica/applica un LSTM ricorrente alla sequenza di input. Questo livello (stack) esegue il mapping di una sequenza di input a una sequenza di stati nascosti della stessa lunghezza.
Descrizione
Ciò implementa l'LSTM ricorrente da applicare a una sequenza di input, in due varianti: un singolo livello e uno stack multili layer. Questa operazione gestisce automaticamente l'input a lunghezza variabile. Il valore iniziale dello stato nascosto e della cella è 0.
L'applicazione di questo livello a una sequenza di input restituirà la sequenza degli stati nascosti dell'LSTM ricorrente (top-of-stack) (il valore della cella di memoria dell'LSTM non viene restituito).
La sequenza restituita ha la stessa lunghezza dell'input.
Se si desidera solo l'ultimo stato, come nella classificazione della sequenza o in alcuni scenari da sequenza a sequenza, usare BS.Sequences.Last()
per estrarre solo lo stato nascosto dell'ultimo elemento.
In una ricorrenza all'indietro si userà BS.Sequences.First()
.)
Per creare un modello bidirezionale con RecurrentLSTMLayer()
, usare due livelli, uno con goBackwards=true
e Splice()
i due output insieme.
RecurrentLSTMLayerStack()
attualmente non supporta i modelli bidirezionali, è necessario crearlo manualmente usando più RecurrentLSTMLayer()/Splice()
combinazioni.
Uso del motore RNN CuDNN5
Questa funzione userà automaticamente il motore RNN ottimizzato di CuDNN5, se possibile, ovvero, se possibile
- il modello specificato è uno che può essere implementato dalla funzione di CuDNN5
- nessuna proiezione (nessun
cellShape
parametro) - nessuna connessione peep-hole
- nessuna stabilizzazione automatica
- non andando indietro
- per
RecurrentLSTMLayerStack{}
, tutte le dimensioni del livello hanno lo stesso valore
- nessuna proiezione (nessun
allowOptimizedEngine=true
In particolare, CNTK richiede l'abilitazione allowOptimizedEngine=true
di .
Ciò è dovuto al fatto che la rete NNN CuDNN5 viene implementata come operazione primitiva CNTK che richiede una GPU.
Tuttavia, molti sistemi reali usano GPU per il training, ma server solo CPU nella distribuzione.
L'RNN CuDNN5 non è adatto qui.
In teoria, è possibile usare il nome RNN CuDNN5 per il training e sostituirlo per la distribuzione con un'operazione di modifica con un'implementazione LSTM esplicita equivalente in BrainScript.
Note
Se allowOptimizedEngine=true
quindi queste due varianti di livello sono wrapper intorno alla OptimizedRNNStack()
primitiva.
Esempio
Un classificatore di testo semplice, che esegue una sequenza di parole attraverso una ricorrenza e quindi passa l'ultimo stato nascosto del LSTM a un classificatore softmax, potrebbe avere questo formato:
w = Input{...} # word sequence (one-hot vectors)
e = EmbeddingLayer {150} (w) # embed as a 150-dimensional dense vector
h = RecurrentLSTMLayer {300} (e) # left-to-right LSTM with hidden and cell dim 300
t = BS.Sequences.Last (h) # extract last hidden state
z = DenseLayer {10000, activation=Softmax} (t) # softmax classifier
Per modificare l'esempio precedente in uno stack a 3 livelli che usa il motore RNN CuDNN5, modificare questa riga:
h = RecurrentLSTMLayerStack {(300:300:300), allowOptimizedEngine=true} (e)
Per creare un LSTM bidirezionale a un livello (ad esempio, usando la metà della dimensione nascosta rispetto a quella precedente), utilizzare questo comando:
hFwd = RecurrentLSTMLayer {150} (e)
hBwd = RecurrentLSTMLayer {150, goBackwards=true} (e)
h = Splice (hFwd:hBwd)
DelayLayer{}
Funzione Factory per creare un livello che ritarda l'input.
DelayLayer {T=1, defaultHiddenActivation=0}
Parametri
-
T
: numero di passaggi di tempo da ritardare. Per accedere ai valori futuri, usare un valore negativo -
defaultHiddenActivation
: valore da usare per i frame ritardati nei limiti
Valore restituito
Funzione che implementa l'operazione di ritardo desiderata.
Descrizione
Questa operazione ritarda una sequenza di input in base ai T
passaggi (impostazione predefinita 1).
Ciò è utile, ad esempio, per trasformare una sequenza di parole in una sequenza di parole sovrapposte triple.
Si consideri una sequenza di input "a b c b", che deve essere codificata come sequenza di vettori one-hot come indicato di seguito:
1 0 0 0
0 1 0 1
0 0 1 0
In questo caso, ogni colonna è un vettore one-hot e corrisponde a una parola.
L'applicazione DelayLayer{T=1}
a questo input genererà questa sequenza:
0 1 0 0
0 0 1 0
0 0 0 1
Tutti i token vengono ritardati di uno e la prima posizione viene compilata come vettore 0.
Analogamente, l'uso DelayLayer{T=-1}
di (ritardo negativo) consentirà l'accesso ai valori futuri e il pad a destra con zero:
0 0 0 0
1 0 1 0
0 1 0 0
Note
Questo livello è un wrapper intorno alle PastValue()
primitive e FutureValue()
.
Esempio
Di seguito viene illustrato come inserire tre parole adiacenti in un vettore di trigramma:
x = ... # input value, e.g. a N-dimensional one-hot vector
xp = DelayLayer{} (x) # previous value
xn = DelayLayer{T-1} (x) # next value (negative delay)
tg = Splice (xp : x : xn) # concatenate all into a 3N-dimensional three-hot vector
BatchNormalizationLayer{}, LayerNormalizationLayer{}, StabilizerLayer{}
Funzioni factory per creare livelli per la normalizzazione batch, la normalizzazione dei livelli e la stabilizzazione automatica.
BatchNormalizationLayer {spatialRank = 0,
normalizationTimeConstant = 5000,
initialScale = 1, epsilon = 0.00001, useCntkEngine = true}
LayerNormalizationLayer {initialScale = 1, initialBias = 0}
StabilizerLayer{}
Parametri
BatchNormalizationLayer
:
-
spatialRank
: i parametri di normalizzazione vengono inseriti in pool sulle primespatialRank
dimensioni. I valori attualmente consentiti sono 0 (nessun pooling) e 2 (pooling in tutte le posizioni pixel di un'immagine) -
normalizationTimeConstant
(valore predefinito 5000): costante temporale nei campioni del filtro a basso passaggio del primo ordine usato per calcolare le statistiche di media/varianza per l'uso nell'inferenza -
initialScale
: valore iniziale del parametro di scala -
epsilon
: valore piccolo che viene aggiunto alla stima della varianza durante il calcolo dell'inverso -
useCntkEngine
: se true, usare l'implementazione nativa di CNTK. Se false, usare l'implementazione di cuDNN (solo GPU).
LayerNormalizationLayer
:
-
initialScale
: valore iniziale del parametro di scala -
initialBias
: valore iniziale del parametro di distorsione
Valore restituito
Funzione che implementa un livello che esegue l'operazione di normalizzazione.
Descrizione
BatchNormalizationLayer{}
implementa la tecnica descritta in Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift (Sergey Ioffe, Christian Szegedy).
Normalizza gli input per ogni minibatch in base alla media/varianza del minibatch e la de normalizza con un fattore di ridimensionamento e una distorsione appresi.
In inferenza, anziché usare la media/varianza minibatch, la normalizzazione batch usa una stima media/var a lungo termine.
Questa stima viene calcolata durante il training in base alle statistiche di minibatch di filtro a basso passaggio.
La costante temporale del filtro a basso passaggio può essere modificata dal normalizationTimeConstant
parametro .
È consigliabile iniziare con il valore predefinito di (5000), ma provare con altri valori, in genere nell'ordine di diverse migliaia a decine di migliaia.
LayerNormalizationLayer{}
implementa la normalizzazione livello (Jimmy Lei Ba, Jamie Ryan Kiros, Geoffrey E. Hinton).
Normalizza ogni campione di input sottraendo la media in tutti gli elementi del campione e quindi dividendo per la deviazione standard su tutti gli elementi del campione.
StabilizerLayer{}
implementa un auto-stabilizzatore per rete neurale profonda stabilizzata (P. Ghahremani, J. Droppo).
Questa tecnica semplice ma efficace moltiplica l'input con un scalare imparabile (ma a differenza della normalizzazione del livello, non normalizza prima l'input, né sottrae una media).
Si noti che rispetto al documento originale, che propone un scalare beta
lineare o un esponenziale Exp (beta)
, abbiamo trovato utile usare un'operazione softplus affilata al secondo suggerimento dell'autore, che evita sia i valori negativi che l'instabilità dall'esponenziale.
Note
BatchNormalizationLayer{}
è un wrapper intorno alla BatchNormalization()
primitiva.
LayerNormalizationLayer{}
e StabilizerLayer{}
sono espressi direttamente in BrainScript.
Esempio
Livello tipico in una rete convoluzionale con normalizzazione batch:
MyLayer (x, depth, initValueScale) =
{
c = ConvolutionalLayer {depth, (5:5), pad=true, initValueScale=initValueScale} (x)
b = BatchNormalizationLayer {spatialRank = 2} (c) #####
r = ReLU (b)
p = MaxPoolingLayer {(3:3), stride = (2:2)} (r)
}.p
FeatureMVNLayer{}
Funzione factory per creare un livello che normalizza l'input delle funzionalità in base alla media e alla deviazione standard.
FeatureMVNLayer{}
Parametri
Elenco di argomenti {}
vuoto.
Valore restituito
Funzione che implementa un livello che esegue l'operazione di normalizzazione.
Descrizione
Questo livello normalizza l'input in una rete neurale in base alla distorsione e alla varianza. Questi valori vengono stimati in anticipo eseguendo un passaggio completo dei dati di training e quindi salvati e bloccati. Questa operazione verrà eseguita automaticamente.
Poiché i parametri di questo livello vengono precompilate in un passaggio separato prima del training principale, può essere applicato solo alle variabili dichiarate come Input{}
.
Esempio
Si tratta di un inizio tipico di una rete neurale per la modellazione acustica del parlato:
features = Input{40} # e.g. speech features
featNorm = FeatureMVNLayer{} (features)
h = DenseLayer{2048} (featNorm)
...