public void BuildAndTrain() { var featurizerModelLocation = inputModelLocation; ConsoleHelpers.ConsoleWriteHeader("Read model"); Console.WriteLine($"Model location: {featurizerModelLocation}"); Console.WriteLine($"Images folder: {imagesFolder}"); Console.WriteLine($"Training file: {dataLocation}"); Console.WriteLine($"Default parameters: image size=({ImageNetSettings.imageWidth},{ImageNetSettings.imageHeight}), image mean: {ImageNetSettings.mean}"); var data = mlContext.Data.LoadFromTextFile <ImageNetData>(path: dataLocation, hasHeader: false); var pipeline = mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: LabelTokey, inputColumnName: "Label") .Append(mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: imagesFolder, inputColumnName: nameof(ImageNetData.ImagePath))) .Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "input")) .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: ImageNetSettings.channelsLast, offsetImage: ImageNetSettings.mean)) .Append(mlContext.Model.LoadTensorFlowModel(featurizerModelLocation). ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true)) .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: LabelTokey, featureColumnName: "softmax2_pre_activation")) .Append(mlContext.Transforms.Conversion.MapKeyToValue(PredictedLabelValue, "PredictedLabel")) .AppendCacheCheckpoint(mlContext); // Train the model ConsoleHelpers.ConsoleWriteHeader("Training classification model"); ITransformer model = pipeline.Fit(data); // Process the training data through the model // This is an optional step, but it's useful for debugging issues var trainData = model.Transform(data); var loadedModelOutputColumnNames = trainData.Schema .Where(col => !col.IsHidden).Select(col => col.Name); var trainData2 = mlContext.Data.CreateEnumerable <ImageNetPipeline>(trainData, false, true).ToList(); trainData2.ForEach(pr => ConsoleHelpers.ConsoleWriteImagePrediction(pr.ImagePath, pr.PredictedLabelValue, pr.Score.Max())); // Get some performance metric on the model using training data var classificationContext = mlContext.MulticlassClassification; ConsoleHelpers.ConsoleWriteHeader("Classification metrics"); var metrics = classificationContext.Evaluate(trainData, labelColumnName: LabelTokey, predictedLabelColumnName: "PredictedLabel"); Console.WriteLine($"LogLoss is: {metrics.LogLoss}"); Console.WriteLine($"PerClassLogLoss is: {String.Join(" , ", metrics.PerClassLogLoss.Select(c => c.ToString()))}"); // Save the model to assets/outputs ConsoleHelpers.ConsoleWriteHeader("Save model to local file"); ModelHelpers.DeleteAssets(outputModelLocation); mlContext.Model.Save(model, trainData.Schema, outputModelLocation); Console.WriteLine($"Model saved: {outputModelLocation}"); }
public void ClassifyImages() { ConsoleHelpers.ConsoleWriteHeader("Loading model"); Console.WriteLine($"Model loaded: {modelLocation}"); // Load the model ITransformer loadedModel = mlContext.Model.Load(modelLocation, out var modelInputSchema); // Make prediction function (input = ImageNetData, output = ImageNetPrediction) var predictor = mlContext.Model.CreatePredictionEngine <ImageNetData, ImageNetPrediction>(loadedModel); // Read csv file into List<ImageNetData> var imageListToPredict = ImageNetData.ReadFromCsv(dataLocation, imagesFolder).ToList(); ConsoleHelpers.ConsoleWriteHeader("Making classifications"); // There is a bug (https://github.com/dotnet/machinelearning/issues/1138), // that always buffers the response from the predictor // so we have to make a copy-by-value op everytime we get a response // from the predictor imageListToPredict .Select(td => new { td, pred = predictor.Predict(td) }) .Select(pr => (pr.td.ImagePath, pr.pred.PredictedLabelValue, pr.pred.Score)) .ToList() .ForEach(pr => ConsoleHelpers.ConsoleWriteImagePrediction(pr.ImagePath, pr.PredictedLabelValue, pr.Score.Max())); }