Использование модели TensorFlow Inception в качестве основы для переобучения настраиваемого набора классификаций изображений
За последние пару лет крупные компании, включая Google, Facebook, Microsoft и Amazon, выпускали библиотеки, фреймворки и сервисы, которые позволяют другим компаниям создавать модели машинного обучения (ML). В этих фреймворках замечательно то, что теперь дешевле и быстрее проводить эксперимент по машинному обучению для вашего бизнеса.
Построение полезных моделей машинного обучения часто требует большого количества данных - тысяч примеров - а также много времени для подготовки данных в формате, подходящем для системы. Контент должен быть тщательно отобран и иметь высокое качество. Это не всегда легко найти.
Благодаря наличию библиотек и фреймворков машинного обучения вы можете взять модель, которая уже была обучена на большом наборе данных, и переобучить ее с меньшим набором данных, чтобы создать прототип своего собственного варианта использования машинного обучения.
Это все равно, что купить сырую пиццу с предварительно приготовленным тестом, соусом и сыром, а затем принести ее домой, добавить свою начинку и приготовить в духовке.
С выпуском Google TensorFlow мир получил доступ к мощной библиотеке для численных вычислений с использованием графов потоков данных для проведения машинного обучения и глубоких исследований нейронных сетей. Он может решать такие проблемы, как распознавание рукописного ввода, распознавание изображений, языковой перевод и распознавание речи. В этом примере мы сосредоточились на распознавании изображений и на том, как мы можем использовать TensorFlow, чтобы изучить, как эти распознаватели работают на практике.
Сайт TensorFlow предоставляет отличный набор руководств. Я использовал статью о переобучении изображений Как перенастроить последний слой Inception для новых категорий, чтобы начать создавать собственный классификатор изображений на основе Inception. Inception - это кодовое название архитектуры глубокой сверточной нейронной сети (CNN), которая достигает нового уровня техники для классификации и обнаружения в наборе данных ImageNet.
Преимущество повторного обучения изображений вместо обучения классификатора с нуля заключается в том, что мы можем воспользоваться преимуществом Transfer Learning.
Трансферное обучение - это не столько техника, сколько полезный атрибут сетей глубокого обучения, который мы можем использовать для обучения моделей с меньшим объемом данных. Например, глубокая нейронная сеть, обученная для перевода с английского на французский, может быть переобучена для перевода на другой язык с меньшим объемом данных, поскольку слои более высокого уровня фиксируют математические отношения или абстракции слов.
Редко кто-то имеет доступ к большому и разнообразному набору данных, достаточному для обучения CNN с нуля. Нам нужно только переобучить последний слой в нейронной сети, который действительно различает наши категории изображений, используя при этом все промежуточные уровни, которые были обучены в ImageNet, для распознавания шаблонов абстрактных изображений более высокого уровня.
Настройка TensorFlow: добавьте ингредиенты
- Для начала необходимо установить Python 3.5.x и Pip.
- Установите TensorFlow, следуя этому руководству.
- Клонируйте репозиторий TensorFlow:
git clone https://github.com/tensorflow/tensorflow.git
- Перейдите в каталог:
cd ./tensorflow/tensorflow/examples/image_retraining/
, который содержит источник, необходимый для запуска процесса переподготовки по модели Inception.
Подготовьте данные для тренировок: соберите пиццу
Чтобы научить вашу модель распознавать новые категории изображений, нам нужно собрать набор изображений для каждой категории. Мы будем использовать часть из них, чтобы повторно обучить Inception распознавать новые категории, и зарезервируем меньшую часть для проверки точности нашей модели. Быстрый и простой способ получить изображения категории - использовать Поиск картинок Google и расширение Chrome под названием Gallerify.
Вдохновленный беседой с Джейми, нашим директором по коммуникациям и матерью малыша, о том, что машинное обучение похоже на обучение маленького ребенка, я хотел создать классификатор, который мог бы различать красные шары и красные яблоки. Ее малыш узнал, что такое мяч, но указывал на яблоко со словами мяч. Ему нужно было больше обучающих примеров, чтобы правильно классифицировать эти два объекта.
Поэтому после выполнения поиска в Google Image по запросу «красные шары» и «красные яблоки» я использовал расширение Gallerify для загрузки изображений и поместил их в две папки с разными именами. Вы можете сделать то же самое с любыми изображениями, которые используете.
Затем создайте training_data/
подпапку в каталоге image_retraining/
, в которой вы поместите две папки с изображениями по каждой категории. В процессе переобучения Inception имена каталогов используются в качестве метки для категории изображений, к которым они будут отнесены. Переместите некоторые изображения из каждой категории в test_data/
папку, которая не будет использоваться для процесса переподготовки.
Важное примечание: мы используем эти данные изображения в качестве примеров, которые модель CNN Inception будет использовать для получения математической модели, которая различает элементы изображений. Единственное явное различие, которое мы проводим, - это метка, связанная с каждым изображением, на основе имени папки, в которой оно содержится, и нашего выбора мульти-меточного классификатора CNN. Мы не кодируем никаких конкретных правил или логики, которые различают эти два класса.
По этой причине очень важно, чтобы данные, которые мы предоставляем в качестве обучающих примеров, были чистыми, репрезентативными и обеспечивали хорошее покрытие всех типов входных данных, которые мы ожидаем использовать для получения точных результатов от нашей модели. Если обучающие данные не точно представляют типы данных, которые, как мы ожидаем, модель будет прогнозировать в будущем, мы можем непреднамеренно внести в модель ошибку или неточность. Например, я удалил изображение мультяшного персонажа с красным мячом, потому что оно не соответствовало красным шарам.
Переобучить модель: испечь пиццу
Настроив данные для обучения, мы готовы переобучить начальную модель. Мы сделаем это, запустив модуль python retrain.py
в каталоге image_retraining/
:
python retrain.py --how_many_training_steps 500 -- output_graph=./retrained_graph.pb --output_labels=./retrained_labels.txt --image_dir=./training_data
Это запустит алгоритм переобучения с в основном параметрами по умолчанию, но вы можете управлять дополнительными параметрами, указав дополнительные аргументы командной строки. Вы можете получить полный список, используя флаг -h
:
python retrain.py -h
Программа будет выводить логи на консоль через процесс обучения:
INFO:tensorflow:Looking for images in 'Red Apple'WARNING:tensorflow:WARNING: Folder has less than 20 images, which may cause issues. INFO:tensorflow:Looking for images in 'Red Ball' WARNING:tensorflow:WARNING: Folder has less than 20 images, which may cause issues. >> Downloading inception-2015-12-05.tgz 100.0% INFO:tensorflow:Successfully downloaded inception-2015-12-05.tgz 88931400 bytes. Extracting file from ./inception-march-3-2018/inception-2015-12-05.tgz Model path: ./inception-march-3-2018/classify_image_graph_def.pb
Сначала он ищет изображения в ваших папках с данными обучения, а затем загружает версию ранее обученной модели начального уровня, потому что мы переобучаем только последний слой. Вы увидите, как скрипт начинает создавать файлы узких мест:
INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_142.jpg_inception_v3.txt INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_143.jpg_inception_v3.txt INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_144.jpg_inception_v3.txt INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_145.jpg_inception_v3.txt INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_146.jpg_inception_v3.txt INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_147.jpg_inception_v3.txt INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_149.jpg_inception_v3.txt
«Узкое место» - неофициальный термин, используемый для слоя непосредственно перед окончательным выходным слоем, который фактически выполняет классификацию. По умолчанию они хранятся в /tmp/bottleneck
directory, и если вы повторно запустите скрипт, они будут повторно использованы, так что вам не придется снова ждать этой части.
Если вы столкнулись с плохим яблоком 🍎, с трассировкой стека ошибок, как показано ниже:
INFO:tensorflow:Creating bottleneck at ./bottlenecks/Red Apple/redapple_136.jpg_inception_v3.txt Not a JPEG file: starts with 0x89 0x50 Traceback (most recent call last): File "retrain.py", line 1486, in <module> tf.app.run(main=main, argv=[sys.argv[0]] + unparsed) File "/Users/barnhart/anaconda/envs/py35/lib/python3.5/site-packages/tensorflow/python/platform/app.py", line 48, in run _sys.exit(main(_sys.argv[:1] + flags_passthrough)) File "retrain.py", line 1294, in main export_model(model_info, class_count, FLAGS.saved_model_dir) File "/Users/barnhart/anaconda/envs/py35/lib/python3.5/site-packages/tensorflow/python/client/session.py", line 1214, in __exit__ exec_type, exec_value, exec_tb) File "/Users/barnhart/anaconda/envs/py35/lib/python3.5/contextlib.py", line 77, in __exit__ self.gen.throw(type, value, traceback) File "/Users/barnhart/anaconda/envs/py35/lib/python3.5/site-packages/tensorflow/python/framework/ops.py", line 3625, in get_controller yield default File "retrain.py", line 1187, in main bottleneck_tensor, FLAGS.architecture) File "retrain.py", line 500, in cache_bottlenecks resized_input_tensor, bottleneck_tensor, architecture) File "retrain.py", line 442, in get_or_create_bottleneck bottleneck_tensor) File "retrain.py", line 397, in create_bottleneck_file str(e))) RuntimeError: Error during processing file ./training_data/Red Apple/redapple_136.jpg (Invalid JPEG data, size 4068 [[Node: DecodeJpeg_1 = DecodeJpeg[acceptable_fraction=1, channels=3, dct_method="", fancy_upscaling=true, ratio=1, try_recover_truncated=false, _device="/job:localhost/replica:0/task:0/cpu:0"](_recv_DecodeJPGInput_0)]]
… Это означает, что изображение не является допустимым файлом формата JPEG (возможно, Gallerify сохранил его в формате, отличном от исходного). Попробуйте удалить это изображение из данных о тренировке и выберите замену. Вы можете повторно запустить тот же сценарий переобучения, и он продолжится с того места, где вы остановились.
Как только он сможет создать файлы узких мест для всех ваших образов обучающих данных, он сможет приступить к обучению последнего уровня Inception:
INFO:tensorflow:2018-03-05 12:09:05.076961: Step 0: Train accuracy = 61.0% INFO:tensorflow:2018-03-05 12:09:05.077692: Step 0: Cross entropy = 0.599025 INFO:tensorflow:2018-03-05 12:09:05.213300: Step 0: Validation accuracy = 51.0% (N=100) INFO:tensorflow:2018-03-05 12:09:06.192184: Step 10: Train accuracy = 100.0% INFO:tensorflow:2018-03-05 12:09:06.192382: Step 10: Cross entropy = 0.253409 INFO:tensorflow:2018-03-05 12:09:06.296140: Step 10: Validation accuracy = 100.0% (N=100) INFO:tensorflow:2018-03-05 12:09:07.352922: Step 20: Train accuracy = 100.0% INFO:tensorflow:2018-03-05 12:09:07.353142: Step 20: Cross entropy = 0.156156 INFO:tensorflow:2018-03-05 12:09:07.464078: Step 20: Validation accuracy = 100.0% (N=100) INFO:tensorflow:2018-03-05 12:09:08.432503: Step 30: Train accuracy = 100.0% INFO:tensorflow:2018-03-05 12:09:08.432636: Step 30: Cross entropy = 0.103196 INFO:tensorflow:2018-03-05 12:09:08.526025: Step 30: Validation accuracy = 100.0% (N=100) INFO:tensorflow:2018-03-05 12:09:09.487891: Step 40: Train accuracy = 100.0% INFO:tensorflow:2018-03-05 12:09:09.488104: Step 40: Cross entropy = 0.085478
Каждые 10 шагов модели обучения он сообщает следующее:
- Точность обучения: насколько хорошо классификатор работает с обучающей выборкой.
- Перекрестная энтропия: функция потерь, которая измеряет, насколько хорошо идет обучение.
- Точность проверки: насколько хорошо классификатор работает с зарезервированным набором изображений для тестирования.
После 500 шагов вы увидите сообщения журнала, указывающие, что ваша модель обучена и сохранена:
INFO:tensorflow:2018-03-05 12:09:55.249556: Step 499: Train accuracy = 100.0% INFO:tensorflow:2018-03-05 12:09:55.249698: Step 499: Cross entropy = 0.007347 INFO:tensorflow:2018-03-05 12:09:55.341729: Step 499: Validation accuracy = 100.0% (N=100) Model path: ./inception-march-3-2018/classify_image_graph_def.pb INFO:tensorflow:Restoring parameters from /tmp/_retrain_checkpoint INFO:tensorflow:Final test accuracy = 100.0% (N=5) Model path: ./inception-march-3-2018/classify_image_graph_def.pb INFO:tensorflow:Restoring parameters from /tmp/_retrain_checkpoint INFO:tensorflow:Froze 2 variables. Converted 2 variables to const ops. Model path: ./inception-march-3-2018/classify_image_graph_def.pb INFO:tensorflow:Restoring parameters from /tmp/_retrain_checkpoint INFO:tensorflow:No assets to save. INFO:tensorflow:No assets to write. INFO:tensorflow:SavedModel written to: b'/tmp/saved_models/1/saved_model.pb'
Тестирование модели: попробуйте пиццу
Итак, у нас есть модель, сохраненная на диск. Что теперь?
Мы можем протестировать нашу модель с изображениями, которые мы исключили из процесса обучения, или найти совершенно новые, и посмотреть, насколько хорошо наша модель обобщает - это способность модели правильно классифицировать ранее невидимые изображения. Мы также увидим, как алгоритм возвращает статистическую достоверность, связанную с каждой категорией, для определенного изображения, которое он пытается классифицировать.
Но сначала нам нужен код, который позволяет нам читать новое изображение с диска (указанное как путь аргумента командной строки к изображению), загружать нашу обученную модель с диска и применять модель к изображению для получения прогнозов. Следующий label_image.py
скрипт Python выполняет это:
Теперь мы можем запустить скрипт и протестировать наше первое изображение, выполнив команду:
python label_image.py ~/Dev/experiment/tensorflow/ic_test_data/red_apple/redapple_003.jpg
что приводит к:
red apple (score = 0.99650) red ball (score = 0.00350)
Наша модель на 99,6% уверена, что это красное яблоко, или только на 0,03% уверена, что это может быть красный шар. Совершенно очевидно, что это яблоко, так что это хорошо. Но вы можете видеть, что существует распределение вероятностей, которое возвращается, поэтому конечной системе, возможно, придется использовать пороговые значения (например,> 75% уверенности), если мы должны были вернуть один ответ. Например, давайте попробуем изображение посложнее:
Для этого изображения, похожего на игрушку из искусственного яблока, результаты нашего классификатора:
red apple (score = 0.60262) red ball (score = 0.39738)
Это изображение, безусловно, более запутанное, поскольку оно содержит элементы как яблок, так и шариков, и может быть некорректно классифицировать его так или иначе.
При создании программного приложения, которое использует эти типы моделей, важно обрабатывать эти случаи в зависимости от требований функционального варианта использования. Возможно, мы программируем порог, который, если наша уверенность недостаточно высока для определенной категории, говорит пользователю, что мы не можем классифицировать его с достаточной точностью. Или, возможно, мы возвращаем три самых высоких возможных метки. Одна вещь, которую мы определенно захотим сделать, - это пометить эти типы входных данных для рассмотрения нашими разработчиками моделей, поскольку это уникальный случай, и мы, возможно, захотим включить их в обучающие данные для следующей версии модели.
Примечание о непредвиденных последствиях
Возможно, вы заметили, что мои данные о тренировках содержат только экземпляры r ed яблок и r ed мячей. Этот выбор был преднамеренным, и я соответственно включил цвет на этикетке, чтобы люди знали об алгоритмической предвзятости этой модели.
Если, однако, я только что выбрал метку pple и ball, но все же в моих обучающих данных были только их красные экземпляры, то мы непреднамеренно кодируем цвет объект, связанный с этой меткой изображениями, которые мы выбрали для обучающих данных. Например, что происходит, когда я отправляю экземпляры этих объектов с разными цветами?
В случае с этим желтым яблоком наш классификатор возвращает с вероятностью 50/50 либо мяч, либо яблоко. Для специалиста по машинному обучению такого результата можно ожидать, если взглянуть на данные обучающей выборки. Не существует экземпляров желтых яблок, и в большинстве случаев это настоящие изображения яблок, а не яблоки в однотонном стиле.
Здесь мы видим, что классификатор все еще не уверен, должен ли это быть красный шар или яблоко, это немного больше похоже на красный шар, но не с большой уверенностью. Если бы мы пытались классифицировать мяч любого типа и цвета, то мы, безусловно, хотели бы добавить этот и другие цветовые вариации в нашу обучающую выборку.
Интересно, что «Красная планета» с вероятностью 95% будет красным шаром, что в абстрактном смысле верно. Но это еще раз подтверждает, что правильное использование модели для тех случаев, когда она была обучена, по-прежнему важно.
Трансферное обучение - хорошее начало
Как мы видели здесь, использование моделей глубокого обучения и повторное обучение последнего слоя классификации - хороший способ начать свои первые эксперименты с машинным обучением. Если у вас есть проблема, связанная с распознаванием изображений, распознаванием речи или языковым переводом, и вы хотите применить меньший набор данных, чтобы увидеть, как это работает на практике, то TensorFlow - эффективный способ быстрого создания прототипов моделей и вариантов использования.
Хотите узнать, как начать использовать машинное обучение в своем бизнесе? Наши роботы могут помочь ... и под роботами мы имеем в виду талантливых специалистов по науке о данных из компании Роботы и карандаши. 🤖 👋