Hur gör jag för att träna modeller i BrainScript
- Utför du lagervis träning?
- Träna med ett multitask-mål?
- Vill du träna en regressionsmodell på bilder?
- Träna en klassificerare med flera etiketter?
- Kom igång i följd med sekvensmodellering?
- Träna en DSSM-modell (eller en convolutional-DSSM)-modell?
- Vill du träna en automatisk avbildningskodare med delegering och avpoolning?
- Objektidentifiering med snabb R-CNN?
Lagervis träning
Om du vill utföra lagervis träning använder du helt enkelt flera "kommandon" i konfigurationsfilen, där varje kommando är av typen action=train.
command = TrainLayer1:TrainLayer2:TrainLayer3:EndToEndTrain:Test:Output
TrainLayer1= [
action = train
...
]
TrainLayer2= [
action = train
...
]
...
Träna med ett multitask-mål
Du kan bara definiera ditt kombinerade kriterium som ett BrainScript-uttryck och du kan övervaka alla enskilda aktivitetsförluster genom att ange dem som evaluationNodes
.
task1loss = CrossEntropyWithSoftMax(prediction,label)
task2loss = SquareError(reconstruction,input)
mtloss = task1loss + Constant(0.3) .* task2loss
criterionNodes = (mtloss)
evaluationNodes = (task1loss:task2loss)
Träna en regressionsmodell på bilder
Nedan beskriver vi hur du förutsäger ett eller flera flyttalsvärde för en indatabild med hjälp av CNTK. Ett exempel på ett användningsfall är att förutsäga en avgränsningsruta, till exempel (x, y, w, h) för ett objekt i en viss bild. Du kan också tänka dig att förutsäga priset för en bil bara genom att titta på en bild av den bilen (skulle vara intressant faktiskt). Här använder vi ett mycket enkelt exempel där vi tränar ett nätverk för att förutsäga de genomsnittliga RGB-värdena för en bild (normaliserat till [0, 1]). Samma steg gäller dock för andra användningsfall. De här stegen är:
- Definiera både avbildningens och grundsanningsregressionsetiketterna som indata till nätverket
- Definiera ett nätverk som förutsäger ett matchande antal värden w.r.t. dina regressionsetiketter
- Definiera en förlustfunktion som jämför de förutsagda värdena med den grundläggande sanningen
- Anpassa läsaravsnittet i konfigurationsfilen .cntk för att läsa både bild- och regressionsetiketter
Så här kan du göra det. Den fullständiga konfigurationsfilen ingår i mappen Exempel på Examples/Image/Regression/RegrSimple_CIFAR10.cntk. Mappen innehåller också skript för att ladda ned bilddata och generera regressionsgrundens sanning för träning och testning.
1–3) Definiera indata, nätverk och förlustfunktion:
BrainScriptNetworkBuilder = [
imageShape = 32:32:3
featScale = Constant(1/256)
labelDim = 3
model (features) = {
featNorm = Scale(features, featScale)
h1 = LinearLayer {100, init="gaussian", initValueScale=1.5} (featNorm)
ol = LinearLayer {labelDim, init="gaussian", initValueScale=1.5} (h1)
}.ol
# inputs
features = Input {imageShape}
regrLabels = Input {labelDim}
# apply model to features
ol = model (features)
# define regression loss
# rmse = sqrt(SquareError(regrLabels, ol) / labelDim)
sqerr = SquareError (regrLabels, ol)
rmse = Sqrt (Constant(1/labelDim).* sqerr)
featureNodes = (features)
labelNodes = (regrLabels)
criterionNodes = (rmse)
evaluationNodes = (rmse)
OutputNodes = (ol)
]
- Definiera en sammansatt läsare med både ImageReader och CNTKTextFormatReader:
reader = {
verbosity = 0 ; randomize = true
deserializers = ({
type = "ImageDeserializer" ; module = "ImageReader"
file = "$dataDir$/cifar-10-batches-py/train_map.txt"
input = {
features = { transforms = (
{ type = "Scale" ; width = 32 ; height = 32 ; channels = 3 ; interpolations = "linear" } :
{ type = "Transpose" }
)}
ignored = { labelDim = 10 }
}
} : {
type = "CNTKTextFormatDeserializer" ; module = "CNTKTextFormatReader"
file = "$dataDir$/cifar-10-batches-py/train_regrLabels.txt"
input = {
regrLabels = { dim = 3 ; format = "dense" }
}
})
}
Läsaren är en sammansatt läsare som använder ImageReader för att läsa bilder och CNTKTextFormatReader för att läsa sanningsetiketterna för regression. Det gör den genom att definiera en matris med deserialiserare (med hjälp {...} : {...}
av ) och tilldela indata enligt definitionen i nätverket ovan (jfr funktioner och regrLabels).
Se Exempel/Bild/Diverse/CIFAR-10/06_RegressionSimple.cntk för den fullständiga konfigurationsfilen och motsvarande Readme i den mappen för att köra exemplet.
Träna en fleretikettsklassificerare
För klassificering med flera etiketter bör du undvika att använda CrossEntropy eftersom det bara kan hantera indatavektorer som summeras till 1. Ett förnuftigt alternativ är att använda en summa av logistiska förlustfunktioner, en för varje utdata
...
probabilities = DenseLayer {outputSize, activation=Sigmoid} (hidden)
logisticLoss = Logistic (multiLabels, probabilities)
trainingCriterion = (logisticLoss)
...
Förutom själva förlusten kanske du vill övervaka andra mått, till exempel antalet felaktiga förutsägelser. Det finns inget inbyggt uttryck för detta, men det kan uttryckas som
...
hammingLoss (y, p) = ReduceSum (y != (p > 0.5))
hl = hammingLoss(multiLabels,probabilities)
evaluationNodes = (hl)
...
Detta räknar antalet gånger som y[i] inte håller med p[i]>0.5.
Kom igång i sekvens till sekvensmodellering
Det här praktiska labbet beskriver huvudingredienserna för att komma igång med sekvensbearbetning, till exempel CNTK-textformatet och hur du konfigurerar läsaren att använda korta alias för de olika indatasekvenserna. G2P-exemplet (grapheme-to-phoneme) visar en faktisk sekvens-till-sekvens-aktivitet.
Ett viktigt problem för sekvens-till-sekvens-modellering är hur du avkodar testdata med beam-sökning. Det kan du göra med i ett avsnitt i konfigurationen där åtgärden på den översta nivån är "write". Avkodning kräver en sökning efter den mest sannolika sekvensen av utdata. CNTK har en avkodare för beam-sökning medan du kan anropa så här
BrainScriptNetworkBuilder = (BS.Seq2Seq.BeamSearchSequenceDecoderFrom (
BS.Network.Load (decodeModelPath), beamSize))
och utför strålsökning med angiven strålstorlek. För en bjälkstorlek på 1 finns det en specialiserad girig avkodare
BrainScriptNetworkBuilder = (BS.Seq2Seq.GreedySequenceDecoderFrom (
BS.Network.Load (decodeModelPath)))
Båda avkodarna har specifika krav för nätverket, som visas i G2P-exemplet
Träna en DSSM-modell (eller en convolutional DSSM)
DSSM (eller Deep Semantic Similarity Model) är en DNN-modell som tränas på par av källmåltexter, för att lära sig ett korttextinbäddningsutrymme där relevanta käll- och måltextpar är närmare. Textinmatningen till modellen representeras av deras förberäknade trigram-hash (se Huang et al.). För C-DSSM beräknas trigram-hashen per ord och sammanfogas sedan i den ordning orden förekommer i texten. Indata för båda modellerna har fast storlek. Om vi överväger 50 000 trigram skulle DSSM-indata som motsvarar källan och måltexten vara en vektor med längden 50 K vardera. För C-DSSM skulle vektorn vara av längd 50K x n, där de första n-1 ordvektorerna sammanfogas, och den n: e vektorn innehåller en summa av de vektorer som motsvarar alla återstående ord i texten. Om det finns mindre än n ord i texten är resten av vektorn utfyllnad med nollor. Om du vill rita en analogi med en bild kan du tänka på textinmatningen för C-DSSM som en bild med dimensionerna 10 x 1 och 50 000 kanaler lagrade i ett [C x H x W]
format.
Det här exemplet visar hur du tränar en DSSM/C-DSSM-modell med CNTKTextFormatReader. Data ska innehålla 2 funktioner (käll- och måltext) och 1 etikett (som alltid anges till värdet 1 i träningsdata eftersom de endast innehåller positiva exempel – under träning genereras de negativa målexemplen genom slumpmässig sampling). Här är läsarkonfigurationen,
reader = {
verbosity = 0
randomize = true
deserializers = ({
type = "CNTKTextFormatDeserializer"
module = "CNTKTextFormatReader"
file = "data.txt"
input = {
Q = { dim = 500000; format = "sparse" }
D = { dim = 500000; format = "sparse" }
L = { dim = 1; format = "dense" }
}
})
}
Ett exempel på indata,
|L 1 |Q 482:1 761:1 1832:1 2117:1 12370:1 17131:1 17854:1 24976:1 27676:1 28055:1 28177:1 29507:1|D 482:1 761:1 1832:1 2117:1 12370:1 17131:1 17854:1 24976:1 27676:1 28055:1 28177:1 29507:1
|L 1 |Q 149:1 153:1 595:1 671:1 675:1 1110:1 1517:1 2077:1 2114:1 5533:1 5662:1 6886:1 6901:1 7294:1 12846:1 13033:1 16614:1 19425:1 22015:1 24839:1 24994:1 26196:1 26358:1 27565:1|D 149:1 153:1 595:1 671:1 675:1 1110:1 1517:1 2077:1 2114:1 5533:1 5662:1 6886:1 6901:1 7294:1 12846:1 13033:1 16614:1 19425:1 22015:1 24839:1 24994:1 26196:1 26358:1 27565:1
|L 1 |Q 187:1 2294:1 2800:1 6920:1|D 187:1 2294:1 2800:1 6920:1
Och slutligen nätverksdefinitionen,
BrainScriptNetworkBuilder = {
# Constants scalars
isConvolutional = true
numWords = (if isConvolutional then 10 else 1)
numTrigramsPerWord = 50000
numHiddenNodes = 300
wordWindowSize = 3
numWindows = numWords - wordWindowSize + 1
numNeg = 50
# Constant tensors
CONST_GAMMA = Constant(10)
CONST_SHIFT = Constant(1)
CONST_NEG = Constant(numNeg)
CONST_PAD_NEG = Constant(0, rows=numNeg, cols=1)
CONST_PAD_POS = Constant(1, rows=1, cols=1)
CONST_PAD = Splice(CONST_PAD_POS : CONST_PAD_NEG, axis=1)
# Inputs
Q = Input(500000)
D = Input(500000)
L = Input(1)
qr = if isConvolutional
then TransposeDimensions(ReshapeDimension(Q, 1, numTrigramsPerWord:1:numWords), 1, 3)
else Slice(0, numTrigramsPerWord, Q, axis=1)
dr = if isConvolutional
then TransposeDimensions(ReshapeDimension(D, 1, numTrigramsPerWord:1:numWords), 1, 3)
else Slice(0, numTrigramsPerWord, D, axis=1)
qdssm = Sequential (
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
qcdssm = Sequential (
ConvolutionalLayer {numHiddenNodes, (wordWindowSize:1), pad=false, activation=Tanh} :
MaxPoolingLayer {(numWindows:1), stride=(1:1)} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
ddssm = Sequential (
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
dcdssm = Sequential (
ConvolutionalLayer {numHiddenNodes, (wordWindowSize:1), pad=false, activation=Tanh} :
MaxPoolingLayer {(numWindows:1), stride=(1:1)} :
DenseLayer {numHiddenNodes, activation=Tanh} :
DenseLayer {numHiddenNodes, activation=Tanh})
qembed = if isConvolutional
then qcdssm
else qdssm
dembed = if isConvolutional
then dcdssm
else ddssm
qf = qembed(qr)
df = dembed(dr)
lf = Times(CONST_PAD, L)
c = CosDistanceWithNegativeSamples(qf, df, CONST_SHIFT, CONST_NEG)
s = Slice(0, 1, c, axis=1, tag="output")
ce = CrossEntropyWithSoftmax(lf, Scale(CONST_GAMMA, c), tag="criterion")
}
Obs!
- Medan C-DSSM har visat sig konsekvent prestera bättre än DSSM, tränar det också långsammare (ibland upp till 5-10x långsammare). I vissa fall kan du få bättre prestanda från DSSM på samma träningstid genom att träna över mer data (eller för fler epoker).
- Den ursprungliga DSSM/C-DSSM tränades på fråge- och dokumenttitelpar. Men du kan lära dig andra relationer mellan korta texter genom att träna på andra typer av data, till exempel sessionsfrågepar eller par med frågeprefix-suffix.
Träna en automatisk avbildningskodare med hjälp av decentralisering och avpoolning
Det finns instruktioner här.
Träna objektidentifiering med snabb R CNN
Det finns instruktioner här.