65.9K
CodeProject 正在变化。 阅读更多。
Home

Train Iris Data by Batch using CNTK and C#

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2017年11月14日

CPOL

2分钟阅读

viewsIcon

10268

如何使用 CNTK 和 C# 按批次训练 Iris 数据

在之前的文章中,我们已经了解了如何使用 MinibatchSource 训练神经网络模型。通常,当数据量很大时,我们应该使用它。如果数据量较小,可以将所有数据加载到内存中,并在每次迭代中传递所有数据以训练模型。 这篇博文将实现这种向训练器提供数据的方式。

我们将重用之前的实现,因此起点可以是之前的源代码。对于数据加载,我们需要定义一个新的方法。Iris 数据以如下文本格式存储

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa(1 0 0)
7.0,3.2,4.7,1.4,versicolor(0 1 0)
7.6,3.0,6.6,2.1,virginica(0 0 1)
...

输出列编码为我们之前见过的 1-N 编码规则。
该方法将从文件中读取所有数据,解析数据并创建两个浮点数组

  • float[] 特征,以及
  • float[] 标签

如您所见,这两个数组都是 1D,这意味着所有数据都将插入到 1D 中,因为 CNTK 要求如此。由于数据位于 1D 数组中,我们还应提供数据的维度,以便 CNTK 可以解析每个特征的值。 以下列表显示了将 Iris 数据加载到两个 1D 数组中,并作为元组返回。

static (float[], float[]) loadIrisDataset(string filePath, int featureDim, int numClasses)
{
    var rows = File.ReadAllLines(filePath);
    var features = new List<float>();
    var label = new List<float>();
    for (int i = 1; i < rows.Length; i++)
    {
        var row = rows[i].Split(',');
        var input = new float[featureDim];
        for (int j = 0; j < featureDim; j++)
        {
            input[j] = float.Parse(row[j], CultureInfo.InvariantCulture);
        }
        var output = new float[numClasses];
        for (int k = 0; k < numClasses; k++)
        {
            int oIndex = featureDim + k;
            output[k] = float.Parse(row[oIndex], CultureInfo.InvariantCulture);
        }

        features.AddRange(input);
        label.AddRange(output);
    }

    return (features.ToArray(), label.ToArray());
}

加载数据后,我们应该更改之前代码中很小一部分,以实现批处理,而不是使用 minibatchSource。 在开始时,我们提供几个变量来定义神经网络模型结构。 然后我们调用 loadIrisDataset,并定义 xValuesyValues,我们用它们来创建特征和标签输入变量。 然后我们创建字典,将特征和标签与稍后将传递给训练器的数据值连接起来。

接下来的代码与之前的版本相同,用于创建神经网络模型、损失和评估函数以及学习率。

然后我们创建循环,进行 800 次迭代。 一旦迭代次数达到最大值,程序将输出模型属性并终止。

以上内容在以下代码中实现

public static void TrainIriswithBatch(DeviceDescriptor device)
{
    //data file path
    var iris_data_file = "Data/iris_with_hot_vector.csv";

    //Network definition
    int inputDim = 4;
    int numOutputClasses = 3;
    int numHiddenLayers = 1;
    int hidenLayerDim = 6;
    int sampleSize = 130;

    //load data in to memory
    var dataSet = loadIrisDataset(iris_data_file, inputDim, numOutputClasses);

    // build a NN model
    //define input and output variable
    var xValues = Value.CreateBatch<float>(new NDShape(1, inputDim), dataSet.Item1, device);
    var yValues    = Value.CreateBatch<float>(new NDShape(1, numOutputClasses), dataSet.Item2, device);

    // build a NN model
    //define input and output variable and connecting to the stream configuration
    var feature = Variable.InputVariable(new NDShape(1, inputDim), DataType.Float);
    var label = Variable.InputVariable(new NDShape(1, numOutputClasses), DataType.Float);

    //Combine variables and data in to Dictionary for the training
    var dic = new Dictionary<Variable, Value>();
    dic.Add(feature, xValues);
    dic.Add(label, yValues);

    //Build simple Feed Forward Neural Network model
    // var ffnn_model = CreateMLPClassifier
    (device, numOutputClasses, hidenLayerDim, feature, classifierName);
    var ffnn_model = createFFNN(feature, numHiddenLayers, hidenLayerDim, 
    numOutputClasses, Activation.Tanh, "IrisNNModel", device);

    //Loss and error functions definition
    var trainingLoss = CNTKLib.CrossEntropyWithSoftmax
    (new Variable(ffnn_model), label, "lossFunction");
    var classError = CNTKLib.ClassificationError
    (new Variable(ffnn_model), label, "classificationError");

    // set learning rate for the network
    var learningRatePerSample = new TrainingParameterScheduleDouble(0.001125, 1);

    //define learners for the NN model
    var ll = Learner.SGDLearner(ffnn_model.Parameters(), learningRatePerSample);

    //define trainer based on ffnn_model, loss and error functions , and SGD learner
    var trainer = Trainer.CreateTrainer(ffnn_model, trainingLoss, classError, new Learner[] { ll });

    //Preparation for the iterative learning process
    //used 800 epochs/iterations. Batch size will be the same as sample size since the data set is small
    int epochs = 800;
    int i = 0;
    while (epochs > -1)
    {
        trainer.TrainMinibatch(dic, device);

        //print progress
        printTrainingProgress(trainer, i++, 50);

        //
        epochs--;
    }
    //Summary of training
    double acc = Math.Round((1.0 - trainer.PreviousMinibatchEvaluationAverage()) * 100, 2);
    Console.WriteLine($"------TRAINING SUMMARY--------");
    Console.WriteLine($"The model trained with the accuracy {acc}%");
}

如果我们运行代码,输出将与我们从之前的博文示例中获得的结果相同

包含训练数据的完整源代码可以从这里下载。

分类于:.NET, C#, CNTK, CodeProject
标签:.NET, C#, CNTK, Code Project, CodeProject, 机器学习

© . All rights reserved.