Я пытался изменить учебник ML.NET по классификации изображений и столкнулся с проблемой несоответствия схемы, когда модель ожидает VarVector, а ей передается вектор.
В исходном примере создается IDataView со столбцом с именем ImagePath, заполненным путями к изображениям, а затем создается столбец Image с байтовыми данными с помощью MLContext.Transforms.LoadRawImageBytes (). Полученный IDataView затем передается в объект Multiclassification.Trainers.ImageClassification (). Это очень просто.
Я хочу обобщить это, чтобы включить немного больше предварительной обработки изображений. Я хотел бы, чтобы конвейер предварительной обработки уменьшил разрешение изображения, а затем также обрезал изображение до правильного размера перед его передачей в тренер ImageClassification (). Он следует той же последовательности, что и пример, но изменяет конвейер обработки для использования оценщиков LoadImages (), ResizeImage () и ExtractPixels () в конвейере обработки изображений. Ниже приведен фрагмент кода, с которым я работаю.
// Fill an IDataView with the Label and ImagePath information:
// The ImageData class is defined for this purpose and it is just:
//
// public class ImageData {
// public string ImagePath { get; set; }
// public string Label { get; set; }
// }
//
// Create a bunch of image names and their labels into a list of ImageData objects.
IEnumerable<ImageData> images = LoadImagesFromDirectory(folder: assetsRelativePath,
useFolderNameAsLabel: true);
IDataView imageData = mlContext.Data.LoadFromEnumerable(images);
// Define the preprocessing pipeline to:
// 1. Map the Label to a unique key
// 2. Load the image data using the ImagePath column
// 3. Reduce the resolution of the image data
// 4. Crop the reduced resolution image data
// 5. Transform the image data from type "Image" to a byte array.
var preprocessingPipeline = mlContext.Transforms.Conversion.MapValueToKey(
inputColumnName: "Label",
outputColumnName: "LabelAsKey")
.Append(mlContext.Transforms.LoadImages(
inputColumnName: "ImagePath",
outputColumnName: "RawImage",
imageFolder: assetsRelativePath))
.Append(mlContext.Transforms.ResizeImages(
inputColumnName: "RawImage",
outputColumnName: "ResReduxImage",
imageWidth: 512,
imageHeight: 459,
resizing: Microsoft.ML.Transforms.Image.ImageResizingEstimator.ResizingKind.Fill))
.Append(mlContext.Transforms.ResizeImages(
inputColumnName: "ResReduxImage",
outputColumnName: "CroppedImage",
imageWidth: 512,
imageHeight: 459,
resizing: Microsoft.ML.Transforms.Image.ImageResizingEstimator.ResizingKind.IsoCrop,
cropAnchor: Microsoft.ML.Transforms.Image.ImageResizingEstimator.Anchor.Center))
.Append(mlContext.Transforms.ExtractPixels(
inputColumnName: "CroppedImage",
outputColumnName: "Image",
outputAsFloatArray: false,
colorsToExtract: ImagePixelExtractingEstimator.ColorBits.Red));
// Transform the raw ImageData into the TransformedData that the Model will train on
IDataView preProcessedData = preprocessingPipeline.Fit(imageData).Transform(imageData);
// Partition the data set for training and validation
TrainTestData trainSplit = mlContext.Data.TrainTestSplit(data: preProcessedData, testFraction: 0.4);
TrainTestData validationTestSplit = mlContext.Data.TrainTestSplit(trainSplit.TestSet);
IDataView trainSet = trainSplit.TrainSet;
IDataView validationSet = validationTestSplit.TrainSet;
IDataView testSet = validationTestSplit.TestSet;
var classifierOptions = new ImageClassificationTrainer.Options()
{
FeatureColumnName = "Image",
LabelColumnName = "LabelAsKey",
ValidationSet = validationSet,
Arch = ImageClassificationTrainer.Architecture.ResnetV2101,
MetricsCallback = (metrics) => Console.WriteLine(metrics),
TestOnTrainSet = false,
ReuseTrainSetBottleneckCachedValues = true,
ReuseValidationSetBottleneckCachedValues = true,
WorkspacePath=workspaceRelativePath
};
var trainingPipeline =
mlContext.MulticlassClassification.Trainers.ImageClassification(classifierOptions)
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
// When I call Fit() in the next line of code, the following runtime error occurs:
// System.ArgumentOutOfRangeException: 'Schema mismatch for feature column 'Image':
// expected VarVector<Byte>, got Vector<Byte> Parameter name: inputSchema'
ITransformer trainedModel = trainingPipeline.Fit(trainSet);
Я озадачен несоответствием VarVector и Vector. За последние два дня я безуспешно пробовал следующее:
- для определения настраиваемой схемы DataViewSchema для передачи преобразованию
- для определения пользовательского DataView, производного от IDataView
- для определения настраиваемого сопоставления с помощью CustomMapping ‹› для изменения типа
Может ли кто-нибудь дать совет, как выбраться из этого затора? Мне бы очень хотелось избежать чтения изображения, его предварительной обработки, записи в файл и последующего вызова исходной функции LoadRawImageBytes (). Я не хочу, чтобы эта дополнительная файловая система работала.