示例#1
0
        static public void TrainAndEvaluate(DeviceDescriptor device)
        {
            // build a logistic regression model
            Variable featureVariable  = Variable.InputVariable(new int[] { inputDim }, DataType.Float);
            Variable labelVariable    = Variable.InputVariable(new int[] { numOutputClasses }, DataType.Float);
            var      classifierOutput = CreateLinearModel(featureVariable, numOutputClasses, device);
            var      loss             = CNTKLib.CrossEntropyWithSoftmax(classifierOutput, labelVariable);
            var      evalError        = CNTKLib.ClassificationError(classifierOutput, labelVariable);

            // prepare for training
            CNTK.TrainingParameterScheduleDouble learningRatePerSample = new CNTK.TrainingParameterScheduleDouble(
                0.02, TrainingParameterScheduleDouble.UnitType.Sample);
            IList <Learner> parameterLearners =
                new List <Learner>()
            {
                Learner.SGDLearner(classifierOutput.Parameters(), learningRatePerSample)
            };
            var trainer = Trainer.CreateTrainer(classifierOutput, loss, evalError, parameterLearners);

            int minibatchSize         = 64;
            int numMinibatchesToTrain = 1000;
            int updatePerMinibatches  = 50;

            // train the model
            for (int minibatchCount = 0; minibatchCount < numMinibatchesToTrain; minibatchCount++)
            {
                Value features, labels;
                GenerateValueData(minibatchSize, inputDim, numOutputClasses, out features, out labels, device);
                trainer.TrainMinibatch(
                    new Dictionary <Variable, Value>()
                {
                    { featureVariable, features }, { labelVariable, labels }
                }, device);
                TestHelper.PrintTrainingProgress(trainer, minibatchCount, updatePerMinibatches);
            }

            // test and validate the model
            int   testSize = 100;
            Value testFeatureValue, expectedLabelValue;

            GenerateValueData(testSize, inputDim, numOutputClasses, out testFeatureValue, out expectedLabelValue, device);

            // GetDenseData just needs the variable's shape
            IList <IList <float> > expectedOneHot = expectedLabelValue.GetDenseData <float>(labelVariable);
            IList <int>            expectedLabels = expectedOneHot.Select(l => l.IndexOf(1.0F)).ToList();

            var inputDataMap = new Dictionary <Variable, Value>()
            {
                { featureVariable, testFeatureValue }
            };
            var outputDataMap = new Dictionary <Variable, Value>()
            {
                { classifierOutput.Output, null }
            };

            classifierOutput.Evaluate(inputDataMap, outputDataMap, device);
            var outputValue = outputDataMap[classifierOutput.Output];
            IList <IList <float> > actualLabelSoftMax = outputValue.GetDenseData <float>(classifierOutput.Output);
            var actualLabels = actualLabelSoftMax.Select((IList <float> l) => l.IndexOf(l.Max())).ToList();
            int misMatches   = actualLabels.Zip(expectedLabels, (a, b) => a.Equals(b) ? 0 : 1).Sum();

            Console.WriteLine($"Validating Model: Total Samples = {testSize}, Misclassify Count = {misMatches}");
        }
示例#2
0
        /// <summary>
        /// Train and evaluate a image classifier for MNIST data.
        /// </summary>
        /// <param name="device">CPU or GPU device to run training and evaluation</param>
        /// <param name="useConvolution">option to use convolution network or to use multilayer perceptron</param>
        /// <param name="forceRetrain">whether to override an existing model.
        /// if true, any existing model will be overridden and the new one evaluated.
        /// if false and there is an existing model, the existing model is evaluated.</param>
        public static void TrainAndEvaluate(DeviceDescriptor device, bool useConvolution, bool forceRetrain)
        {
            var      featureStreamName = "features";
            var      labelsStreamName  = "labels";
            var      classifierName    = "classifierOutput";
            Function classifierOutput;

            int[] imageDim   = useConvolution ? new int[] { 28, 28, 1 } : new int[] { 784 };
            int   imageSize  = 28 * 28;
            int   numClasses = 10;

            IList <StreamConfiguration> streamConfigurations = new StreamConfiguration[]
            { new StreamConfiguration(featureStreamName, imageSize), new StreamConfiguration(labelsStreamName, numClasses) };

            string modelFile = useConvolution ? "MNISTConvolution.model" : "MNISTMLP.model";

            // If a model already exists and not set to force retrain, validate the model and return.
            if (File.Exists(modelFile) && !forceRetrain)
            {
                var minibatchSourceExistModel = MinibatchSource.TextFormatMinibatchSource(
                    Path.Combine(ImageDataFolder, "Test_cntk_text.txt"), streamConfigurations);
                TestHelper.ValidateModelWithMinibatchSource(modelFile, minibatchSourceExistModel,
                                                            imageDim, numClasses, featureStreamName, labelsStreamName, classifierName, device);
                return;
            }

            // build the network
            var input = CNTKLib.InputVariable(imageDim, DataType.Float, featureStreamName);

            if (useConvolution)
            {
                var scaledInput = CNTKLib.ElementTimes(Constant.Scalar <float>(0.00390625f, device), input);
                classifierOutput = CreateConvolutionalNeuralNetwork(scaledInput, numClasses, device, classifierName);
            }
            else
            {
                // For MLP, we like to have the middle layer to have certain amount of states.
                int hiddenLayerDim = 200;
                var scaledInput    = CNTKLib.ElementTimes(Constant.Scalar <float>(0.00390625f, device), input);
                classifierOutput = CreateMLPClassifier(device, numClasses, hiddenLayerDim, scaledInput, classifierName);
            }

            var labels       = CNTKLib.InputVariable(new int[] { numClasses }, DataType.Float, labelsStreamName);
            var trainingLoss = CNTKLib.CrossEntropyWithSoftmax(new Variable(classifierOutput), labels, "lossFunction");
            var prediction   = CNTKLib.ClassificationError(new Variable(classifierOutput), labels, "classificationError");

            // prepare training data
            var minibatchSource = MinibatchSource.TextFormatMinibatchSource(
                Path.Combine(ImageDataFolder, "Train_cntk_text.txt"), streamConfigurations, MinibatchSource.InfinitelyRepeat);

            var featureStreamInfo = minibatchSource.StreamInfo(featureStreamName);
            var labelStreamInfo   = minibatchSource.StreamInfo(labelsStreamName);

            // set per sample learning rate
            CNTK.TrainingParameterScheduleDouble learningRatePerSample = new CNTK.TrainingParameterScheduleDouble(
                0.003125, TrainingParameterScheduleDouble.UnitType.Sample);

            IList <Learner> parameterLearners = new List <Learner>()
            {
                Learner.SGDLearner(classifierOutput.Parameters(), learningRatePerSample)
            };
            var trainer = Trainer.CreateTrainer(classifierOutput, trainingLoss, prediction, parameterLearners);

            //
            const uint minibatchSize = 64;
            int        outputFrequencyInMinibatches = 20, i = 0;
            int        epochs = 5;

            while (epochs > 0)
            {
                var minibatchData = minibatchSource.GetNextMinibatch(minibatchSize, device);
                var arguments     = new Dictionary <Variable, MinibatchData>
                {
                    { input, minibatchData[featureStreamInfo] },
                    { labels, minibatchData[labelStreamInfo] }
                };

                trainer.TrainMinibatch(arguments, device);
                TestHelper.PrintTrainingProgress(trainer, i++, outputFrequencyInMinibatches);

                // MinibatchSource is created with MinibatchSource.InfinitelyRepeat.
                // Batching will not end. Each time minibatchSource completes an sweep (epoch),
                // the last minibatch data will be marked as end of a sweep. We use this flag
                // to count number of epochs.
                if (TestHelper.MiniBatchDataIsSweepEnd(minibatchData.Values))
                {
                    epochs--;
                }
            }

            // save the trained model
            classifierOutput.Save(modelFile);

            // validate the model
            var minibatchSourceNewModel = MinibatchSource.TextFormatMinibatchSource(
                Path.Combine(ImageDataFolder, "Test_cntk_text.txt"), streamConfigurations, MinibatchSource.FullDataSweep);

            TestHelper.ValidateModelWithMinibatchSource(modelFile, minibatchSourceNewModel,
                                                        imageDim, numClasses, featureStreamName, labelsStreamName, classifierName, device);
        }