Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Узнайте, как обучить пользовательскую модель глубокого обучения с помощью трансферного обучения, предварительно обученной модели TensorFlow и API для классификации изображений ML.NET, чтобы классифицировать изображения бетонных поверхностей как имеющие трещины или не имеющие трещин.
В этом руководстве описано, как:
- Определение проблемы
- Сведения об API классификации изображений ML.NET
- Общие сведения о предварительно обученной модели
- Использование обучения для обучения пользовательской модели классификации изображений TensorFlow
- Классификация изображений с помощью пользовательской модели
Предпосылки
Определение проблемы
Классификация изображений — это проблема компьютерного зрения. Классификация изображений принимает изображение как входные данные и классифицирует его в назначенный класс. Модели классификации изображений обычно обучены с помощью глубокого обучения и нейронных сетей. Дополнительные сведения см. в разделе Глубокое обучение против машинного обучения.
Некоторые сценарии, в которых классификация изображений полезна, включают:
- Распознавание лиц
- Определение эмоций
- Медицинский диагноз
- Обнаружение ориентиров
В этом руководстве показано, как обучить пользовательскую модель для классификации изображений, чтобы осуществлять автоматический визуальный осмотр мостовых настилов и выявлять структуры, поврежденные трещинами.
API классификации изображений ML.NET
ML.NET предоставляет различные способы классификации изображений. В этом руководстве применяется обучение по передаче с помощью API классификации изображений. API классификации изображений использует TensorFlow.NET, низкоуровневую библиотеку, которая предоставляет привязки C# для API TensorFlow C++.
Что такое передача обучения?
Передача обучения применяет знания, полученные от решения одной проблемы к другой связанной проблеме.
Для обучения модели глубокого обучения с нуля требуется задание нескольких параметров, большое количество помеченных обучающих данных и огромное количество вычислительных ресурсов (сотни часов GPU). Использование предварительно обученной модели вместе с обучением передачи позволяет смешать процесс обучения.
Учебный процесс
API классификации изображений запускает процесс обучения путем загрузки предварительно обученной модели TensorFlow. Учебный процесс состоит из двух этапов:
- Этап узких мест.
- Этап обучения.
Этап узких мест
На этапе узких мест набор обучающих изображений загружается, а значения пикселей используются в качестве входных данных или функций для замороженных слоев предварительно обученной модели. Замороженные слои включают все слои нейронной сети до предпоследнего слоя, неофициально известного как узкий слой. Эти слои называются замороженными, так как обучение не будет выполняться на этих слоях, и операции будут пропускаться через них без изменений. На этих замороженных уровнях вычисляются шаблоны нижнего уровня, которые помогают модели различать различные классы. Чем больше количество слоев, тем больше вычислительных ресурсов этот шаг. К счастью, так как это однократное вычисление, результаты можно кэшировать и использовать в последующих запусках при эксперименте с разными параметрами.
Этап обучения
После вычисления выходных значений на этапе узких мест они используются в качестве входных данных для повторного обучения окончательного слоя модели. Этот процесс является итеративным и выполняется для количества раз, указанного параметрами модели. Во время каждого выполнения оцениваются ошибка и точность. Затем соответствующие корректировки вносятся для улучшения модели с целью минимизации потери и максимизации точности. После завершения обучения выводятся два формата модели. Одна из них — .pb это версия модели, а другая — .zip это ML.NET сериализованная версия модели. При работе в средах, поддерживаемых ML.NET, рекомендуется использовать .zip версию модели. Однако в средах, где ML.NET не поддерживается, у вас есть возможность использовать версию .pb .
Общие сведения о предварительно обученной модели
Предварительно обученная модель, используемая в этом руководстве, — это 101-слойный вариант модели ResNet версии 2. Исходная модель обучена классифицировать изображения в тысячу категорий. Модель принимает на вход изображение размером 224 x 224 и выводит вероятности класса для каждого из классов, на которых она обучена. Часть этой модели используется для обучения новой модели с помощью пользовательских изображений для прогнозирования между двумя классами.
Создание консольного приложения
Теперь, когда у вас есть общее представление о передаче обучения и API классификации изображений, пришло время создать приложение.
Создайте консольное приложение C# с именем "DeepLearning_ImageClassification_Binary". Нажмите кнопку Далее.
Выберите .NET 8 в качестве используемой платформы и нажмите кнопку "Создать".
Установите пакет NuGet Microsoft.ML :
Примечание.
В этом примере используется последняя стабильная версия упомянутых пакетов NuGet, если не указано иное.
- В обозревателе решений щелкните проект правой кнопкой мыши и выберите Управление пакетами NuGet.
- Выберите nuget.org в качестве источника пакета.
- Перейдите на вкладку Browse.
- Установите флажок "Включить предварительную версию ".
- Найдите Microsoft.ML.
- Нажмите кнопку Установить.
- Нажмите кнопку "Принять" в диалоговом окне "Принятие лицензий ", если вы согласны с условиями лицензии для перечисленных пакетов.
- Повторите эти действия для пакетов NuGet Microsoft.ML.Vision, SciSharp.TensorFlow.Redist (версия 2.3.1) и Microsoft.ML.ImageAnalytics.
Подготовка и понимание данных
Примечание.
Наборы данных для этого руководства предоставлены Магуайром, Марком; Дорафшаном, Саттаром; и Томасом, Робертом Дж., "SDNET2018: набор данных изображений трещин в бетоне для приложений машинного обучения" (2018). Просмотрите все наборы данных. Документ 48. https://digitalcommons.usu.edu/all_datasets/48
SDNET2018 — это набор данных изображений, содержащий аннотации для трещиноватых и нетрещиноватых бетонных конструкций (мостовые настилы, стены и тротуары).
Данные организованы в трех подкаталогах:
- D содержит изображения палубы моста
- P содержит изображения тротуаров
- W содержит изображения стен
Каждая из этих подкаталогов содержит два дополнительных подкаталога с префиксом:
- C — это префикс, используемый для трещинных поверхностей
- U — это префикс, используемый для неповрежденных поверхностей.
В этом руководстве используются только образы палубы моста.
- Скачайте набор данных и распакуйте его.
- Создайте каталог с именем Assets в проекте, чтобы сохранить файлы набора данных.
- Скопируйте подкаталоги CD и UD из недавно распакованного каталога в каталог Assets.
Создание входных и выходных классов
Откройте файл Program.cs и замените существующее содержимое следующими
usingдирективами:using Microsoft.ML; using Microsoft.ML.Vision; using static Microsoft.ML.DataOperationsCatalog;Создайте класс с именем
ImageData. Этот класс используется для представления первоначально загруженных данных.class ImageData { public string? ImagePath { get; set; } public string? Label { get; set; } }ImageDataсодержит следующие свойства:-
ImagePath— это полный путь, в котором хранится изображение. -
Label— это категория, к которой принадлежит изображение. Это значение для прогнозирования.
-
Создайте классы для входных и выходных данных.
Под классом
ImageDataопределите схему входных данных в новом классеModelInput.class ModelInput { public byte[]? Image { get; set; } public uint LabelAsKey { get; set; } public string? ImagePath { get; set; } public string? Label { get; set; } }ModelInputсодержит следующие свойства:-
Imagebyte[]— это представление изображения. Модель ожидает, что данные изображения будут иметь этот тип для обучения. -
LabelAsKey— числовое представлениеLabel. -
ImagePath— это полный путь, в котором хранится изображение. -
Label— это категория, к которой принадлежит изображение. Это значение для прогнозирования.
Только
ImageиLabelAsKeyиспользуются для обучения модели и прогнозирования.ImagePathСвойстваLabelхранятся для удобства доступа к имени и категории исходного файла образа.-
Затем под классом
ModelInputопределите схему выходных данных в новом классеModelOutput.class ModelOutput { public string? ImagePath { get; set; } public string? Label { get; set; } public string? PredictedLabel { get; set; } }ModelOutputсодержит следующие свойства:-
ImagePath— это полный путь, в котором хранится изображение. -
Label— исходная категория, к которой принадлежит изображение. Это значение для прогнозирования. -
PredictedLabel— это значение, прогнозируемое моделью.
ModelInputАналогично , требуется толькоPredictedLabelдля прогнозирования, так как он содержит прогноз, сделанный моделью.ImagePathСвойстваLabelсохраняются для удобства доступа к имени и категории исходного файла образа.-
Определение путей и инициализация переменных
usingВ директивах добавьте следующий код:Определите расположение ресурсов.
Инициализировать
mlContextпеременную с новым экземпляром MLContext.Класс MLContext — это отправная точка для всех операций ML.NET, а инициализация mlContext создает новую среду ML.NET, которую можно совместно использовать для объектов рабочего процесса создания модели. Концептуально, это похоже на
DbContextв Entity Framework.
var projectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../")); var assetsRelativePath = Path.Combine(projectDirectory, "Assets"); MLContext mlContext = new();
Загрузка данных
Создание метода загрузки данных
Изображения хранятся в двух подкаталогах. Перед загрузкой данных его необходимо отформатировать в список ImageData объектов. Для этого создайте LoadImagesFromDirectory метод:
static IEnumerable<ImageData> LoadImagesFromDirectory(string folder, bool useFolderNameAsLabel = true)
{
var files = Directory.GetFiles(folder, "*",
searchOption: SearchOption.AllDirectories);
foreach (var file in files)
{
if ((Path.GetExtension(file) != ".jpg") && (Path.GetExtension(file) != ".png"))
continue;
var label = Path.GetFileName(file);
if (useFolderNameAsLabel)
label = Directory.GetParent(file)?.Name;
else
{
for (int index = 0; index < label.Length; index++)
{
if (!char.IsLetter(label[index]))
{
label = label[..index];
break;
}
}
}
yield return new ImageData()
{
ImagePath = file,
Label = label
};
}
}
Метод LoadImagesFromDirectory:
- Возвращает все пути к файлам из подкаталогов.
- Выполняет итерацию по каждому из файлов с помощью
foreachинструкции и проверяет, поддерживаются ли расширения файлов. API классификации изображений поддерживает форматы JPEG и PNG. - Возвращает метку для файла.
useFolderNameAsLabelЕсли для параметра задано значениеtrue, родительский каталог, в котором сохраняется файл, используется в качестве метки. В противном случае она ожидает, что метка будет префиксом имени файла или самого имени файла. - Создает новый экземпляр
ModelInput.
Подготовка данных
Добавьте следующий код после строки, в которой создается новый экземпляр MLContext.
IEnumerable<ImageData> images = LoadImagesFromDirectory(folder: assetsRelativePath, useFolderNameAsLabel: true);
IDataView imageData = mlContext.Data.LoadFromEnumerable(images);
IDataView shuffledData = mlContext.Data.ShuffleRows(imageData);
var preprocessingPipeline = mlContext.Transforms.Conversion.MapValueToKey(
inputColumnName: "Label",
outputColumnName: "LabelAsKey")
.Append(mlContext.Transforms.LoadRawImageBytes(
outputColumnName: "Image",
imageFolder: assetsRelativePath,
inputColumnName: "ImagePath"));
IDataView preProcessedData = preprocessingPipeline
.Fit(shuffledData)
.Transform(shuffledData);
TrainTestData trainSplit = mlContext.Data.TrainTestSplit(data: preProcessedData, testFraction: 0.3);
TrainTestData validationTestSplit = mlContext.Data.TrainTestSplit(trainSplit.TestSet);
IDataView trainSet = trainSplit.TrainSet;
IDataView validationSet = validationTestSplit.TrainSet;
IDataView testSet = validationTestSplit.TestSet;
Предыдущий код:
LoadImagesFromDirectoryВызывает метод служебной программы, чтобы получить список изображений, используемых для обучения после инициализации переменнойmlContext.Загружает изображения в
IDataViewметод с помощьюLoadFromEnumerableметода.Перемешив данные с помощью
ShuffleRowsметода. Данные загружаются в том порядке, в котором они считывались из каталогов. Перетасовка выполняется для его балансировки.Выполняет предварительную обработку данных перед обучением. Это делается, так как модели машинного обучения ожидают, что входные данные будут находиться в числовом формате. Код предварительной обработки создает объект
EstimatorChain, который состоит из преобразованийMapValueToKeyиLoadRawImageBytes. ПреобразованиеMapValueToKeyпринимает категориальное значение вLabelстолбце, преобразует его в числовоеKeyTypeзначение и сохраняет его в новом столбце с именемLabelAsKey. ПринимаетLoadImagesзначения из столбцаImagePathвместе с параметромimageFolder, чтобы загрузить изображения для обучения.FitИспользует метод для применения данных кpreprocessingPipelineEstimatorChainследуютTransformметоду, который возвращаетIDataViewсодержащий предварительно обработанные данные.Разделяет данные на наборы для обучения, проверки и тестирования.
Для обучения модели важно иметь обучающий набор данных, а также набор данных проверки. Модель обучена на обучаемом наборе. Насколько хорошо это делает прогнозы на невидимых данных, измеряется производительностью для набора проверки. Основываясь на результатах этой эффективности, модель корректирует свои знания, стремясь к улучшению. Проверочный набор может быть полученным из разделения исходного набора данных или из другого источника, который уже был отложен для этой цели.
В примере кода выполняется два разбиения. Во-первых, предварительно обработанные данные разделяются и 70% используются для обучения, а остальные 30% используются для проверки. Затем 30% набор проверки делится на наборы для проверки и тестирования, где для проверки используется 90%, а для тестирования 10%.
Один из способов подумать о назначении этих секций данных является прием экзамена. При изучении экзамена вы просматриваете заметки, книги или другие ресурсы, чтобы получить представление о понятиях, которые находятся на экзамене. Вот для чего нужен этот набор поездов. Затем вы можете пройти пробный экзамен, чтобы проверить свои знания. Здесь набор данных для проверки оказывается полезным. Вы хотите проверить, есть ли у вас хорошее понимание концепций перед принятием фактического экзамена. Основываясь на этих результатах, вы отмечаете, что сделали неправильно или недостаточно поняли, и вносите изменения, когда вы готовитесь к настоящему экзамену. Наконец, вы принимаете экзамен. Это то, для чего используется тестовый набор. Вы никогда не видели вопросы, которые есть в экзамене, и теперь используете знания, полученные в ходе обучения и проверки, чтобы применить их к задаче перед вами.
Назначает разбиения соответствующие значения для учебных, проверочных и тестовых данных.
Определение конвейера обучения
Обучение модели состоит из двух этапов. Во-первых, API классификации изображений используется для обучения модели. Затем закодированные метки в PredictedLabel столбце преобразуются обратно в исходное категориальное значение с помощью MapKeyToValue преобразования.
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
};
var trainingPipeline = mlContext.MulticlassClassification.Trainers.ImageClassification(classifierOptions)
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
ITransformer trainedModel = trainingPipeline.Fit(trainSet);
Предыдущий код:
Создает новую переменную для хранения набора обязательных и необязательных параметров для объекта ImageClassificationTrainer. Принимает ImageClassificationTrainer несколько необязательных параметров:
-
FeatureColumnName— это столбец, используемый в качестве входных данных для модели. -
LabelColumnName— это столбец для прогнозируемого значения. -
ValidationSetIDataView— это содержащий данные проверки. -
Archопределяет, какие из предварительно обученных архитектур модели следует использовать. В этом руководстве используется 101-слойный вариант модели ResNetv2. -
MetricsCallbackпривязывает функцию для отслеживания хода выполнения во время обучения. -
TestOnTrainSetуказывает модели измерять производительность для обучающего набора, если валидационный набор отсутствует. -
ReuseTrainSetBottleneckCachedValuesсообщает модели, следует ли использовать кэшированные значения из этапа узких мест в последующих запусках. Этап узких мест — это однократное сквозное вычисление, которое требует много вычислительных ресурсов при первом выполнении. Если данные обучения не изменяются и вы хотите экспериментировать с использованием другого количества эпох или размера пакета, использование кэшированных значений значительно сокращает время, необходимое для обучения модели. -
ReuseValidationSetBottleneckCachedValuesаналогиченReuseTrainSetBottleneckCachedValues, только в этом случае это для набора данных проверки.
-
Определяет конвейер обучения, состоящий как из
mapLabelEstimator, так и из ImageClassificationTrainer,EstimatorChain.FitИспользует метод для обучения модели.
Используйте модель
Теперь, когда вы обучили модель, пришло время использовать ее для классификации изображений.
Создайте новый метод служебной программы, который вызывается OutputPrediction для отображения сведений о прогнозировании в консоли.
static void OutputPrediction(ModelOutput prediction)
{
string? imageName = Path.GetFileName(prediction.ImagePath);
Console.WriteLine($"Image: {imageName} | Actual Value: {prediction.Label} | Predicted Value: {prediction.PredictedLabel}");
}
Классификация одного изображения
Создайте метод, вызывающийся
ClassifySingleImageдля создания и вывода одного прогноза изображения.static void ClassifySingleImage(MLContext mlContext, IDataView data, ITransformer trainedModel) { PredictionEngine<ModelInput, ModelOutput> predictionEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(trainedModel); ModelInput image = mlContext.Data.CreateEnumerable<ModelInput>(data, reuseRowObject: true).First(); ModelOutput prediction = predictionEngine.Predict(image); Console.WriteLine("Classifying single image"); OutputPrediction(prediction); }Метод
ClassifySingleImage:-
PredictionEngineСоздает внутриClassifySingleImageметода. ЭтоPredictionEngineудобный API, который позволяет передавать и выполнять прогноз на одном экземпляре данных. - Чтобы получить доступ к одному
ModelInputэкземпляру, преобразуетdataIDataViewего вIEnumerableCreateEnumerableметод, а затем получает первое наблюдение. -
PredictИспользует метод для классификации изображения. - Выводит прогноз в консоль с
OutputPredictionпомощью метода.
-
Сначала вызовите метод
Fit, затем вызовитеClassifySingleImage, используя тестовый набор изображений.ClassifySingleImage(mlContext, testSet, trainedModel);
Классификация нескольких изображений
Создайте метод, вызывающийся
ClassifyImagesдля создания и вывода нескольких прогнозов изображений.static void ClassifyImages(MLContext mlContext, IDataView data, ITransformer trainedModel) { IDataView predictionData = trainedModel.Transform(data); IEnumerable<ModelOutput> predictions = mlContext.Data.CreateEnumerable<ModelOutput>(predictionData, reuseRowObject: true).Take(10); Console.WriteLine("Classifying multiple images"); foreach (var prediction in predictions) { OutputPrediction(prediction); } }Метод
ClassifyImages:-
IDataViewСоздает содержащий прогнозы с помощьюTransformметода. - Чтобы итерировать прогнозы, преобразует
predictionDataIDataViewвIEnumerableс помощью методаCreateEnumerable, а затем получает первые 10 наблюдений. - Выполняет итерацию и выводит исходные и прогнозируемые метки для прогнозов.
-
Вызовите
ClassifyImagesпосле вызова методаClassifySingleImage()с использованием тестового набора изображений.ClassifyImages(mlContext, testSet, trainedModel);
Запуск приложения
Запустите консольное приложение. Выходные данные должны совпадать со следующими выходными данными.
Примечание.
Вы можете видеть предупреждения или сообщения об обработке. Эти сообщения были удалены из представленных ниже результатов для ясности. Для краткости выходные данные были сокращены.
Этап узких мест
Значение для имени изображения не выводится, потому что изображения загружаются как byte[], следовательно, имя изображения отсутствует для отображения.
Phase: Bottleneck Computation, Dataset used: Train, Image Index: 279
Phase: Bottleneck Computation, Dataset used: Train, Image Index: 280
Phase: Bottleneck Computation, Dataset used: Validation, Image Index: 1
Phase: Bottleneck Computation, Dataset used: Validation, Image Index: 2
Этап обучения
Phase: Training, Dataset used: Validation, Batch Processed Count: 6, Epoch: 21, Accuracy: 0.6797619
Phase: Training, Dataset used: Validation, Batch Processed Count: 6, Epoch: 22, Accuracy: 0.7642857
Phase: Training, Dataset used: Validation, Batch Processed Count: 6, Epoch: 23, Accuracy: 0.7916667
Классификация выходных данных изображений
Classifying single image
Image: 7001-220.jpg | Actual Value: UD | Predicted Value: UD
Classifying multiple images
Image: 7001-220.jpg | Actual Value: UD | Predicted Value: UD
Image: 7001-163.jpg | Actual Value: UD | Predicted Value: UD
Image: 7001-210.jpg | Actual Value: UD | Predicted Value: UD
При проверке изображения 7001-220.jpg можно убедиться, что он не взломан, как прогнозировала модель.
Поздравляю! Теперь вы успешно создали модель глубокого обучения для классификации изображений.
Улучшение модели
Если вы не удовлетворены результатами модели, попробуйте улучшить ее производительность, выполнив некоторые из следующих подходов:
- Дополнительные данные: чем больше примеров модель учится, тем лучше она выполняется. Скачайте полный набор данных SDNET2018 и используйте его для обучения.
- Расширение данных: распространенный способ добавления разнообразия к данным заключается в том, чтобы расширить данные путем создания изображения и применения различных преобразований (поворот, переворачивание, смена, обрезка). Это добавляет более разнообразные примеры для модели для изучения.
- Обучение в течение длительного времени: чем дольше вы обучаете, тем более настроенная модель будет. Увеличение числа эпох может повысить производительность модели.
- Эксперимент с гиперпараметров: помимо параметров, используемых в этом руководстве, можно настроить другие параметры, чтобы повысить производительность. Изменение скорости обучения, определяющее величину обновлений, внесенных в модель после каждой эпохи, может повысить производительность.
- Используйте другую архитектуру модели: в зависимости от того, как выглядят данные, модель, которая лучше всего узнает о своих функциях, может отличаться. Если вы не удовлетворены производительностью модели, попробуйте изменить архитектуру.
Дальнейшие действия
В этом руководстве вы узнали, как создать пользовательскую модель глубокого обучения с помощью обучения переносу, предварительно обученной модели классификации изображений TensorFlow и API классификации изображений ML.NET, чтобы классифицировать изображения бетонных поверхностей как с трещинами или без трещин.
Продолжите к следующему уроку, чтобы узнать больше.