Систематический поиск оптимальной стратегии обучения для задачи классификации изображений видов птиц

Вступление

Хотите работать инженером по машинному обучению, но никогда не работали над проектами машинного обучения? Тогда найти работу непросто. Большинство компаний ищут опытных инженеров по машинному обучению. Имея опыт, я не имею в виду, что вы прошли онлайн-курс машинного обучения. Не поймите меня неправильно: всегда приятно проходить онлайн-курсы по машинному обучению, чтобы получить больше знаний по этой теме! Однако работодателю очень сложно правильно оценить онлайн-курс. Некоторые из них очень простые, а некоторые очень сложные. Однако работодатель может хорошо оценить собственные проекты. Там он может напрямую увидеть, как вы подходите к определенным темам и какой опыт вы уже приобрели в проектах.

Однако в этих проектах вам больше не следует сосредотачиваться только на части машинного обучения, которая в основном выполняется в записных книжках Jupyter, но вам также следует подумать о развертывании. Потому что в настоящее время обучение модели глубокого обучения больше не является сложной задачей. Такие библиотеки, как Keras, позволяют создавать и тренировать модель глубокого обучения всего в нескольких строках кода. Однако если вы умеете разработать полноценное приложение, то вам однозначно намного интереснее. Кроме того, вы можете лучше убедить рекрутера с нетехническим образованием, если вы разработали веб-страницу и можете показать на ней свою обученную модель, вместо того, чтобы проводить его через свой блокнот Jupyter, где можно увидеть только код и выходные данные для печати.

По этой причине я создал две статьи, в которых систематически обнаруживается и применяется стратегия обучения глубокому обучению, а обученная модель развертывается через веб-сайт.

В этой первой части серии я хочу продемонстрировать вам систематический подход к поиску хорошей модели для задачи классификации изображений. В качестве набора данных я решил использовать набор данных о видах птиц с открытым исходным кодом от Kaggle, который вы можете найти здесь. Код и всю документацию можно найти на моей странице Github здесь. Код написан на Python.

Во второй части этой серии я покажу вам, как разработать полноценное веб-приложение, включая интерфейсную и внутреннюю части, с использованием html и Flask. Статью можно здесь.

Содержание

В первом разделе я представляю набор данных и уже применяю некоторую предварительную обработку к входным данным. Во втором разделе я покажу вам, как я создал входной конвейер с помощью Tensorflow и как выглядит код для него. В разделе «Методология» описаны различные оценки, которые я выполнил, чтобы найти оптимальную стратегию обучения. Эти оценки могут использоваться всякий раз, когда необходимо обучать CNN. В разделе «Результаты» показаны результаты обучения окончательной стратегии обучения. В разделе «Заключение» суммируются результаты этого проекта, а в разделе «Перспективы» содержится ссылка на вторую статью этой серии.

Исследовательский анализ и предварительная обработка данных

В качестве первого шага я загрузил предоставленный файл Bird_Species.csv во фрейм данных pandas (рисунок 1).

Создатель набора данных также предоставляет второй файл csv, содержащий классы и некоторые метаданные изображений. Я также загрузил этот CSV-файл во фрейм данных pandas (рисунок 2).

Затем я быстро проверил количество различных классов в этом наборе данных, используя второй фрейм данных, и сравнил его с количеством уникальных меток в файле «Bird_Species.csv» (код 1).

Интересно, что согласно файлу class_dict.csv существует 300 различных классов птиц, но во всем наборе данных всего 285 различных классов. Поэтому я проверил, какие классы не представлены в наборе данных, и просмотрел папки, чтобы увидеть, действительно ли они не представлены или просто отсутствуют в файле Bird_Species.csv. И действительно, были изображения для отсутствующих классов. Это означает, что существующий файл CSV неверен. Итак, я сначала создал чистый файл csv, сохранил его и использовал для остальной части этого проекта. Код для этого шага можно найти в записной книжке Make_Clean_Dataset.ipynb здесь.

Теперь, когда набор данных чист, я начал его дальнейшее изучение. Я начал с построения нескольких случайных примеров изображений набора данных, чтобы получить представление о том, как они выглядят. На рисунке 3 показаны два примера изображений птиц.

В качестве следующего шага я построил график распределения уже созданных автором обучающих и тестовых наборов (рисунок 4 и рисунок 5). Это важно, чтобы проверить, не является ли набор данных несбалансированным, и убедиться, что распределение тестов и распределение обучения примерно одинаковы.

Как видно, обучающая выборка несбалансированная, а тестовая - полностью сбалансированная. Это ясно показывает, что набор тестов происходит из другого распределения, чем обучающий набор. Это может привести к модели, которая хорошо работает на тестовом наборе, но плохо работает на реальных данных, потому что тестовое распределение не отражает «реальное» распределение. Поэтому я решил создать свои собственные наборы для обучения, проверки и тестирования, используя расслоение в случайном порядке из Scikit-Learn. Но перед разделением данных я также горячо закодировал метки, чтобы они соответствовали желаемому формату ввода для CNN. Код 2 показывает код для этих шагов, включая начальную загрузку csv-файла очищенного набора данных.

На рисунках 6 и 7 показано распределение обучающей и тестовой выборки после стратифицированного перемешивания. Оба дистрибутива теперь происходят из одного и того же дистрибутива.

Набор обучающих данных немного несбалансирован, что не должно быть проблемой. Но давайте позже проверим, может ли передискретизация улучшить производительность этого набора данных.

Рисунок проверочного набора сюда не добавляется, но имеет то же распределение, что и тестовый набор и обучающий набор.

Создать входной конвейер

Для обучения модели глубокого обучения всегда важно иметь хороший конвейер ввода. Tensorflow очень хорошо поддерживает вас своим классом ImageDataGenerator. Этот класс позволяет вам указать некоторые предварительные обработки, позволяет вам выбирать из некоторых дополнений данных и позволяет загружать изображения пакетно во время обучения. Это особенно важно, потому что с большими наборами данных потребовалось бы много оперативной памяти, если бы все изображения должны были быть загружены один раз перед обучением.

Для классификации видов птиц я создал следующие этапы входного конвейера:

  1. Примените несколько случайно выбранных дополнений данных, так что примерно 10% данных не будут дополнены.
  2. Нормализовать значения пикселей изображения, чтобы они находились в диапазоне (0,1).

Я использовал некоторые базовые дополнения данных из библиотеки Python imgaug, чтобы увеличить вариации в наборе данных. Эта библиотека очень полезна, потому что она реализует почти все дополнения, о которых вы можете подумать. Дополнения данных, используемые для этого проекта, выбираются вручную путем применения дополнения к образцу изображения и оценки того, имеет ли изображение смысл или нет. Результаты оценки различных примененных дополнений можно увидеть в записной книжке Jupyter под названием Check Augmentations.ipynb в вышеупомянутом репозитории Github. В общем, можно использовать эти дополнения и можно обучать модель с одним дополнительным дополнением за раз и сравнивать ее производительность с базовой моделью без каких-либо дополнений. Но ради этого проекта я решил не проводить эту оценку, потому что я предполагаю, что каждое расширение приводит к улучшению по сравнению с базовой моделью.

Я использовал следующие аугментации (рис. 8):

  1. Отразить изображение влево вправо.
  2. Умножайте значения пикселей со смещением.
  3. Соль и перец.
  4. Изменение гамма-контраста.
  5. Добавьте смещение к значениям пикселей.
  6. Добавьте аддитивный гауссовский шум.
  7. Примените размытие в движении.
  8. Примените аффинное преобразование.
  9. Поверните изображение.
  10. Примените эластичное преобразование.

Увеличение «Добавить» и «Гамма-контраст» никогда не используются одновременно, поскольку это может привести к нереалистичным изображениям.

Код 3 показывает полный код Python для создания входного конвейера, при этом используется опция «flow_from_dataframe» в Tensorflow. Это позволяет загружать изображения пакетно во время обучения. Вам нужен только CSV-файл, в котором первый столбец содержит имя изображения, а другие столбцы содержат метки для этого изображения. Чтобы сначала найти оптимальную архитектуру CNN, я решил использовать размер пакета 8 и установил размер изображений (224, 224).

Методология

Входной конвейер создан. Пришло время выбрать наиболее подходящую стратегию обучения. Прежде всего, сравниваются некоторые современные архитектуры CNN, и лучшая из них используется в качестве архитектуры для оставшейся части этого проекта. Во-вторых, сравниваются разные размеры изображений, чтобы найти оптимальный размер изображения. В качестве третьего шага делается попытка передискретизации немного несбалансированного набора данных. И в качестве последнего шага выполняется поиск оптимальных гиперпараметров с помощью байесовского поиска гиперпараметров.

Код раздела методологии не включен в эту статью, потому что он будет слишком длинным. Не стесняйтесь проверить мою записную книжку Github Jupyter, чтобы увидеть и скопировать созданный мной код. Я включил только код для передискретизации фрейма данных, потому что он может быть более интересной частью кода.

Сравнение архитектуры CNN

Существует множество различных доступных архитектур CNN, которые можно использовать для классификатора птиц. В этом проекте выбраны шесть различных архитектур CNN (таблица 2) и сравниваются друг с другом. Каждая архитектура используется для обучения классификатора птиц с гиперпараметрами, приведенными в таблице 1. В конце концов, лучший результат проверки f1 сохраняется и используется для поиска лучшей архитектуры CNN. Здесь используется только лучшая проверка f1-score, и она игнорируется, что каждая архитектура имеет разную сложность обучения и что, возможно, одна архитектура приводит лишь к немного менее хорошим f1-оценкам проверки, но имеет намного меньше параметров, чем модель, которая достигает более высокий показатель проверки f1. Но для будущей оптимизации, сложность обучения также может быть учтена и может быть включена в решение, какую архитектуру кодера использовать для окончательного классификатора птиц. Таблица 2 также показывает окончательные результаты. Как можно видеть, DenseNet121 обеспечивает наилучшую оценку f1 при проверке и поэтому используется в качестве окончательной архитектуры кодировщика для классификатора птиц, а также для других оценок этого проекта. На рисунке 5 показаны значения f1 в процессе обучения для различных кодировщиков, а на рисунке 4 - значения потерь во время процесса обучения.

Сравнение размеров изображений

На пути к оптимальной стратегии обучения следует найти оптимальный размер изображения. Будут оцениваться и сравниваться четыре различных варианта. DenseNet обучается для каждого из четырех размеров изображения с гиперпараметрами из Таблицы 1. Результаты можно найти в Таблице 3, где снова в качестве метрики для принятия решения принимается лучший f1-балл проверки. На рисунках 6 и 7 показаны результаты оценки f1 и значений потерь во время процесса обучения для изображений разных размеров.

Как можно было догадаться: чем больше изображения, тем лучше производительность модели. Однако при увеличении размера изображения 192x192 до 224x224 лучший результат проверки f1-score увеличился только на 0,4%. Поэтому я решил использовать в качестве размера изображения 192x192, чтобы уменьшить количество обучаемых параметров и немного ускорить процесс обучения.

Передискретизация

Как упоминалось ранее, набор данных немного несбалансирован. Следовательно, передискретизация может использоваться для лучшего баланса набора данных и во избежание риска того, что модель будет более смещена в сторону классов большинства и будет менее точной при прогнозировании классов меньшинства (рисунок 8, код 4).

Затем DenseNet121 обучается с использованием набора данных с избыточной выборкой и гиперпараметров из таблицы 1, за исключением того, что количество эпох сокращается до 20 эпох. Это происходит из-за передискретизации и, следовательно, из-за того, что модель должна учиться быстрее, потому что одни и те же изображения доступны более одного раза в течение одной эпохи обучения. Наилучший показатель f1 для проверки модели с избыточной выборкой составляет 95,4%, что почти такое же, как и в случае, когда передискретизация не применяется. Следовательно, передискретизация не используется для обучения окончательного классификатора птиц, потому что она также требует больше времени на обучение и, как правило, более склонна к переобучению.

Байесовский гиперпараметрический поиск

В качестве последнего шага к поиску оптимальной стратегии обучения гиперпараметры оптимизируются с помощью байесовского поиска по гиперпараметрам. Байесовский поиск имеет то преимущество, что он более эффективен в поиске оптимальных гиперпараметров, чем случайный поиск, и требует меньше итераций, чем поиск по сетке. В качестве стратегии оптимизации используется гауссовский процесс с каппа 3. Четыре начальных точки задаются вручную, что поможет направить процесс оптимизации в оптимальное русло. Байесовская оптимизация выполняется за 12 итераций. Используется функция сбора данных, именуемая «Нижняя граница уверенности», и она получает лучший проверочный показатель f1 в качестве метрики для оптимизации. Нижняя граница уверенности пытается минимизировать свой показатель оптимизации. Следовательно, используется отрицательная оценка f1 для наилучшей проверки. В таблице 4 показано использованное пространство поиска для гиперпараметров, а в таблице 5 показаны лучшие параметры. Скорость затухания указывает, насколько должна уменьшаться скорость обучения каждые эпохи шагов затухания.

На рисунке 9 показан график сходимости байесовского поиска гиперпараметров. Как видим, лучшие параметры находятся на последних итерациях. Это связано с природой байесовской оптимизации. Вначале существует много неопределенности, и выборки модели Байеса находятся в неоптимальной области. Но, в конце концов, модель делает больше выборок в оптимальной области и, следовательно, находит все лучшие и лучшие параметры.

Полученные результаты

Классификатор птиц обучен всем выводам, приведенным в разделе «Методология». Классификатор птиц теперь обучен для 30 эпох, и лучшая модель в соответствии с проверкой f1-score сохраняется как модель Tensorflow (рисунок 10). После этого загружается лучшая модель с оценкой f1 96,2% и оценивается на тестовом наборе для проверки эффективности окончательного классификатора птиц на реальных данных. Лучшая модель набирает почти 96% балла f1 в наборе тестов удержания, что почти совпадает с лучшим результатом проверки f1, достигнутым в процессе обучения. Это показывает, что модель очень хорошо работает с реальными данными и что нет переоснащения модели на данных обучения и проверки.

Заключение

Последний классификатор птиц набирает почти 96% по шкале f1 на тестовом наборе. В качестве базовой архитектуры CNN используется DenseNet121 из-за его хорошей производительности. В качестве размера целевого изображения используется размер 192x192 пикселей. Обучающий набор не подвергается избыточной выборке, потому что модель, обученная на тренировочном наборе с избыточной выборкой, достигла примерно того же проверочного f1-балла, что и модель, которая была обучена на обучающем наборе без избыточной выборки. Некоторые гиперпараметры оптимизированы за счет использования байесовского поиска по гиперпараметрам.

Перспективы

Во второй части этой серии я разрабатываю API с интерфейсом, написанным на HTML, и серверным приложением с использованием библиотеки Python Flask. Прочтите вторую статью, если вам интересно, как это работает. Вторую статью вы можете найти здесь. В общем, я всегда рекомендую встроить окончательное приложение машинного обучения в развертываемое приложение, потому что это то, о чем в конце концов должен подумать инженер по машинному обучению.

Спасибо, что дочитали мою статью до конца! Надеюсь, вам понравилась эта статья и проект, над которым я работал. Если вы хотите читать больше подобных статей в будущем, подписывайтесь на меня, чтобы оставаться в курсе.