Delen via


Hoe kan ik modellen trainen in BrainScript

Laagswijs trainen

Als u laagsgewijze training wilt uitvoeren, gebruikt u eenvoudig meerdere 'opdrachten' in uw configuratiebestand, waarbij elke opdracht van het type action=train is.

command = TrainLayer1:TrainLayer2:TrainLayer3:EndToEndTrain:Test:Output

TrainLayer1= [ 
   action = train
   ...
]

TrainLayer2= [ 
   action = train
   ...
]
...

Trainen met een multitaskdoelstelling

U kunt uw gecombineerde criterium alleen definiëren als een BrainScript-expressie en u kunt alle afzonderlijke taakverlies bewaken door ze op te geven als evaluationNodes.

task1loss = CrossEntropyWithSoftMax(prediction,label)
task2loss = SquareError(reconstruction,input)
mtloss = task1loss + Constant(0.3) .* task2loss 
criterionNodes = (mtloss)
evaluationNodes = (task1loss:task2loss)

Een regressiemodel trainen op afbeeldingen

Hieronder wordt beschreven hoe u een of meer drijvendekommawaarden voor een invoerafbeelding voorspelt met behulp van CNTK. Een voorbeeld van een use-case is het voorspellen van een begrenzingsvak, bijvoorbeeld (x, y, w, h), van een object in een bepaalde afbeelding. U kunt ook de prijs voor een auto voorspellen door naar een afbeelding van die auto te kijken (zou eigenlijk interessant zijn). Hier gebruiken we een heel eenvoudig voorbeeld waarin we een netwerk trainen om de gemiddelde RGB-waarden van een afbeelding te voorspellen (genormaliseerd tot [0, 1]). Dezelfde stappen zijn echter van toepassing op andere use cases. Deze stappen zijn:

  1. Definieer zowel de afbeelding als de aardwaarregressielabels als invoer voor uw netwerk
  2. Definieer een netwerk dat een overeenkomend aantal waarden voorspelt w.r.t. uw regressielabels
  3. Een verliesfunctie definiëren die de voorspelde waarden vergelijkt met de grondwaar
  4. Pas de sectie Lezer in uw .cntk-configuratiebestand aan om zowel afbeeldings- als regressielabels te lezen

U kunt het als volgt doen. Het volledige configuratiebestand is opgenomen in de map Voorbeelden op Examples/Image/Regression/RegrSimple_CIFAR10.cntk. Deze map bevat ook de scripts om de afbeeldingsgegevens te downloaden en de regressiegrondwaar te genereren voor training en testen.

1-3) Invoer, netwerk- en verliesfunctie definiëren:

    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)
    ]
  1. Een samengestelde lezer definiëren met zowel ImageReader als 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" }
            }
        })
    }

De lezer is een samengestelde lezer die de ImageReader gebruikt om afbeeldingen te lezen en de CNTKTextFormatReader om de regressie grond waarheidslabels te lezen. Dit doet u door een matrix van deserializers (met behulp van {...} : {...}) te definiëren en de invoer toe te wijzen zoals gedefinieerd in het bovenstaande netwerk (cf. functies en regrLabels).

Zie Voorbeelden/Afbeelding/Diverse/CIFAR-10/06_RegressionSimple.cntk voor het volledige configuratiebestand en de bijbehorende leesmij in die map voor het uitvoeren van het voorbeeld.

Een classificatie met meerdere labels trainen

Voor classificatie met meerdere labels moet u het gebruik van CrossEntropy vermijden, omdat deze alleen invoervectoren kan verwerken die som tot 1. Een verstandig alternatief is het gebruik van een som van logistieke verliesfuncties, één voor elke uitvoer

...
probabilities = DenseLayer {outputSize, activation=Sigmoid} (hidden)
logisticLoss = Logistic (multiLabels, probabilities)
trainingCriterion = (logisticLoss)
...

Naast het verlies zelf wilt u mogelijk andere metrische gegevens bewaken, zoals het aantal onjuiste voorspellingen. Er is geen ingebouwde expressie voor dit, maar deze kan worden uitgedrukt als

...
hammingLoss (y, p) = ReduceSum (y != (p > 0.5))
hl = hammingLoss(multiLabels,probabilities)
evaluationNodes = (hl)
...

Dit telt het aantal keren dat y[i] het niet eens is met p[i]>0,5.

Aan de slag met reeksmodellering

In dit praktijklab worden de belangrijkste ingrediënten beschreven voor het aan de slag gaan met reeksverwerking, zoals de CNTK-tekstindeling en hoe u de lezer configureert voor het gebruik van korte aliassen voor de verschillende invoerreeksen. In het voorbeeld van grapheme-to-phoneme (G2P) ziet u een werkelijke takenreeks-naar-reeks.

Een belangrijk probleem bij het sequentie-naar-reeksmodelleren is het decoderen van testgegevens met zoekfunctie voor balken. Dit kan worden gedaan in een sectie van uw configuratie waarbij de actie op het hoogste niveau 'schrijven' is. Voor decodering is een zoekopdracht vereist naar de meest waarschijnlijke reeks uitvoer. CNTK heeft een beam search decoder terwijl u als volgt kunt bellen

BrainScriptNetworkBuilder = (BS.Seq2Seq.BeamSearchSequenceDecoderFrom (
                                        BS.Network.Load (decodeModelPath), beamSize))

en voert zoekbalken uit met de opgegeven grootte van de balk. Voor een straalgrootte van 1 is er een gespecialiseerde greedy decoder

BrainScriptNetworkBuilder = (BS.Seq2Seq.GreedySequenceDecoderFrom (
                                        BS.Network.Load (decodeModelPath)))

Beide decoders hebben specifieke vereisten voor het netwerk, zoals wordt weergegeven in het G2P-voorbeeld

Een DSSM-model (of een convolutionele DSSM)-model trainen

DSSM (of Deep Semantic Similarity Model) is een DNN-model dat is getraind op paren van brondoelteksten, voor het leren van een ruimte voor het insluiten van korte tekst, waar relevante bron- en doeltekstparen dichter bij elkaar staan. De tekstinvoer voor het model wordt vertegenwoordigd door de vooraf berekende trigram-hash (zie : Huang et al.). Voor C-DSSM wordt de trigram-hash per woord berekend en vervolgens samengevoegd in de volgorde waarin de woorden in de tekst voorkomen. De invoer voor beide modellen is van vaste grootte. Als we 50K-trigrammen overwegen, is de DSSM-invoer die overeenkomt met de bron en de doeltekst elk een vector van lengte 50K. Voor C-DSSM zou de vector de lengte 50K x n hebben, waarbij de eerste n-1 woordvectoren worden samengevoegd en de nde vector een som bevat van de vectoren die overeenkomen met alle resterende woorden in de tekst. Als de tekst minder dan n woorden bevat, wordt de rest van de vector opgevuld met nullen. Als u een analogie met afbeelding wilt tekenen, kunt u de tekstinvoer voor C-DSSM beschouwen als een afbeelding met dimensies 10x1 en 50K-kanalen die zijn opgeslagen in een [C x H x W] indeling.

In dit voorbeeld ziet u hoe u een DSSM-/C-DSSM-model traint met behulp van CNTKTextFormatReader. De gegevens moeten 2 functies (bron- en doeltekst) en 1 label bevatten (dat altijd is ingesteld op de waarde 1 in de trainingsgegevens, omdat deze alleen positieve steekproeven bevat– tijdens het trainen worden de negatieve doelvoorbeelden gegenereerd door willekeurige steekproeven). Dit is de configuratie van de lezer,

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" }
        }
    })
}

Een voorbeeld van de invoergegevens,

|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

En ten slotte de netwerkdefinitie,

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")
}

Opmerking:

  • Hoewel C-DSSM consistent beter presteert dan DSSM, traint het ook langzamer (soms tot 5-10x langzamer). In sommige gevallen krijgt u dus betere prestaties van DSSM in dezelfde trainingstijd door meer gegevens te trainen (of voor meer tijdvakken).
  • De oorspronkelijke DSSM/C-DSSM is getraind op query- en documenttitelparen. Maar u kunt andere relaties tussen korte teksten leren door te trainen op andere soorten gegevens, zoals sessiequeryparen of paren voorvoegselvoorvoegsels.

Een automatisch coderingsprogramma voor afbeeldingen trainen met behulp van deconvolution en unpooling

Hier vindt u instructies.

Objectdetectie trainen met fast R CNN

Hier vindt u instructies.