[.NET, Машинное обучение] Посмотрим на девочек? Или ml.net в работе
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
К сожалению, мир машинного обучения принадлежит python. Он давно закрепился, как рабочий язык для Data Silence, но Microsoft решила поспорить и представила свой инструмент, который легко можно интегрировать с экосистемой, которой сейчас пользуется весь мир. Так появился ML.NET, кросс-платформенная и открытая система машинного обучения для разработчиков .NET. В данной статье, я хочу показать, что использовать ml.net - не сложнее, чем остальные варианты, которые есть, на реально работающем примере, ссылку на который оставлю внизу. Это канал в телеграмме, который в автоматическом режиме забирает данные, классифицирует их(это и будем рассматривать) и постит. Кому интересно, добро пожаловать.Постановка задачиЯ в подростковом возрасте очень хотел, чтобы у меня был прикольный бот, где я могу смотреть на девочек, который не будет забит рекламой под завязку, а просто фото и все. Так что, когда выдалось свободное время, сошлись звезды и желание, я сразу же приступил к решению этой задачиСбор данныхДля начала, я купил выгрузку данных твиттера по интересующему меня тегу, которую сервис отдает в формате csv(несколько разных файлов, которые различаются: сам твит, медиа, ссылки). Выбрав нужный мне файл, быстро пишем класс, чтобы распарсить данные, отсеять дубликаты. В итоге, в памяти, оставляются только ссылки на изображения, которые будут участвовать в обучении. Это хорошо, но все равно изображения нужно промаркировать, то есть разделить на категории. В моем случае, я выбрал: boys, girls, trash и other(вначале выбрал default, но, когда перешёл от строк к Enum, пришлось менять название категории). Все эти фото, я выгрузил, скурпулезно разделил на папочки, которые отражали метку фотографии, так что настало время для самого интересного - код. Обучение моделиДля определения того, что изображено на фото, используются алгоритмы классификации изображений.Классификация изображений Классификация изображений — это задача из области компьютерного зрения. Классификация изображений принимает изображение в качестве входных данных и классифицирует его, относя к предписанному классу. Конкретнее, я буду использовать глубокое обучение.Глубокое обучениеГлубокое обучение (глубинное обучение; англ. Deep learning) — совокупность методов машинного обучения (с учителем, с частичным привлечением учителя, без учителя, с подкреплением), основанных на обучении представлениям (англ. feature/representation learning), а не специализированным алгоритмам под конкретные задачи.Чтобы не тратить множество часов на обучение, проще всего взять готовую модель, которая уже содержит признаки изображений, и дообучить её для своих классов, чем обучать её с ноля. Я буду использовать TensorFlow Inception , которая уже обучена на популярном сете ImageNet. Теперь можно добавить тип проекта "Библиотека классов", для более удобного переиспользования данной модели и наконец начать писать код(распределение 2000 картинок, у меня заняло около 2х часов, при условии, что мне требовалось +- равное количество изображений в каждой из категорий).ОффтопЯ немного экспериментировал с количество изображений в наборах для обучения, но лучше всего себя показывал вариант, когда количество изображений, в каждой категории, примерно, равно. В данном примере используется 4 категории по 500 фото. Сначала создадим класс. Например, model и после этого добавим нужные библиотеки через nuget и добавим их к файлу класса:
using Microsoft.ML;
using Microsoft.ML.Data;
Теперь добавим элементы, которые потребуются для работы основного функционала:
private readonly string _inceptionTensorFlowModel; // путь к модели Inception
private MLContext mlContext;
private ITransformer model;
private DataViewSchema schema;
private string modelName = "model.zip"; // название модели для её сохранения
private string _setsPath = @"C:\datasets"; // путь к сетам и место, куда будет сложена модель после сохранения
public Model(string inceptionTensorFlowModel)
{
mlContext = new MLContext();
_inceptionTensorFlowModel = inceptionTensorFlowModel;
}
MLContext - это отправная точка в мир машинного обучения в .NET. Этот класс "связывает" всю работу и все элементы, примерно, как DbContext в EntityFramework.ITransformer - описывает то, как изменять данные, и то, как они будут выглядеть после трансформации. DataViewSchema - схема данных колонок сета. Теперь добавил классы, которые будут описывать "вход", то есть данные, которые мы будем подавать приложению.
public class ImageData
{
[LoadColumn(0)]
public string ImagePath;
[LoadColumn(1)]
public string Label;
//метод, который я использую, чтобы забрать данные из папок и отмаркировать их
public static (IEnumerable<ImageData> train, IEnumerable<ImageData> test) ReadData(string pathToFolder)
{
List<ImageData> list = new List<ImageData>();
var directories = Directory.EnumerateDirectories(pathToFolder);
foreach (var dir in directories)
{
if (!dir.Contains("girls") && !dir.Contains("boys") && !dir.Contains("trash") && !dir.Contains("other"))
continue;
var label = dir.Split(@"").Last();
foreach (var file in Directory.GetFiles(dir))
{
list.Add(new ImageData()
{
ImagePath = file,
Label = label
});
}
}
list = list.Shuffle().ToList();
return GetSets(list);
}
//Делим изображения на тестовую и основную выборки
public static (IEnumerable<ImageData> train, IEnumerable<ImageData> test) GetSets(IEnumerable<ImageData> data)
{
var trainCount = data.Count() / 100 * 99;
var train = data.Take(trainCount);
var test = data.Skip(trainCount);
return (train, test);
}
}
public class ImagePrediction : ImageData
{
[ColumnName("Score")]
public float[] Score;
public string PredictedLabelValue;
}
И расширение для IEnumerable для перемешивания данных: Оффтоп по новому редакторуПопытался в спойлер вставить код, после чего у меня полностью зависла вкладка браузера
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
return source.Shuffle(new Random());
}
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
if (source == null) throw new ArgumentNullException("source");
if (rng == null) throw new ArgumentNullException("rng");
return source.ShuffleIterator(rng);
}
private static IEnumerable<T> ShuffleIterator<T>(
this IEnumerable<T> source, Random rng)
{
var buffer = source.ToList();
for (int i = 0; i < buffer.Count; i++)
{
int j = rng.Next(i, buffer.Count);
yield return buffer[j];
buffer[j] = buffer[i];
}
}
А так же скруктуру, которая будет описывать настройки для модели:
private struct InceptionSettings
{
public const int ImageHeight = 224;
public const int ImageWidth = 224;
public const float Mean = 117;
public const float Scale = 1;
public const bool ChannelsLast = true;
}
Она нужна, чтобы просто дать более понятные имена параметрам.Наконец приготовления закончены и можна начинать писать метод обучения модели:
private double TrainModel()
{
IEstimator<ITransformer> pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: "", inputColumnName: nameof(ImageData.ImagePath))
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input"))
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean))
.Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel).
ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel"))
.AppendCacheCheckpoint(mlContext);
var loadImages = ImageData.ReadData(_setsPath);
IDataView trainingData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.train);
ITransformer model = pipeline.Fit(trainingData);
IDataView testData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.test);
IDataView predictions = model.Transform(testData);
List<ImagePrediction> imagePredictionData = mlContext.Data.CreateEnumerable<ImagePrediction>(predictions, true).ToList();
MulticlassClassificationMetrics metrics =
mlContext.MulticlassClassification.Evaluate(predictions,
labelColumnName: "LabelKey",
predictedLabelColumnName: "PredictedLabel");
schema = trainingData.Schema;
return metrics.LogLoss;
}
Разберем по порядку:
IEstimator<ITransformer> pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: "", inputColumnName: nameof(ImageData.ImagePath))
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input"))
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean))
Создаем пайплайн. Добавляем загрузку, изменение размера и извлечение пикселей из изображений:
.Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel).
ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true))
Применение входных данных к модели глубокого обучения и формирование выходных данных с помощью модели называется оценкой. Добавляем в пайплайн модель по пути, заданному раннее и оцениваем модель:
.Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
Для работы моделей ml.net, метки должны быть в формате ключей, которые являются целочисленными значениями. Добавляем алгоритм классификации:
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
И средство преобразования ключей обратно в строку:
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel"))
.AppendCacheCheckpoint(mlContext);
Теперь остальная часть метода:
var loadImages = ImageData.ReadData(_setsPath);
IDataView trainingData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.train);
model = pipeline.Fit(trainingData);
Данный отрезок отвечает за получение данных, их загрузку и обучение модели.
IDataView testData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.test);
IDataView predictions = model.Transform(testData);
List<ImagePrediction> imagePredictionData = mlContext.Data.CreateEnumerable<ImagePrediction>(predictions, true).ToList();
MulticlassClassificationMetrics metrics =
mlContext.MulticlassClassification.Evaluate(predictions,
labelColumnName: "LabelKey",
predictedLabelColumnName: "PredictedLabel");
Сначала мы загружаем наш тестовый сет. Далее трансформируем его и пытаемся классифицировать. После чего, этот "классифицированный" список используем для оценки точности модели.
schema = trainingData.Schema;
return metrics.LogLoss;
Записываем схему данных в переменную класса и возвращаем LogLoss(метрика точности модели). Наконец метод обучения модели готов, осталось только собрать все в одну кучу. Сразу же создадим метод, которым будем сохранять модель на диске, чтобы её можно было в дальнейшем использовать:
public void SaveModel() => mlContext.Model.Save(model, schema, Path.Combine(_setsPath, modelName));
И после добавим публичный метод, которым мы сразу и учим, и сохраняем модель:
public void FitModel()
{
var LogLoss = TrainModel();
Console.WriteLine($"LogLoss is {LogLoss}");
SaveModel();
}
Можно было после обучения сразу же сохранять модель, но данный метод удобнее будет расширить, если будет желание переучивать модель, записывать лог лосс и сохранять в том случае, если точность выше, а не ниже. Теперь мы готовы к тому, чтобы обучить модель, но я рекомендую дописать возможность произвольной классификации одного изображения, чтобы модель было удобно использовать после обучения. Под переменными класса добавим сам классификатор:
private PredictionEngine<ImageData, ImagePrediction> predictor;
А теперь и метод, который его будет использовать(+ сразу же и загрузка модели):
public ImagePrediction ClassifySingleImage(string filePath)
{
if (model == null)
LoadModel();
if (predictor == null)
predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model);
var imageData = new ImageData()
{
ImagePath = filePath
};
return predictor.Predict(imageData);
}
public void LoadModel() =>
model = mlContext.Model.Load(Path.Combine(_setsPath, modelName), out schema);
Теперь мы можем свободно использовать данный класс как для обучения, так и для классификации изображений.Для демострации работы, я добавил в проект приложение консольного типа и написал такой код:
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.White;
Stopwatch s = new Stopwatch();
s.Start();
Model model = new Model(@"C:\tensorflow_inception_graph.pb");
model.FitModel();
Console.WriteLine($"##### Model train ended for {s.Elapsed.Minutes}:{s.Elapsed.Seconds} #####");
s.Restart();
var res1 = model.ClassifySingleImage(@"C:\EugRqKFXUAYMTWz.jpg");
Console.WriteLine($" > It's trash. Classification result is {res1.PredictedLabelValue} with score: {res1.Score.Max()}");
Console.WriteLine($"##### Ended for {s.Elapsed.Minutes}:{s.Elapsed.Seconds} #####");
s.Restart();
var res2 = model.ClassifySingleImage(@"C:\EvpmOjIXcAMgj5r.jpg");
Console.WriteLine($" > It's girl. Classification result is {res2.PredictedLabelValue} with score: {res1.Score.Max()}");
Console.WriteLine($"##### Ended for {s.Elapsed.Minutes}:{s.Elapsed.Seconds} #####");
}
Выбранные изображения
И получил такие результаты:
Несмотря на достаточно слабые метрики(я все таки использовал для тестов 20 изображений): 0.55, но модель отлично справилась со своими задачами. Именно такую модель, я использую для своего nsfw-бота, который получает данные из твиттера, а потом классифицирует и постит их.Так что достаточно не сложно обучить модель и добавить в свой проект, главное желание разобраться. И никогда не стоит останавливаться в том, чтобы учиться чему-то новому.
===========
Источник:
habr.com
===========
Похожие новости:
- [Машинное обучение, Развитие стартапа, Искусственный интеллект, Здоровье, Телемедицина] Новосибирский стартап запустил камеры по мониторингу первичного состояния здоровья
- [Python, Программирование, Машинное обучение] Поиск нарушений на видео с помощью компьютерного зрения
- [.NET] Нюансы при работе с EF миграциями
- [Ненормальное программирование, Поисковые технологии, Python, Игры и игровые приставки] Однажды Microsoft забанила всю мою страну за читерство (перевод)
- Выпуск среды разработки PascalABC.NET 3.8
- [Машинное обучение, DevOps, Kubernetes, Data Engineering] MLOps без боли в облаке: как развернуть Kubeflow в продакшен-кластере Kubernetes
- [Разработка веб-сайтов, .NET, C#, Функциональное программирование] От внедрения зависимостей к отказу от зависимостей
- [Машинное обучение, Искусственный интеллект, Будущее здесь] Как bias может повлиять на мир вообще и людей-пользователей в частности?
- [Python, Программирование, Машинное обучение] NLP: ВЫДЕЛЯЕМ ФАКТЫ ИЗ ТЕКСТОВ С ПОМОЩЬЮ ТОМИТА-ПАРСЕРА
- [C#, Serverless] Создание превью картинок в объектном хранилище с помощью Yandex Cloud Functions
Теги для поиска: #_.net, #_mashinnoe_obuchenie (Машинное обучение), #_nsfw, #_ml.net, #_c#, #_.net, #_.net, #_mashinnoe_obuchenie (
Машинное обучение
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:39
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
К сожалению, мир машинного обучения принадлежит python. Он давно закрепился, как рабочий язык для Data Silence, но Microsoft решила поспорить и представила свой инструмент, который легко можно интегрировать с экосистемой, которой сейчас пользуется весь мир. Так появился ML.NET, кросс-платформенная и открытая система машинного обучения для разработчиков .NET. В данной статье, я хочу показать, что использовать ml.net - не сложнее, чем остальные варианты, которые есть, на реально работающем примере, ссылку на который оставлю внизу. Это канал в телеграмме, который в автоматическом режиме забирает данные, классифицирует их(это и будем рассматривать) и постит. Кому интересно, добро пожаловать.Постановка задачиЯ в подростковом возрасте очень хотел, чтобы у меня был прикольный бот, где я могу смотреть на девочек, который не будет забит рекламой под завязку, а просто фото и все. Так что, когда выдалось свободное время, сошлись звезды и желание, я сразу же приступил к решению этой задачиСбор данныхДля начала, я купил выгрузку данных твиттера по интересующему меня тегу, которую сервис отдает в формате csv(несколько разных файлов, которые различаются: сам твит, медиа, ссылки). Выбрав нужный мне файл, быстро пишем класс, чтобы распарсить данные, отсеять дубликаты. В итоге, в памяти, оставляются только ссылки на изображения, которые будут участвовать в обучении. Это хорошо, но все равно изображения нужно промаркировать, то есть разделить на категории. В моем случае, я выбрал: boys, girls, trash и other(вначале выбрал default, но, когда перешёл от строк к Enum, пришлось менять название категории). Все эти фото, я выгрузил, скурпулезно разделил на папочки, которые отражали метку фотографии, так что настало время для самого интересного - код. Обучение моделиДля определения того, что изображено на фото, используются алгоритмы классификации изображений.Классификация изображений Классификация изображений — это задача из области компьютерного зрения. Классификация изображений принимает изображение в качестве входных данных и классифицирует его, относя к предписанному классу. Конкретнее, я буду использовать глубокое обучение.Глубокое обучениеГлубокое обучение (глубинное обучение; англ. Deep learning) — совокупность методов машинного обучения (с учителем, с частичным привлечением учителя, без учителя, с подкреплением), основанных на обучении представлениям (англ. feature/representation learning), а не специализированным алгоритмам под конкретные задачи.Чтобы не тратить множество часов на обучение, проще всего взять готовую модель, которая уже содержит признаки изображений, и дообучить её для своих классов, чем обучать её с ноля. Я буду использовать TensorFlow Inception , которая уже обучена на популярном сете ImageNet. Теперь можно добавить тип проекта "Библиотека классов", для более удобного переиспользования данной модели и наконец начать писать код(распределение 2000 картинок, у меня заняло около 2х часов, при условии, что мне требовалось +- равное количество изображений в каждой из категорий).ОффтопЯ немного экспериментировал с количество изображений в наборах для обучения, но лучше всего себя показывал вариант, когда количество изображений, в каждой категории, примерно, равно. В данном примере используется 4 категории по 500 фото. Сначала создадим класс. Например, model и после этого добавим нужные библиотеки через nuget и добавим их к файлу класса: using Microsoft.ML;
using Microsoft.ML.Data; private readonly string _inceptionTensorFlowModel; // путь к модели Inception
private MLContext mlContext; private ITransformer model; private DataViewSchema schema; private string modelName = "model.zip"; // название модели для её сохранения private string _setsPath = @"C:\datasets"; // путь к сетам и место, куда будет сложена модель после сохранения public Model(string inceptionTensorFlowModel) { mlContext = new MLContext(); _inceptionTensorFlowModel = inceptionTensorFlowModel; } public class ImageData
{ [LoadColumn(0)] public string ImagePath; [LoadColumn(1)] public string Label; //метод, который я использую, чтобы забрать данные из папок и отмаркировать их public static (IEnumerable<ImageData> train, IEnumerable<ImageData> test) ReadData(string pathToFolder) { List<ImageData> list = new List<ImageData>(); var directories = Directory.EnumerateDirectories(pathToFolder); foreach (var dir in directories) { if (!dir.Contains("girls") && !dir.Contains("boys") && !dir.Contains("trash") && !dir.Contains("other")) continue; var label = dir.Split(@"").Last(); foreach (var file in Directory.GetFiles(dir)) { list.Add(new ImageData() { ImagePath = file, Label = label }); } } list = list.Shuffle().ToList(); return GetSets(list); } //Делим изображения на тестовую и основную выборки public static (IEnumerable<ImageData> train, IEnumerable<ImageData> test) GetSets(IEnumerable<ImageData> data) { var trainCount = data.Count() / 100 * 99; var train = data.Take(trainCount); var test = data.Skip(trainCount); return (train, test); } } public class ImagePrediction : ImageData { [ColumnName("Score")] public float[] Score; public string PredictedLabelValue; } public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{ return source.Shuffle(new Random()); } public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng) { if (source == null) throw new ArgumentNullException("source"); if (rng == null) throw new ArgumentNullException("rng"); return source.ShuffleIterator(rng); } private static IEnumerable<T> ShuffleIterator<T>( this IEnumerable<T> source, Random rng) { var buffer = source.ToList(); for (int i = 0; i < buffer.Count; i++) { int j = rng.Next(i, buffer.Count); yield return buffer[j]; buffer[j] = buffer[i]; } } private struct InceptionSettings
{ public const int ImageHeight = 224; public const int ImageWidth = 224; public const float Mean = 117; public const float Scale = 1; public const bool ChannelsLast = true; } private double TrainModel()
{ IEstimator<ITransformer> pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: "", inputColumnName: nameof(ImageData.ImagePath)) .Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input")) .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean)) .Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel). ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true)) .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label")) .Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation")) .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel")) .AppendCacheCheckpoint(mlContext); var loadImages = ImageData.ReadData(_setsPath); IDataView trainingData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.train); ITransformer model = pipeline.Fit(trainingData); IDataView testData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.test); IDataView predictions = model.Transform(testData); List<ImagePrediction> imagePredictionData = mlContext.Data.CreateEnumerable<ImagePrediction>(predictions, true).ToList(); MulticlassClassificationMetrics metrics = mlContext.MulticlassClassification.Evaluate(predictions, labelColumnName: "LabelKey", predictedLabelColumnName: "PredictedLabel"); schema = trainingData.Schema; return metrics.LogLoss; } IEstimator<ITransformer> pipeline = mlContext.Transforms.LoadImages(outputColumnName: "input", imageFolder: "", inputColumnName: nameof(ImageData.ImagePath))
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "input", imageWidth: InceptionSettings.ImageWidth, imageHeight: InceptionSettings.ImageHeight, inputColumnName: "input")) .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "input", interleavePixelColors: InceptionSettings.ChannelsLast, offsetImage: InceptionSettings.Mean)) .Append(mlContext.Model.LoadTensorFlowModel(_inceptionTensorFlowModel).
ScoreTensorFlowModel(outputColumnNames: new[] { "softmax2_pre_activation" }, inputColumnNames: new[] { "input" }, addBatchDimensionInput: true)) .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName: "LabelKey", inputColumnName: "Label"))
.Append(mlContext.MulticlassClassification.Trainers.LbfgsMaximumEntropy(labelColumnName: "LabelKey", featureColumnName: "softmax2_pre_activation"))
.Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabelValue", "PredictedLabel"))
.AppendCacheCheckpoint(mlContext); var loadImages = ImageData.ReadData(_setsPath);
IDataView trainingData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.train); model = pipeline.Fit(trainingData); IDataView testData = mlContext.Data.LoadFromEnumerable<ImageData>(loadImages.test);
IDataView predictions = model.Transform(testData); List<ImagePrediction> imagePredictionData = mlContext.Data.CreateEnumerable<ImagePrediction>(predictions, true).ToList(); MulticlassClassificationMetrics metrics = mlContext.MulticlassClassification.Evaluate(predictions, labelColumnName: "LabelKey", predictedLabelColumnName: "PredictedLabel"); schema = trainingData.Schema;
return metrics.LogLoss; public void SaveModel() => mlContext.Model.Save(model, schema, Path.Combine(_setsPath, modelName));
public void FitModel()
{ var LogLoss = TrainModel(); Console.WriteLine($"LogLoss is {LogLoss}"); SaveModel(); } private PredictionEngine<ImageData, ImagePrediction> predictor;
public ImagePrediction ClassifySingleImage(string filePath)
{ if (model == null) LoadModel(); if (predictor == null) predictor = mlContext.Model.CreatePredictionEngine<ImageData, ImagePrediction>(model); var imageData = new ImageData() { ImagePath = filePath }; return predictor.Predict(imageData); } public void LoadModel() => model = mlContext.Model.Load(Path.Combine(_setsPath, modelName), out schema); static void Main(string[] args)
{ Console.ForegroundColor = ConsoleColor.White; Stopwatch s = new Stopwatch(); s.Start(); Model model = new Model(@"C:\tensorflow_inception_graph.pb"); model.FitModel(); Console.WriteLine($"##### Model train ended for {s.Elapsed.Minutes}:{s.Elapsed.Seconds} #####"); s.Restart(); var res1 = model.ClassifySingleImage(@"C:\EugRqKFXUAYMTWz.jpg"); Console.WriteLine($" > It's trash. Classification result is {res1.PredictedLabelValue} with score: {res1.Score.Max()}"); Console.WriteLine($"##### Ended for {s.Elapsed.Minutes}:{s.Elapsed.Seconds} #####"); s.Restart(); var res2 = model.ClassifySingleImage(@"C:\EvpmOjIXcAMgj5r.jpg"); Console.WriteLine($" > It's girl. Classification result is {res2.PredictedLabelValue} with score: {res1.Score.Max()}"); Console.WriteLine($"##### Ended for {s.Elapsed.Minutes}:{s.Elapsed.Seconds} #####"); } И получил такие результаты: Несмотря на достаточно слабые метрики(я все таки использовал для тестов 20 изображений): 0.55, но модель отлично справилась со своими задачами. Именно такую модель, я использую для своего nsfw-бота, который получает данные из твиттера, а потом классифицирует и постит их.Так что достаточно не сложно обучить модель и добавить в свой проект, главное желание разобраться. И никогда не стоит останавливаться в том, чтобы учиться чему-то новому. =========== Источник: habr.com =========== Похожие новости:
Машинное обучение ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 19:39
Часовой пояс: UTC + 5