コード例 #1
0
        /// <summary>Applies the derivative of tanh to each of the elements in the vector.</summary>
        /// <remarks>Applies the derivative of tanh to each of the elements in the vector.  Returns a new matrix.</remarks>
        public static SimpleMatrix ElementwiseApplyTanhDerivative(SimpleMatrix input)
        {
            SimpleMatrix output = new SimpleMatrix(input.NumRows(), input.NumCols());

            output.Set(1.0);
            output = output.Minus(input.ElementMult(input));
            return(output);
        }
        private void BackpropDerivativesAndError(Tree tree, TwoDimensionalMap <string, string, SimpleMatrix> binaryTD, TwoDimensionalMap <string, string, SimpleMatrix> binaryCD, TwoDimensionalMap <string, string, SimpleTensor> binaryTensorTD, IDictionary
                                                 <string, SimpleMatrix> unaryCD, IDictionary <string, SimpleMatrix> wordVectorD, SimpleMatrix deltaUp)
        {
            if (tree.IsLeaf())
            {
                return;
            }
            SimpleMatrix currentVector = RNNCoreAnnotations.GetNodeVector(tree);
            string       category      = tree.Label().Value();

            category = model.BasicCategory(category);
            // Build a vector that looks like 0,0,1,0,0 with an indicator for the correct class
            SimpleMatrix goldLabel = new SimpleMatrix(model.numClasses, 1);
            int          goldClass = RNNCoreAnnotations.GetGoldClass(tree);

            if (goldClass >= 0)
            {
                goldLabel.Set(goldClass, 1.0);
            }
            double       nodeWeight  = model.op.trainOptions.GetClassWeight(goldClass);
            SimpleMatrix predictions = RNNCoreAnnotations.GetPredictions(tree);
            // If this is an unlabeled class, set deltaClass to 0.  We could
            // make this more efficient by eliminating various of the below
            // calculations, but this would be the easiest way to handle the
            // unlabeled class
            SimpleMatrix deltaClass = goldClass >= 0 ? predictions.Minus(goldLabel).Scale(nodeWeight) : new SimpleMatrix(predictions.NumRows(), predictions.NumCols());
            SimpleMatrix localCD    = deltaClass.Mult(NeuralUtils.ConcatenateWithBias(currentVector).Transpose());
            double       error      = -(NeuralUtils.ElementwiseApplyLog(predictions).ElementMult(goldLabel).ElementSum());

            error = error * nodeWeight;
            RNNCoreAnnotations.SetPredictionError(tree, error);
            if (tree.IsPreTerminal())
            {
                // below us is a word vector
                unaryCD[category] = unaryCD[category].Plus(localCD);
                string word = tree.Children()[0].Label().Value();
                word = model.GetVocabWord(word);
                //SimpleMatrix currentVectorDerivative = NeuralUtils.elementwiseApplyTanhDerivative(currentVector);
                //SimpleMatrix deltaFromClass = model.getUnaryClassification(category).transpose().mult(deltaClass);
                //SimpleMatrix deltaFull = deltaFromClass.extractMatrix(0, model.op.numHid, 0, 1).plus(deltaUp);
                //SimpleMatrix wordDerivative = deltaFull.elementMult(currentVectorDerivative);
                //wordVectorD.put(word, wordVectorD.get(word).plus(wordDerivative));
                SimpleMatrix currentVectorDerivative = NeuralUtils.ElementwiseApplyTanhDerivative(currentVector);
                SimpleMatrix deltaFromClass          = model.GetUnaryClassification(category).Transpose().Mult(deltaClass);
                deltaFromClass = deltaFromClass.ExtractMatrix(0, model.op.numHid, 0, 1).ElementMult(currentVectorDerivative);
                SimpleMatrix deltaFull      = deltaFromClass.Plus(deltaUp);
                SimpleMatrix oldWordVectorD = wordVectorD[word];
                if (oldWordVectorD == null)
                {
                    wordVectorD[word] = deltaFull;
                }
                else
                {
                    wordVectorD[word] = oldWordVectorD.Plus(deltaFull);
                }
            }
            else
            {
                // Otherwise, this must be a binary node
                string leftCategory  = model.BasicCategory(tree.Children()[0].Label().Value());
                string rightCategory = model.BasicCategory(tree.Children()[1].Label().Value());
                if (model.op.combineClassification)
                {
                    unaryCD[string.Empty] = unaryCD[string.Empty].Plus(localCD);
                }
                else
                {
                    binaryCD.Put(leftCategory, rightCategory, binaryCD.Get(leftCategory, rightCategory).Plus(localCD));
                }
                SimpleMatrix currentVectorDerivative = NeuralUtils.ElementwiseApplyTanhDerivative(currentVector);
                SimpleMatrix deltaFromClass          = model.GetBinaryClassification(leftCategory, rightCategory).Transpose().Mult(deltaClass);
                deltaFromClass = deltaFromClass.ExtractMatrix(0, model.op.numHid, 0, 1).ElementMult(currentVectorDerivative);
                SimpleMatrix deltaFull      = deltaFromClass.Plus(deltaUp);
                SimpleMatrix leftVector     = RNNCoreAnnotations.GetNodeVector(tree.Children()[0]);
                SimpleMatrix rightVector    = RNNCoreAnnotations.GetNodeVector(tree.Children()[1]);
                SimpleMatrix childrenVector = NeuralUtils.ConcatenateWithBias(leftVector, rightVector);
                SimpleMatrix W_df           = deltaFull.Mult(childrenVector.Transpose());
                binaryTD.Put(leftCategory, rightCategory, binaryTD.Get(leftCategory, rightCategory).Plus(W_df));
                SimpleMatrix deltaDown;
                if (model.op.useTensors)
                {
                    SimpleTensor Wt_df = GetTensorGradient(deltaFull, leftVector, rightVector);
                    binaryTensorTD.Put(leftCategory, rightCategory, binaryTensorTD.Get(leftCategory, rightCategory).Plus(Wt_df));
                    deltaDown = ComputeTensorDeltaDown(deltaFull, leftVector, rightVector, model.GetBinaryTransform(leftCategory, rightCategory), model.GetBinaryTensor(leftCategory, rightCategory));
                }
                else
                {
                    deltaDown = model.GetBinaryTransform(leftCategory, rightCategory).Transpose().Mult(deltaFull);
                }
                SimpleMatrix leftDerivative  = NeuralUtils.ElementwiseApplyTanhDerivative(leftVector);
                SimpleMatrix rightDerivative = NeuralUtils.ElementwiseApplyTanhDerivative(rightVector);
                SimpleMatrix leftDeltaDown   = deltaDown.ExtractMatrix(0, deltaFull.NumRows(), 0, 1);
                SimpleMatrix rightDeltaDown  = deltaDown.ExtractMatrix(deltaFull.NumRows(), deltaFull.NumRows() * 2, 0, 1);
                BackpropDerivativesAndError(tree.Children()[0], binaryTD, binaryCD, binaryTensorTD, unaryCD, wordVectorD, leftDerivative.ElementMult(leftDeltaDown));
                BackpropDerivativesAndError(tree.Children()[1], binaryTD, binaryCD, binaryTensorTD, unaryCD, wordVectorD, rightDerivative.ElementMult(rightDeltaDown));
            }
        }