Dela via


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 h2kommer 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 exempel activation=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. Om pad 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 exempel lowerPad=(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. Om autoPadding 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. Om pad 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 p1och 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=truebö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 med outDim. 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 som cellShape för för RecurrentLSTMLayer() 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 liknar StabilizerLayer{}
  • 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=trueoch 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
  • 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örsta spatialRank 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)
...