Lagerreferens med BrainScript
CNTK fördefinierade ett antal vanliga "lager", vilket gör det mycket enkelt att skriva enkla nätverk som består av standardskikt skiktade ovanpå varandra.
Lager är funktionsobjekt som kan användas som vanliga BrainScript-funktioner men som innehåller inlärningsbara parametrar och har ytterligare ett par {}
för att skicka byggparametrar eller attribut.
Det här är till exempel nätverksbeskrivningen för en enkel 1-dold lagermodell med hjälp av DenseLayer{}
lagret:
h = DenseLayer {1024, activation=ReLU} (features)
p = DenseLayer {9000, activation=Softmax} (h)
som sedan kan användas för träning mot ett korsentropy-kriterium:
ce = CrossEntropy (labels, p)
Om nätverket är en rak sammanlänkning av åtgärder (många är det) kan du använda alternativet
Sequential()
Notation:
myModel = Sequential (
DenseLayer {1024, activation=ReLU} :
DenseLayer {9000, activation=Softmax}
)
och anropa den så här:
p = myModel (features)
Exempelmodeller
Följande visar en facktaggerare som bäddar in en ordsekvens, bearbetar den med en återkommande LSTM och klassificerar sedan varje ord:
taggingModel = Sequential (
EmbeddingLayer {150} : # embed into a 150-dimensional vector
RecurrentLSTMLayer {300} : # forward LSTM
DenseLayer {labelDim} # word-wise classification
)
Och följande är ett enkelt convolutional-nätverk för bildigenkänning:
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}
)
Parameterdelning
Om du tilldelar ett lager till en variabel och använder den på flera platser delas parametrarna. Om du säger
lay = DenseLayer {1024, activation=Sigmoid}
h1 = lay (x)
h2 = lay (h1) # same weights as `h1`
h1
och h2
kommer att dela samma parametrar, som lay()
är samma funktion i båda fallen.
I ovanstående fall är detta förmodligen inte vad som önskades, så var medveten.
Om båda anropen lay()
ovan är avsedda att ha olika parametrar, kom ihåg att definiera två separata instanser, till exempel lay1 = DenseLayer{...}
och lay2 = DenseLayer{...}
.
Så varför det här beteendet?
Skikt tillåter att parametrar delas mellan delar av en modell.
Överväg en DSSM-modell som bearbetar två indatabilder, till exempel doc
och query
identiskt med samma bearbetningskedja, och jämför de resulterande dolda vektorerna:
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)
där imageToVec
är den del av modellen som konverterar bilder till platt vektor.
imageToVec
är ett funktionsobjekt som i sin tur innehåller flera funktionsobjekt (t.ex. tre instanser av ConvolutionalLayer{}
).
imageToVec
instansieras en gång och den här instansen innehåller de inlärbara parametrarna för alla inkluderade funktionsobjekt. Båda anropen av model()
kommer att dela dessa parametrar i programmet, och deras toningar blir summan av båda anropen.
Observera slutligen att om i exemplet query
ovan och doc
måste ha samma dimensioner, eftersom de bearbetas via samma funktionsobjekt, och det funktionsobjektets första lager har sin indatadimension som härleds för att matcha både query
och doc
.
Om deras dimensioner skiljer sig åt är det här nätverket felaktigt och dimensionsinferensen/valideringen misslyckas med ett felmeddelande.
Implementeringsanteckning
Många lager är omslutna kring underliggande CNTK primitiver, tillsammans med respektive obligatoriska inlärningsparametrar. Till exempel ConvolutionalLayer{}
omsluter det Convolution()
primitiva.
Fördelarna med att använda lager är:
- lager innehåller läsbara parametrar för rätt dimension
- lager är skrivbara (jfr.
Sequential()
)
DenseLayer{}, LinearLayer{}
Factory-funktion för att skapa ett helt anslutet lager.
DenseLayer{}
tar med en valfri icke-linjäritet.
DenseLayer {outDim, activation=Identity, init='glorotUniform', initValueScale=1, bias=true}
LinearLayer {outDim, init='glorotUniform', initValueScale=1, bias=true}
Parametrar
-
outDim
: utdatadimensionen för det här lagret -
activation
(DenseLayer{}
endast): skicka en funktion här för att användas som aktiveringsfunktion, till exempelactivation=ReLU
-
init
('heNormal'
|'glorotUniform'
|...): typ av initiering för vikterna. Se här för en fullständig lista över initieringsalternativ. -
initValueScale
: variansen för slumpmässig initiering multipliceras med -
bias
: om falskt, ta inte med en bias-parameter
Returvärde
En funktion som implementerar det önskade fullständigt anslutna lagret. Se beskrivningen.
Description
Använd de här fabriksfunktionerna för att skapa ett helt anslutet lager.
Använd DenseLayer{}
om du vill att en aktiveringsfunktion ska inkluderas, annars LinearLayer{}
.
Var och en av dessa fabriksfunktioner skapar ett funktionsobjekt som innehåller en lärbar viktmatris och, om inte bias=false
, en lärbar bias. Funktionsobjektet kan användas som en funktion, som implementerar en av följande formler:
DenseLayer{...} (v) = activation (W * v + b)
LinearLayer{...} (v) = W * v + b
där W
är en viktmatris av dimensionen [outDim x (dimension of v)]
, b
är dimensionens [outdim]
bias och det resulterande värdet har dimension (eller tensordimensioner) enligt outDim
.
Tensor-stöd
Om den returnerade funktionen tillämpas på indata från en tensor-rangordning > 1, t.ex. en 2D-avbildning, W
kommer att ha dimensionen [outDim x (first dimension of input) x (second dimension of input) x ...]
.
Å andra sidan outDim
kan vara en vektor som anger tensor-dimensioner, till exempel (10:10)
.
I så fall W
har dimensionen [outDim[0] x outDim[1] x ... x (dimension of input)]
, och b
har tensor-dimensionerna [outDim[0] x outDim[1] x ...]
.
CNTK matrisprodukt tolkar dessa extra utdata- eller indatadimensioner som om de plattas ut till en lång vektor.
Mer information om detta finns i dokumentationen om Times()
Exempel:
h = DenseLayer {1024, activation=Sigmoid) (v)
eller alternativt:
Layer = DenseLayer {1024, activation=Sigmoid)
h = Layer (v)
ConvolutionalLayer{}
Skapar ett faltningslager med valfri icke-linjäritet.
ConvolutionalLayer {numOutputChannels, filterShape,
activation = Identity,
init = 'glorotUniform', initValueScale = 1,
stride = 1, pad = false, lowerPad = 0, upperPad = 0,
bias = true}
Parametrar
-
numOutputChannels
: antal utdatakanaler (antal filter) -
filterShape
: filtrets rumsliga omfattning, t.ex.(5:5)
för ett 2D-filter. Dimensionen input-channel ska inte inkluderas här. -
activation
: valfri icke-linjäritet, t.ex.activation=ReLU
-
init
('heNormal'
|'glorotUniform'
|...): typ av slumpmässig initiering för vikterna. Se här för en fullständig lista över alternativ för slumpmässig initiering. -
initValueScale
: variansen för slumpmässig initiering multipliceras med -
stride
: öka när du skjuter filtret över indata. T.ex.(2:2)
för att minska dimensionerna med 2 -
pad
: om det inte anges (standard) flyttas filtret över det "giltiga" området för indata, det vill sa att inget värde utanför området används. Ompad
anges å andra sidan tillämpas filtret på alla indatapositioner och värden utanför den giltiga regionen betraktas som noll. -
lowerPad
,upperPad
: ange uttryckligen olika marginaler för utfyllnad. Filter flyttas över en giltig region som (praktiskt taget) utökas med nollor. Till exempellowerPad=(1:2)
läggs en kolumn med nolla och två rader med noll. Dimensionen för utdata utökas i enlighet med detta. -
bias
: om falskt, ta inte med en bias-parameter
Returvärde
En funktion som implementerar det önskade fullständigt anslutna lagret. Se beskrivningen.
Description
Använd de här fabriksfunktionerna för att skapa ett skikt för decentralisering.
Det resulterande lagret tillämpar en convolution-åtgärd på en N-dimensionell tensor.
Anroparen anger filtrets rumsliga utökning.
En uppsättning filter av en viss rumslig omfattning (t.ex. (5:5)
) korreleras med varje plats för indata (t.ex. en [640 x 480]
-storleksbild).
Förutsatt att utfyllnad är aktiverat (pad
) och steg är 1 genererar detta en utdataregion med samma dimension ([640 x 480]
).
Vanligtvis används många filter samtidigt.
numOutputChannels
anger talet, så för varje indataplats skapas en hel vektor av numOutputChannels
.
I vårt exempel ovan skulle inställningen numOutputChannels
till 64 i en [640 x 480 x 64]
tensor i storlek.
Den sista axeln kallas kanaldimensionen.
När faltning tillämpas på indata med en kanaldimension består varje filter också av vektorer för indatans kanaldimension.
När du till exempel tillämpar konvolution med en angiven rumslig filterstorlek (5:5)
på en [640 x 480 x 3]
färgbild i storlek, blir varje filter en [5 x 5 x 3]
tensor.
Alla numOutputChannels
filter som staplas tillsammans kallas kerneln.
I vårt exempel blir [5 x 5 x 3 x 64]
kernelformen .
Följande sammanfattar relationen mellan de olika dimensionerna och formerna:
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 ]
som i vårt exempel är:
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 ]
Utfyllnad
Om utfyllnad inte är aktiverat minskas utdataregionen av de gränsplatser som det inte går att tillämpa hela filterområdet på. Om du t.ex. tillämpar ett (5:5)
-extent-filter på en bild utan utfyllnad skulle de yttersta 2 raderna och kolumnerna med bildpunkter göra att filtret tillämpas utanför gränserna.
ConvolutionalLayer{}
Därför minskar dimensionerna i enlighet med detta.
En [640 x 480]
bild som är kopplad till ett (5:5)
filter utan utfyllnad lämnar en [636 x 476]
utdataregion i storlek.
Framsteg
Parametrarna stride
anger ökning av filter.
Stegvärden som är större än ett leder till en delsampling av utdataregionen.
Om du t.ex. filtrerar en [640 x 480]
bild med ett steg (2:2)
i resulterar det i en [320 x 240]
region med utfyllnad och [318 x 238]
utan utfyllnad.
Obs!
Det här lagret är en omslutning runt primitiven Convolution()
.
Filtrets kernelparametrars namn som visas i loggens valideringsavsnitt slutar i .W
.
Dimensionen visas för närvarande inte enligt [ (filterShape) x (#input channels) x numOutputChannels ]
beskrivningen ovan, utan i stället [ numOutputChannels x ((produkt över filterform) * (#input kanaler)) ]'.
Exempel:
c = ConvolutionalLayer {64, (3:3), pad = true, stride = (1:1), bias=false} (x)
DeconvLayer{}
Skapar ett decentraliseringslager.
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}
Parametrar
-
numOutputChannels
: antal utdatakanaler (antal filter) -
filterShape
: filtrets rumsliga omfattning, t.ex.(5:5)
för ett 2D-filter. Dimensionen input-channel ska inte tas med här. -
numInputChannels
: antal indatakanaler (antal filter för indatavolymen) -
bias
: om falskt, ta inte med en biasparameter -
activation
: valfri icke-linjäritet, t.ex.activation=ReLU
-
init
('heNormal'
|'glorotUniform'
|...): typ av slumpmässig initiering för vikterna. Här finns en fullständig lista över alternativ för slumpmässig initiering. -
initValueScale
: variansen för slumpmässig initiering multipliceras med -
initBias
: det ursprungliga värdet för biasen -
stride
: öka när du skjuter filtret över indata. T.ex.(2:2)
för att minska dimensionerna med 2 -
autoPadding
: om det inte har angetts (standard) flyttas filtret över det "giltiga" indataområdet, d.v.s. inget värde utanför området används. OmautoPadding
anges å andra sidan tillämpas filtret på alla indatapositioner och värden utanför den giltiga regionen betraktas som noll. -
lowerPad
,upperPad
: ange uttryckligen olika marginaler för utfyllnad för utdatavolymen, d.v.s. de som användes för indata i motsvarande faltningslager. Det är viktigt att ställa in dem i korrespondens med det faltningsliga skiktet för att uppnå samma tensordimensioner.
Returvärde
En funktion som implementerar önskat fullständigt anslutet lager. Se beskrivningen.
Description
Använd dessa fabriksfunktioner för att skapa ett decentraliseringslager.
Det resulterande lagret tillämpar en delegeringsåtgärd på en N-dimensionell tensor.
Det här lagret är en omslutning runt primitiven Convolution()
med deconv=true
.
Ett populärt användningsfall för decentralisering är att rekonstruera en bild (se här till exempel). Om decentraliseringen tar en indataregion för 2D-receptivt fält och beräknar korrelationen med ett 2D-filter, tar decentraliseringen en pixel och sprider den över en 2D-region.
Överväg ett bildfilter (.,.), en pixelplats (x,y) och ett centrerat filter [3 x 3] med följande innehåll (ingen djupdimension för funktionskartan för tillfället, d.v.s. en enda kanal):
[ . . c
a b .
. . . ]
Här är b och c vikterna för filtret, '.' Motsvarar en vikt på noll. Convolution() beräknar utdatapunkt q(x, y) på plats (x, y) som:
q(x,y) = b * p(x,y) + a * p(x-1,y) + c * p(x+1,y-1)
Deconconvolution tar bildpunkter q(x,y) och sprider dem över en region runt (x,y). Om vi använde samma filter skulle det göra följande bidrag till utdata 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)
Eftersom vi vet att samma sak gäller för alla x och y över planet kan vi uttrycka detta för 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)
eller totalt,
r(x,y) = b * q(x,y) + a * q(x+1,y) + c * q(x-1,y+1)
Detta har samma formulär som convolution ovan, förutom att filtret speglas längs båda axlarna.
Nu introducerar vi funktionskartor i mixen. Det är enkelt: I stället för att gå från indatadjup till utdatadjup går vi åt andra hållet.
Sammanfattningsvis, Convolution (W, x) == Deconconvolution (W', x), där
W : [W x H x C x K]
och
W’ = W
med dess värden omorganiserade som: [(W mirrored) x (H mirrored) x K x C]
D.v.s. vad Deconvolution() gör implicit är:
- byta ut de två djupdimensionerna (transponera)
- de rumsliga dimensionerna (omvänd ordning på data)
- Convolution() med dessa
Exempel:
deconv_A = DeconvLayer {inputDim, (5:5), cMap1, lowerPad=(2:2:0), upperPad=(2:2:0)}(unpool_A)
Ett detaljerat exempel och en genomgång finns i Automatisk avkodare för avbildning med deconvolution och Avpooling .
MaxPoolingLayer{}, AveragePoolingLayer{}
Fabriksfunktioner för att skapa ett lager för max- eller genomsnittspooler.
MaxPoolingLayer {poolShape, stride = 1, pad = false, lowerPad = 0, upperPad = 0}
AveragePoolingLayer {poolShape, stride = 1, pad = false, lowerPad = 0, upperPad = 0} =
Parametrar
-
poolShape
: regionens form som ska poolas, t.ex.(2:2)
-
stride
: öka när du skjuter poolen över indata. T.ex.(2:2)
för att minska dimensionerna med 2 -
pad
: om den inte anges (standard) flyttas poolen över det "giltiga" indataområdet, det vill sa att inget värde utanför området används. Ompad
anges å andra sidan tillämpas poolen på alla indatapositioner och värden utanför den giltiga regionen betraktas som noll. För genomsnittlig poolning inkluderar antalet för medelvärde inte vadderade värden. -
lowerPad
,upperPad
: ange uttryckligen olika marginaler för utfyllnad. Filter flyttas över en giltig region som (praktiskt taget) utökas med nollor. T.ex.lowerPad=(1:2)
kommer att lägga till en kolumn med nolla och två rader med nolla. Utdatadimensionen utökas därefter.
Returvärde
En funktion som implementerar önskat poollager. Se beskrivningen.
Description
Använd den här fabriksfunktionen för att skapa en poolåtgärd. Använd MaxPoolingLayer{}
för att beräkna det maximala värdet över värdena i poolområdet och AveragePoolingLayer{}
för att ta medelvärdet.
Poolåtgärden skjuter ett "poolfönster" över platser i en indataregion och beräknar antingen maxvärdet eller medelvärdet av värdena i respektive poolregion.
Den här åtgärden är strukturellt mycket lik faltning, förutom att den åtgärd som tillämpas på skjutfönstret är av en annan typ.
Alla överväganden gällande indatadimensioner, utfyllnad och steg gäller på samma sätt, så mer ConvolutionalLayer{}
information finns i.
Exempel:
p = MaxPoolingLayer {(3:3), stride=(2:2)} (c)
MaxUnpoolingLayer{}
Skapar ett lager med maximalt avstökande värde.
MaxUnpoolingLayer {poolShape,
stride = 1, pad = false,
lowerPad = 0, upperPad = 0}
Parametrar
-
poolShape
: regionens form som ska kopplas från ( storleken på utdataområdet ), t.ex.(2:2)
-
stride
: öka när du skjuter poolen över utdata. T.ex.(2:2)
för att öka dimensionerna med 2 -
pad
: om den inte anges (standard) flyttas poolen över det "giltiga" utdataområdet, d.v.s. inget värde utanför området används. -
lowerPad
,upperPad
: ange uttryckligen olika marginaler för utfyllnad. Filter förutsätter en giltig utdataregion som är (praktiskt taget) förhöjd.
Returvärde
En funktion som implementerar önskat skikt för avpoolning. Se beskrivningen.
Description
Använd den här fabriksfunktionen för att skapa en avpoolningsåtgärd.
Avpoolningsåtgärden är inversen till en poolåtgärd. Det kräver två indata: utdata från dess motsvarande poollager, till exempel p1
och indata för motsvarande poollager, till exempel r1
, också. Den skjuter ett "inverterade poolfönster" över platser för dess indata p1
och projicerar värdet till den positionen för utdataregionen som hade det maximala värdet i motsvarande poolåtgärd, d.v.s. i r1
. Den andra inmatningen r1
krävs i CNTK för att fastställa målet för avpoolningsåtgärden, eftersom CNTK inte lagrar så kallade växelvariabler (se här för mer information).
Exempel:
unpool_A = MaxUnpoolingLayer {(2:2), stride=(2:2)}(deconv_B, relu_A)
Ett detaljerat exempel och en genomgång finns i Automatisk avkodare för avbildning med deconvolution och Avpooling .
EmbeddingLayer{}
EmbeddingLayer {outDim,
init='glorotUniform', initValueScale=1,
embeddingPath = '', transpose = false}
Parametrar
-
outDim
: dimensionen för den önskade inbäddningsvektorn -
init
('heNormal'
|'glorotUniform'
|...): typ av initiering för vikterna. En fullständig lista över initieringsalternativ finns här. -
initValueScale
: variansen för slumpmässig initiering multipliceras med -
embeddingPath
: om detta anges läses inbäddningar inte in men läses in från en fil och uppdateras inte ytterligare under träningen -
transpose
: gör det möjligt att läsa in inbäddningar som lagras i transponerat format
Returvärde
En funktion som implementerar inbäddningsskiktet. Se beskrivningen.
Description
"Inbäddning" syftar på att representera ord eller andra diskreta objekt med täta kontinuerliga vektorer. Det här lagret förutsätter att indata är i en frekvent form. Om du till exempel har en vokabulärstorlek på 10 000 förväntas varje indatavektor ha dimensionen 10 000 och bestå av nollor förutom en position som innehåller en 1. Indexet för den platsen är indexet för det ord eller objekt som det representerar.
I CNTK lagras motsvarande inbäddningsvektorer som kolumner i en matris. Därför implementeras mappning av ett indataord till dess inbäddning som en matrisprodukt. För att detta ska vara mycket effektivt är det viktigt att indatavektorerna lagras i ett glest format.
Roligt faktum: Toningen i en inbäddningsmatris har formen av toningsvektorer som bara är icke-noll för ord som visas i en minibatch. Eftersom för realistiska vokabulärer på tiotals eller hundratusentals skulle de allra flesta kolumner vara noll, CNTK implementerar har en specifik optimering för att representera toningen i "kolumn-gles" form.
Känt problem: Ovanstående kolumnsparse gradient-form stöds för närvarande inte av vår 1-bitars SGD-parallelliseringsteknik . Använd block-momentum-tekniken i stället.
Exempel
En inbäddning som representerar ord från ett ordförråd på 87636 som en 300-dimensionell vektor:
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
Förutom sparse=true
bör man även deklarera indata som glesa i konfigurationsblocket reader
.
Här är ett exempel på läsning av gles textinmatning med CNTKTextFormatReader
:
reader = {
readerType = "CNTKTextFormatReader"
file = "en2fr.txt"
randomize = true
input = {
input = { alias = "E" ; dim = 87636 ; format = "sparse" }
labels = { alias = "F" ; dim = 98624 ; format = "sparse" }
}
}
Om inbäddningsvektorerna i stället redan finns och ska läsas in från en fil skulle det se ut så här:
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
där filen "embedding-en.txt"
förväntas bestå av 87 636 textrader, som var och en består av 300 blankstegsavgränsade tal.
Eftersom den här filen sparar inbäddningarna som rader i stället för kolumner, transpose=true
transponerar matrisen i farten.
RecurrentLSTMLayer{}, RecurrentLSTMLayerStack{}
Fabriksfunktioner för att skapa en återkommande LSTM med ett lager eller flera lager.
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}
Parametrar
-
outDim
(RecurrentLSTMLayer{}
): dimension för nätverkets utdata. Om du vill ange en tensor av rangordning>1 kan detta vara en vektor, t.ex.(40:2)
-
layerDims
(RecurrentLSTMLayerStack{}
): matris med dimensioner för nätverkets inre lager och utdata -
cellShape
( (RecurrentLSTMLayer{}
, valfritt): dimensionen för LSTM-cellen. Normalt är detta identiskt medoutDim
. Om ett annat värde anges infogas ytterligare en linjär projektion för att konvertera från celldimensionen till utdata. -
cellShapes
( (RecurrentLSTMLayerStack{}
, valfritt): matris med värden somcellShape
för förRecurrentLSTMLayer()
att ange projektion -
goBackwards
(valfritt): Om värdet är sant körs upprepningen bakåt -
usePeepholes
(valfritt): Om det är sant använder du titthålsanslutningar i LSTM -
init
('heNormal'
|'glorotUniform'
|...): typ av initiering för vikterna. En fullständig lista över initieringsalternativ finns här. -
initValueScale
: variansen för slumpmässig initiering multipliceras med -
enableSelfStabilization
(valfritt): Om det är sant infogar du en "stabilisatoråtgärd" som liknarStabilizerLayer{}
-
allowOptimizedEngine
(valfritt, standard falskt): Om det är sant använder du cuDNN:s optimerade RNN-motor där det är möjligt
Returvärde
En funktion som implementerar önskade lager som tillämpar/tillämpar en återkommande LSTM på dess indatasekvens. Det här lagret (-stack) mappar en indatasekvens till en sekvens med dolda tillstånd med samma längd.
Description
Detta implementerar den återkommande LSTM som ska tillämpas på en sekvens med indata, i två varianter: ett enda lager och en stack med flera lager. Den här åtgärden hanterar automatiskt indata med variabel längd. Det ursprungliga värdet för det dolda tillståndet och cellen är 0.
Om du tillämpar det här lagret på en indatasekvens returneras sekvensen för de dolda tillstånden för den (översta stacken) återkommande LSTM (LSTM-minnescellens värde returneras inte).
Den returnerade sekvensen har samma längd som indata.
Om endast det sista tillståndet önskas, som i sekvensklassificering eller vissa sekvens-till-sekvens-scenarier, använder BS.Sequences.Last()
du för att extrahera det sista objektets dolda tillstånd.
(I en bakåtkompatibel upprepning använder BS.Sequences.First()
du .)
Om du vill skapa en dubbelriktad modell med RecurrentLSTMLayer()
använder du två lager, ett med goBackwards=true
och Splice()
de två utdata tillsammans.
RecurrentLSTMLayerStack()
för närvarande inte stöder dubbelriktade modeller måste du manuellt konstruera den med hjälp av flera RecurrentLSTMLayer()/Splice()
kombinationer.
Använda CuDNN5 RNN-motorn
Den här funktionen använder automatiskt CuDNN5:s optimerade RNN-motor om möjligt, det vill
- den angivna modellen är en modell som kan implementeras av CuDNN5-funktionen
- ingen projektion (ingen
cellShape
parameter) - inga titthålsanslutningar
- ingen självstabilisering
- går inte bakåt
- för
RecurrentLSTMLayerStack{}
har alla lagerdimensioner samma värde
- ingen projektion (ingen
allowOptimizedEngine=true
Mer specifikt kräver CNTK att aktivera allowOptimizedEngine=true
.
Det beror på att CuDNN5 RNN implementeras som en CNTK primitiv åtgärd som kräver en GPU.
Många verkliga system använder dock GPU:er för träning men endast CPU-servrar i distributionen.
CuDNN5 RNN passar inte här.
(Det är teoretiskt möjligt att använda CuDNN5 RNN för träning och ersätta det för distribution med en redigeringsåtgärd med en motsvarande explicit LSTM-implementering i BrainScript.)
Obs!
Om allowOptimizedEngine=true
dessa två lagervarianter är omslutningar runt primitiven OptimizedRNNStack()
.
Exempel
En enkel textklassificerare, som kör en ordsekvens genom en upprepning och sedan skickar LSTM :s sista dolda tillstånd till en softmax-klassificerare, kan ha följande formulär:
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
Om du vill ändra exemplet ovan till en 3-lagersstack som använder CuDNN5 RNN-motorn ändrar du den här raden:
h = RecurrentLSTMLayerStack {(300:300:300), allowOptimizedEngine=true} (e)
Om du vill skapa en dubbelriktad enlagers LSTM (t.ex. med hälften av den dolda dimensionen jämfört med ovan) använder du följande:
hFwd = RecurrentLSTMLayer {150} (e)
hBwd = RecurrentLSTMLayer {150, goBackwards=true} (e)
h = Splice (hFwd:hBwd)
DelayLayer{}
Factory-funktionen för att skapa ett lager som fördröjer indata.
DelayLayer {T=1, defaultHiddenActivation=0}
Parametrar
-
T
: antalet tidssteg som ska fördröjas. Om du vill komma åt framtida värden använder du ett negativt värde -
defaultHiddenActivation
: värde som ska användas för de fördröjda bildrutorna vid gränserna
Returvärde
En funktion som implementerar önskad fördröjningsåtgärd.
Description
Den här åtgärden fördröjer en indatasekvens med T
steg (standard 1).
Detta är till exempel användbart för att omvandla en ordsekvens till en sekvens med överlappande ord tripplar.
Överväg en indatasekvens "a b c b", som ska kodas som en sekvens med one-hot-vektorer enligt följande:
1 0 0 0
0 1 0 1
0 0 1 0
Här är varje kolumn en het vektor och motsvarar ett ord.
Om du tillämpar DelayLayer{T=1}
på dessa indata genereras den här sekvensen:
0 1 0 0
0 0 1 0
0 0 0 1
Alla token fördröjs med en och den första positionen fylls i som en 0-vektor.
På samma sätt ger användning av DelayLayer{T=-1}
(negativ fördröjning) åtkomst till framtida värden och fyller ut från höger med noll:
0 0 0 0
1 0 1 0
0 1 0 0
Obs!
Det här lagret är en omslutning runt primitiverna PastValue()
och FutureValue()
.
Exempel
Följande visar hur du staplar tre grannord i en trigramvektor:
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{}, StabilisrLayer{}
Fabriksfunktioner för att skapa lager för batchnormalisering, lagernormalisering och självstabilisering.
BatchNormalizationLayer {spatialRank = 0,
normalizationTimeConstant = 5000,
initialScale = 1, epsilon = 0.00001, useCntkEngine = true}
LayerNormalizationLayer {initialScale = 1, initialBias = 0}
StabilizerLayer{}
Parametrar
BatchNormalizationLayer
:
-
spatialRank
: normaliseringsparametrar poolas över de förstaspatialRank
dimensionerna. För närvarande är tillåtna värden 0 (ingen poolning) och 2 (poolning över alla pixelpositioner i en bild) -
normalizationTimeConstant
(standardvärde 5 000): tidskonstant i urval av lågpassfiltret i första ordningen som används för att beräkna medelvärdes-/variansstatistik för användning i slutsatsdragning -
initialScale
: startvärdet för skalningsparametern -
epsilon
: litet värde som läggs till i avvikelseuppskattningen vid beräkning av inversen -
useCntkEngine
: Om det är sant använder du CNTK interna implementering. Om det är falskt använder du cuDNN-implementeringen (endast GPU).
LayerNormalizationLayer
:
-
initialScale
: startvärdet för skalningsparametern -
initialBias
: inledande värde för biasparameter
Returvärde
En funktion som implementerar ett lager som utför normaliseringsåtgärden.
Description
BatchNormalizationLayer{}
implementerar den teknik som beskrivs i papper Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift (Sergej Ioffe, Christian Szegedy).
Den normaliserar indata för varje minibatch med minibatch-medelvärdet/variansen och avnormaliserar den med en inlärd skalningsfaktor och bias.
I inferens använder batchnormalisering i stället för att använda minibatch-medelvärde/varians en långsiktig beräkning av medelvärdet/variansen.
Den här uppskattningen beräknas under träningen med hjälp av minibatchstatistik för lågpassfiltrering.
Tidskonstanten för lågpassfiltret kan ändras av parametern normalizationTimeConstant
.
Vi rekommenderar att du börjar med standardvärdet (5000), men experimentera med andra värden, vanligtvis i ordningen flera tusen till tiotals tusen.
LayerNormalizationLayer{}
implementerar lagernormalisering (Jimmy Lei Ba, Jamie Ryan Kiros, Geoffrey E. Hinton).
Det normaliserar varje indataexempel genom att subtrahera medelvärdet över alla element i urvalet och sedan dividera med standardavvikelsen över alla element i urvalet.
StabilizerLayer{}
implementerar en självstabilisator per självstabiliserat djupt neuralt nätverk (P. Ghahremani, J. Droppo).
Den här enkla men effektiva tekniken multiplicerar indata med en lärbar skalär (men till skillnad från lagernormalisering normaliserar den inte först indata och subtraherar inte heller ett medelvärde).
Observera att jämfört med det ursprungliga dokumentet, som föreslår en linjär skalär beta
eller en exponentiell Exp (beta)
, fann vi att det var fördelaktigt att använda en vässad softplus-åtgärd per den andra författarens förslag, vilket undviker både negativa värden och instabilitet från exponentiell.
Obs!
BatchNormalizationLayer{}
är en omslutning runt primitiven BatchNormalization()
.
LayerNormalizationLayer{}
och StabilizerLayer{}
uttrycks direkt i BrainScript.
Exempel
Ett typiskt lager i ett convolutional-nätverk med batchnormalisering:
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{}
Factory-funktion för att skapa ett lager som normaliserar funktionsindata med deras medelvärde och standardavvikelse.
FeatureMVNLayer{}
Parametrar
Tom argumentlista {}
.
Returvärde
En funktion som implementerar ett lager som utför normaliseringsåtgärden.
Description
Det här lagret normaliserar indata till ett neuralt nätverk med dess bias och varians. Dessa värden beräknas i förväg genom att utföra en fullständig genomströmning av träningsdata och sedan sparas och frysas. Detta sker automatiskt.
Eftersom det här lagrets parametrar förberäknas i ett separat pass före huvudträningen kan det bara tillämpas på variabler som deklareras som Input{}
.
Exempel
Det här är en typisk början på ett neuralt nätverk för akustisk modellering av tal:
features = Input{40} # e.g. speech features
featNorm = FeatureMVNLayer{} (features)
h = DenseLayer{2048} (featNorm)
...