Несоответствие схемы ML.NET: ожидалось, что VarVector ‹Byte› получил Vector ‹Byte›

Я пытался изменить учебник 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 (). Я не хочу, чтобы эта дополнительная файловая система работала.


person user2894130    schedule 17.09.2020    source источник


Ответы (1)