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

В Keras предварительно обученные сети находятся в модуле applications. Большая часть сетей предназначена для распознавания объектов на изображениях из набора данных ImageNet, но есть и сеть для обработки музыки. Модуль содержит следующие сети:

  1. VGG16 - сеть Visual Geometry Group из университета Оксфорда для распознавания объектов на изображениях, состоит из 16 слоев.
  2. VGG19 - еще одна сеть Visual Geometry Group для распознавания объектов, но содержит 19 слоев.
  3. Inception v3 - нейронная сеть компании Google для распознавания объектов на изображениях.
  4. ResNet50 - нейронная сеть компании Microsoft, использующая остаточное обучение (residual learning). Применяется для распознавании объектов на изображениях.
  5. Xception - модификация сети Inception от создателя Keras François Chollet.
  6. CRNN for music tagging - сверточная рекуррентная нейронная сеть для классификации музыки.

Как можно видеть, сети очень глубокие, содержат десятки слоев. Для их обучения требуются огромные вычислительные мощности, которые есть только у таких крупных компаний, как Google и Microsoft. Но благодаря тому, что компании выкладывают обученные сети в открытый доступ, вы можете использовать их в своих программах на Keras. Давайте посмотрим, как это сделать для распознавания объектов на изображениях.

Набор данных ImageNet

Начнем с набора данных ImageNet, который используется для обучения большинства нейронных сетей в Keras. Это открытый набор данных из 14 миллионов изображений. Для каждого изображения указано, какой объект на нем. Таким образом, ImageNet можно использовать для обучения с учителем.

ImageNet содержит двадцать одну тысячу классов объектов, однако нейронные сети обучают распознавать только 1000 из них (что очень много по сравнению с CIFAR-10 и другими аналогичными наборами изображений). В ImageNet классы образуют иерархию. Например, указывается, что на изображении не просто кот, а конкретный вид кота (сиамский, египетский и т.п.).

Архитектура сети VGG16

VGG16 - это сверточная нейронная сеть, которая содержит 16 слоев. Сеть состоит из двух частей:

  1. Первая часть сети выделяет характерные признаки в изображении. Состоит из чередующихся каскадов свертки и подвыборки. Сначала идут два каскада свертка-свертка-подвыборка, а затем три каскада свертка-свертка-свертка-подвыборка. Размер узла свертки во всех слоях 3х3. При подвыборке производится выбор максимального значения (Max Pooling) из квадрата размером 2х2.
  2. Вторая часть отвечает за классификацию объекта на изображении по выделенным на предыдущем этапе признакам. Эта часть содержит 3 полносвязных слоя. В первых двух слоях 4096 нейронов, а в последнем - 1000 нейронов (по количеству классов объектов).

На вход сеть VGG16, получает изображение размером 224х224 пиксела, 3 канала цвета (красный, зеленый и синий). На выходе сеть выдает вероятности (в формате one hot encoding), что на изображении тот или иной класс объекта.

Нейронная сеть VGG16 в Keras

Использовать сеть VGG16 в Keras, как и другие предварительно обученные сети, очень легко. Сначала нужно подключить необходимые нам модули:

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input, decode_predictions
import numpy as np

Затем создаем сеть VGG16 и загружаем веса, обученные на наборе данных ImageNet:

model = VGG16(weights='imagenet')

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

Загружаем картинку, преобразуем ее в массив numpy и выполняем предварительную обработку:

img = image.load_img('image_file_name.jpg', target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

Выполняем распознавание объекта на изображении:

preds = model.predict(x)

Результат распознавания - это массив из 1000 элементов. Выберем 3 элемента с самой высокой вероятностью и напечатаем их:

print('Результаты распознавания:', decode_predictions(preds, top=3)[0])

Тестирование работы сети VGG16

Давайте попробуем протестировать, как предварительно обученная сеть VGG16 справляется с распознаванием объектов на изображениях.

Первым делом, конечно же, попытаемся распознать кота:

Фотография кота

Программа выдает следующие результаты:

Результаты распознавания: [('n02124075', 'Egyptian_cat', 0.71789128), ('n02123045', 'tabby', 0.079336673), ('n02123159', 'tiger_cat', 0.048442803)]

Первый результат - Egyptian_cat, его вероятность примерно 72%. Число 02124075 - это метка класса Egyptian_cat в наборе данных ImageNet. На втором месте tabby (это тоже порода кошки) с вероятностью примерно 8%. Затем идет tiger_cat с вероятностью меньше 5%. В породах кошек я разбираюсь не очень хорошо, но сеть явно определила, что на картинке котик.

Теперь давайте протестируем работу сети на фотографиях самолета и корабля. Начнем с самолета:

Фотография самолета

Программа выдает следующее:

Результаты распознавания: [('n02690373', 'airliner', 0.76766956), ('n04266014', 'space_shuttle', 0.13178571), ('n04592741', 'wing', 0.079244711)]

Самая большая вероятность у airliner (воздушный лайнер), что правильно. Вторая позиция space_shuttle (космический корабль) явно не правильная. На третьем месте wing (крыло), что не совсем правильно. Крыло на фотографии есть, но оно не является основным объектом.

Теперь попробуем распознать корабль:

Фотография самолета

Сеть выдает несколько типов кораблей:

Результаты распознавания: [('n04147183', 'schooner', 0.55734098), ('n04612504', 'yawl', 0.25635034), ('n02981792', 'catamaran', 0.094705731)]

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

Перенос обучения

Сейчас одним из самых популярных подходов к практическому обучению глубоких нейронных сетей является перенос обучения (по-английски transfer learning). В этом случае берется предварительно обученная сеть, например, VGG16, Inception или ResNet, и дообучается на наших данных. При таком подходе данных для обучения нужно гораздо меньше, т.к. сеть уже обучена выделять нужные нам признаки, например, на наборе данных ImageNet. Времени для дообучения, как правило, тоже требуется меньше, по сравнению с обучением с нуля. При этом, возможно, придется менять архитектуру сети, чтобы она решала нужные нам задачи. Как это делать, я расскажу в одной из следующих статей.

Итоги

Мы рассмотрели, как применять предварительно обученную сеть VGG16 в Keras для распознавания объектов на изображениях. Попробуйте провести свои эксперименты с сетью и оценить качество распознавания. О результатах пишите в комментариях.

Также можете попробовать заменить сеть VGG16 на ResNet или Inception. Примеры смотрите на странице Keras Applications. Пишите в комментариях о том, что получилось.

Полезные ссылки

  1. Keras Applications.
  2. Набор данных Image Net.
  3. Сети VGG16 и VGG19.
  4. Сеть Inception компании Google:
  5. Сеть остаточного обучения компании Microsoft.
  6. Сеть Xception.
  7. Convolutional Recurrent Neural Networks for Music Classification.