private void MixMatch(string dataPath)
        {
            // Create a new context for ML.NET operations. It can be used for exception tracking and logging,
            // as a catalog of available operations and as the source of randomness.
            var mlContext = new MLContext();

            // Read the data as an IDataView.
            // First, we define the loader: specify the data columns and where to find them in the text file.
            var loader = mlContext.Data.CreateTextLoader(ctx => (
                                                             // The four features of the Iris dataset.
                                                             SepalLength: ctx.LoadFloat(0),
                                                             SepalWidth: ctx.LoadFloat(1),
                                                             PetalLength: ctx.LoadFloat(2),
                                                             PetalWidth: ctx.LoadFloat(3),
                                                             // Label: kind of iris.
                                                             Label: ctx.LoadText(4)
                                                             ),
                                                         // Default separator is tab, but the dataset has comma.
                                                         separator: ',');

            // Read the data.
            var data = loader.Load(dataPath);

            // Build the pre-processing pipeline.
            var pipeline = loader.MakeNewEstimator()
                           .Append(r => (
                                       // Convert string label to a key.
                                       Label: r.Label.ToKey(),
                                       // Concatenate all the features together into one column 'Features'.
                                       Features: r.SepalLength.ConcatWith(r.SepalWidth, r.PetalLength, r.PetalWidth)));

            // Now, at the time of writing, there is no static pipeline for OVA (one-versus-all). So, let's
            // append the OVA learner to the dynamic pipeline.
            IEstimator <ITransformer> dynamicPipe = pipeline.AsDynamic;

            // Create a binary classification trainer.
            var binaryTrainer = mlContext.BinaryClassification.Trainers.AveragedPerceptron("Label", "Features");

            // Append the OVA learner to the pipeline.
            dynamicPipe = dynamicPipe.Append(mlContext.MulticlassClassification.Trainers.OneVersusAll(binaryTrainer));

            // At this point, we have a choice. We could continue working with the dynamically-typed pipeline, and
            // ultimately call dynamicPipe.Fit(data.AsDynamic) to get the model, or we could go back into the static world.
            // Here's how we go back to the static pipeline:
            var staticFinalPipe = dynamicPipe.AssertStatic(mlContext,
                                                           // Declare the shape of the input. As you can see, it's identical to the shape of the loader:
                                                           // four float features and a string label.
                                                           c => (
                                                               SepalLength: c.R4.Scalar,
                                                               SepalWidth: c.R4.Scalar,
                                                               PetalLength: c.R4.Scalar,
                                                               PetalWidth: c.R4.Scalar,
                                                               Label: c.Text.Scalar),
                                                           // Declare the shape of the output (or a relevant subset of it).
                                                           // In our case, we care only about the predicted label column (a key type), and scores (vector of floats).
                                                           c => (
                                                               Score: c.R4.Vector,
                                                               // Predicted label is a key backed by uint, with text values (since original labels are text).
                                                               PredictedLabel: c.KeyU4.TextValues.Scalar))
                                  // Convert the predicted label from key back to the original string value.
                                  .Append(r => r.PredictedLabel.ToValue());

            // Train the model in a statically typed way.
            var model = staticFinalPipe.Fit(data);

            // And here is how we could've stayed in the dynamic pipeline and train that way.
            dynamicPipe = dynamicPipe.Append(new KeyToValueMappingEstimator(mlContext, "PredictedLabel"));
            var dynamicModel = dynamicPipe.Fit(data.AsDynamic);

            // Now 'dynamicModel', and 'model.AsDynamic' are equivalent.
        }