Partager via


Comment faire entraîner des modèles dans BrainScript

Formation par couches

Pour effectuer une formation au niveau de la couche, utilisez simplement plusieurs « commandes » dans votre fichier de configuration, où chaque commande est de type action=train.

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

TrainLayer1= [ 
   action = train
   ...
]

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

Effectuer un apprentissage avec un objectif multitask

Vous pouvez simplement définir votre critère combiné en tant qu’expression BrainScript et vous pouvez surveiller toutes les pertes de tâches individuelles en les spécifiant comme evaluationNodes.

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

Entraîner un modèle de régression sur des images

Nous décrivons ci-dessous comment prédire une ou plusieurs valeurs à virgule flottante pour une image d’entrée à l’aide de CNTK. Un exemple de cas d’usage consiste à prédire un cadre englobant, par exemple comme (x, y, w, h), d’un objet dans une image donnée. Vous pourriez également penser à prédire le prix d’une voiture juste en regardant une image de cette voiture (serait intéressant en fait). Ici, nous utilisons un exemple très simple dans lequel nous effectuons l’apprentissage d’un réseau pour prédire les valeurs RVB moyennes d’une image (normalisées à [0, 1]). Toutefois, les mêmes étapes s’appliquent à d’autres cas d’usage. Ces étapes sont les suivantes :

  1. Définir à la fois l’image et les étiquettes de régression de vérité de base comme entrées de votre réseau
  2. Définissez un réseau qui prédit un nombre correspondant de valeurs w.r.t. vos étiquettes de régression
  3. Définir une fonction de perte qui compare les valeurs prédites à la vérité de base
  4. Adapter la section lecteur dans votre fichier de configuration .cntk pour lire les étiquettes d’image et de régression

Voici comment vous pouvez le faire. Le fichier de configuration complet est inclus dans le dossier Examples/Image/Regression/RegrSimple_CIFAR10.cntk. Ce dossier contient également les scripts permettant de télécharger les données d’image et de générer la vérité de base de régression pour l’entraînement et le test.

1-3) Définition des entrées, du réseau et de la fonction de perte :

    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. Définition d’un lecteur composite à l’aide de ImageReader et 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" }
            }
        })
    }

Le lecteur est un lecteur composite qui utilise ImageReader pour lire des images et CNTKTextFormatReader pour lire les étiquettes de vérité de base de régression. Il le fait en définissant un tableau de désérialiseurs (à l’aide {...} : {...}) et en affectant les entrées telles que définies dans le réseau ci-dessus (cf. caractéristiques et regrLabels).

Consultez Exemples/Image/Divers/CIFAR-10/06_RegressionSimple.cntk pour le fichier config complet et le fichier Readme correspondant dans ce dossier pour l’exécution de l’exemple.

Entraîner un classifieur à étiquettes multiples

Pour la classification à plusieurs étiquettes, vous devez éviter d’utiliser CrossEntropy, car il ne peut gérer que les vecteurs d’entrée qui se résument à 1. Une alternative raisonnable consiste à utiliser une somme de fonctions de perte logistique, une pour chaque sortie

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

En dehors de la perte elle-même, vous pouvez surveiller d’autres métriques, telles que le nombre de prédictions incorrectes. Il n’existe aucune expression intégrée pour cela, mais elle peut être exprimée comme

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

Cela compte le nombre de fois où y[i] n’est pas d’accord avec p[i]>0,5.

Prise en main de la modélisation séquentielle

Ce laboratoire pratique décrit les principaux ingrédients pour commencer à traiter des séquences, comme le format de texte CNTK et comment configurer le lecteur pour utiliser des alias courts pour les différentes séquences d’entrée. L’exemple graphème à phonème (G2P) illustre une tâche de séquence à séquence réelle.

Un problème important pour la modélisation de séquence à séquence consiste à décoder les données de test avec la recherche de faisceaux. Cette opération peut être effectuée dans une section de votre configuration où l’action de niveau supérieur est « write ». Le décodage nécessite une recherche de la séquence de sorties la plus probable. CNTK a un décodeur de recherche de faisceaux , tandis que vous pouvez appeler comme ceci

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

et exécutera la recherche de faisceau avec la taille de faisceau spécifiée. Pour une taille de faisceau de 1, il existe un décodeur gourmand spécialisé

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

Les deux décodeurs ont des exigences spécifiques pour le réseau, comme indiqué dans l’exemple G2P

Entraîner un modèle DSSM (ou DSSM convolutionnel)

DSSM (ou modèle de similarité sémantique profonde) est un modèle DNN formé sur des paires de textes cibles source, pour apprendre un espace d’incorporation de texte court dans lequel les paires de texte source et cible pertinentes sont plus proches. L’entrée de texte du modèle est représentée par leur hachage de trigramme précalcalisé (voir , Huang et al.). Pour C-DSSM, le hachage trigramme est calculé par mot, puis concaténé dans l’ordre dans lequel les mots se produisent dans le texte. L’entrée des deux modèles est de taille fixe. Si nous considérons 50 000 trigrammes, l’entrée DSSM correspondant à la source et le texte cible serait un vecteur de longueur 50 000 chacun. Pour C-DSSM, le vecteur serait de longueur 50 000 x n, où les premiers vecteurs de mots n-1 sont concaténés, et le nième vecteur contient une somme des vecteurs correspondant à tous les mots restants dans le texte. S’il y a moins de n mots dans le texte, le reste du vecteur est rempli de zéros. Pour dessiner une analogie avec l’image, vous pouvez considérer l’entrée de texte pour C-DSSM comme une image avec des dimensions 10x1 et 50 000 canaux stockés dans un [C x H x W] format.

Cet exemple montre comment entraîner un modèle DSSM / C-DSSM à l’aide de CNTKTextFormatReader. Les données doivent contenir 2 caractéristiques (texte source et cible) et 1 étiquette (qui est toujours définie sur la valeur 1 dans les données d’apprentissage, car elles contiennent uniquement des échantillons positifs , pendant l’entraînement, les exemples cibles négatifs sont générés par un échantillonnage aléatoire). Voici la configuration du lecteur,

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

Exemple de données d’entrée,

|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

Enfin, la définition du réseau,

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

Remarque :

  • Bien que C-DSSM ait été démontré qu’il était toujours plus performant que DSSM, il entraîne également plus lent (parfois jusqu’à 5 à 10x plus lents). Par conséquent, dans certains cas, vous pouvez obtenir de meilleures performances à partir de DSSM dans le même temps d’entraînement en effectuant l’entraînement sur plus de données (ou pour plus d’époques).
  • Le DSSM / C-DSSM d’origine a été formé sur les paires de titres de requête et de document. Toutefois, vous pouvez apprendre d’autres relations entre des textes courts en effectuant une formation sur d’autres types de données, tels que des paires de requêtes de session ou des paires préfixe-suffixe de requête.

Entraîner un encodeur automatique d’image à l’aide de la décovolution et du dépooling

Il existe des instructions ici.

Entraîner la détection d’objets à l’aide de Fast R CNN

Il existe des instructions ici.