Перенести обучение на практику. Классификация изображений отелей с библиотекой fast.ai

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

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

Для достижения цели мы использовали библиотеку fast.ai, повышающую уровень абстракции PyTorch. Он относительно новый, но уже поддерживает передовые методы и всегда в курсе достижений в области глубокого обучения. Он предоставлен Джереми Ховардом с его (отличным) курсом, очень подходящим для создания прототипов нейронных сетей. Это позволило нам сосредоточиться на решениях, а не на кодировании.

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

Во-первых, всегда есть много бесплатных наборов данных. Kaggle - отличный источник, а также коллекции MIT и многие другие. Для нашей задачи неплохо подходит набор данных для распознавания внутренней сцены. Требовалась некоторая предварительная обработка, а категорий было гораздо больше, чем нужно. Когда дело доходит до данных для обучения, всегда легче, когда у вас их больше, чем требуется, поскольку вы можете исключить ненужные. Второй вариант - просто использовать Google Graphics. У них открытый API, а GitHub предоставляет удобную библиотеку. Первая сотня результатов по каждому ключевому слову (категории) обычно довольно точна. Если нам нужно больше, вам может потребоваться их краткое ознакомление и исключить неточные изображения. Есть и третий способ - арендовать опрос, например, Amazon Mechanical Turk. В нашем случае мы использовали первые два варианта.

Хочу отметить, что подготовка категорий и всего набора данных - довольно важная задача. В нашем случае категории должны быть исключительными. Легко выбрать две категории, которые должны содержать одно и то же изображение. В чем разница между шкафом и кладовой? Мы знаем, что шкаф может быть кладовой. Но сеть не знает.

Затем мы должны разделить набор данных на две части: обучающую часть, на которой мы обучаем модель, и часть проверки, используемую для измерения ее производительности. От 7 до 3 - подходящее соотношение. Вот совет: настройте случайное семя перед тем, как начать. Если вы этого не сделаете и попытаетесь продолжить тренировку в следующий раз, ваше разделение будет другим, и набор для проверки может перекрывать набор для обучения. Это прямой способ переобучения (и если у вас нет третьего набора данных для проверки, вы его не увидите). Переоснащение - это когда ваша сеть «запоминает» изображения вместо того, чтобы учиться их обобщать.

У нас должно быть примерно одинаковое количество изображений в каждой категории, и мы должны помнить о нормализации изображений (fast.ai справится с этим).

ResNet - это модель нейронной сети 2015 года, которая теперь имеет множество вариантов и улучшений, но базовая версия по-прежнему «достаточно хороша» почти для всех распространенных случаев. Чтобы правильно описать эту модель, потребовалась бы совершенно новая статья, но вкратце, это модель, которая позволяет добавлять больше слоев и углубляться без потери результатов (она решает проблему исчезающего градиента).

Теперь критический функционал: передача обучения. Когда мы создаем нейронную сеть с нуля, все веса инициализируются нулями или некоторыми случайными значениями. И настройка их для распознавания изображений занимает гораздо больше времени, чем у нас. Чтобы сэкономить время, мы используем сеть, которая уже обучена на изображениях со стандартными категориями. Только несколько верхних слоев утяжелителей отвечают за выбор правильного класса. Все слои ниже являются распознаваемыми элементами с меньшим уровнем абстракции, то есть градиентами, кривыми, линиями, пикселями и т. Д. Таким образом, нам нужно только переобучить верхние слои с нуля и немного настроить другие.

Перед обучением у нас есть выбор значений параметров. Самым важным является скорость обучения (lr). Для достижения более быстрой сходимости (и, возможно, большей точности) скорость обучения должна изменяться во время обучения. Библиотека предлагает нам устанавливать скорость обучения в соответствии со следующей формой.

Мы должны выбрать максимальное значение, и форма будет применена автоматически.

Вот как выглядит простой прогон:

Наша модель - resnet50, предварительно обученная на имаженете. Тренируем 10 эпох. Но перед этим, чтобы найти правильную скорость обучения (lr), нам нужно запустить:

График показывает, как меняются потери для разных темпов обучения. Мы выбрали значение, при котором убыток все еще уменьшается. Вот ~ 10-2.

Вот как выглядят результаты после обучения в течение 10 эпох со скоростью обучения 10-2.

Это график потерь для обучающего набора и набора проверки. Сеть работает намного хуже на наборе для проверки. Это перекрывает.

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

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

Снижение веса - это метод регуляризации, при котором алгоритм обучения добавляет штраф, когда значения веса становятся слишком низкими или слишком высокими. Идеальные значения веса должны соответствовать распределению со средним значением, равным нулю, и стандартным отклонением, близким к единице.

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

И, наконец, мы всегда можем увеличить размер набора данных или изменить количество эпох.

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

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

Результаты:
потеря поезда - 0,703716
допустимая потеря - 1.000399
точность - 70,4%

Дальнейшее обучение мало что улучшит.

Мы пытались настроить его по-разному, но все же он не приближается к 96% - уровню, который мы можем получить, когда обучаем сеть распознавать кошек и собак. В чем разница?

Матрица путаницы может показать нам, как наша сеть классифицирует различные категории.

Сеть правильно классифицирует большинство категорий (по диагонали), но есть некоторые недостатки.

99 - front_hotel как открытый
81 - открытый как front_hotel
49 - рецепция как вестибюль
44 - бар как ресторан

Интуитивно некоторые бары можно легко спутать с ресторанами, а также стойку регистрации с вестибюлем. Фасадный отель и открытый бассейн - определенно ошибочно выбранные категории. После исключения ненужных классов мы можем добиться точности до 76%. Остались недостающие 20%.

Мы можем посмотреть на худшую классификацию:

Это не вестибюль, но и не ресторан, как было указано в оригинале. Мы могли бы исправить какие-то неправильные ярлыки или удалить несвязанные изображения, и мы получим еще 2-5%.

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

Это широкое поле для дальнейших исследований, и я опишу его в следующей статье.

Ознакомьтесь с живой версией нашего приложения здесь

Хотите больше от команды Nexocode? Следуйте за нами в Medium, Twitter и LinkedIn. Хотите вместе творить волшебство? Мы нанимаем!