В этом блоге проекта я расскажу о проекте классификации пород собак, который является краеугольным камнем моего проекта Udacity Data Scientist Nano Degree. Этот проект вращается вокруг распознавания лиц, Conv Net и обучения передаче.

Обзор

Цель проекта — создать веб-приложение, способное определять породу собаки, если на вход подается фотография или изображение. Если фотография или изображение содержит человеческое лицо, то приложение вернет ту породу собаки, которая больше всего похожа лицом на этого человека.

Набор данных для этого проекта предоставлен Udacity. мы используем python 3.5 с TensorFlow в качестве серверной части Keras. Кроме того, мы будем использовать трансферное обучение и ясно увидим, как трансферное обучение может быть эффективным методом обучения модели машинного обучения с меньшим количеством данных и небольшими вычислительными ресурсами.

Проект следует следующим шагам в блокноте Jupyter, предоставленном Udacity:

  • Шаг 0: Импорт наборов данных
  • Шаг 1: Обнаружение людей
  • Шаг 2: Обнаружение собак
  • Шаг 3: Создайте CNN для классификации пород собак (с нуля)
  • Шаг 4: Используйте CNN для классификации пород собак (с использованием трансферного обучения)
  • Шаг 5: Создайте CNN для классификации пород собак (с использованием трансферного обучения)
  • Шаг 6: Напишите свой алгоритм
  • Шаг 7: Проверьте свой алгоритм

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

Шаг 0. Импорт наборов данных

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

В переменной dog_names хранится список имен классов, которые мы будем использовать в нашей окончательной модели прогнозирования. В зависимости от пути, по которому у вас есть изображения, вам может потребоваться изменить 20 в элементе [20:-1] на большее или меньшее число.

Если все сработало, получим следующий результат:

There are 133 total dog categories.
There are 8351 total dog images.
There are 6680 training dog images.
There are 835 validation dog images.
There are 836 test dog images.

Шаг 1. Обнаружение людей

Я использую реализацию OpenCV каскадных классификаторов Хаара на основе признаков для обнаружения человеческих лиц на изображениях. OpenCV предоставляет множество предварительно обученных детекторов лиц.

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

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

100.0% of faces detected in the first 100 images in human_files by OpenCV
11.0% of faces detected in the first 100 images in dog_files by OpenCV

Шаг 2. Обнаружение собак

В этом разделе мы используем предварительно обученную сеть Resnet50. Наша первая строка кода загружает модель ResNet-50 вместе с весами, которые были обучены в ImageNet.

Чтобы использовать эту модель с нашими изображениями, нам нужно обработать наши изображения до правильного размера тензора для модели. Функция path_to_tensor принимает в качестве входных данных путь к файлу со строковым значением к цветному изображению и возвращает четырехмерный тензор, подходящий для предоставления в Keras CNN. Сначала функция загружает изображение и изменяет его размер до квадратного изображения размером 224×224 пикселя. Затем изображение преобразуется в массив, размер которого затем изменяется до четырехмерного тензора. В данном случае, поскольку мы работаем с цветными изображениями, каждое изображение имеет три канала. Аналогично, поскольку мы обрабатываем одно изображение (или образец), возвращаемый тензор всегда будет иметь форму (1 224 224,3).

Функция paths_to_tensor принимает в качестве входных данных пустой массив строковых путей к изображениям и возвращает 4D-тензор с количеством изображений из обучающих, проверочных или тестовых наборов данных в зависимости от того, какой img_path вызывается.

Теперь мы готовы делать прогнозы. Функция, показанная ниже, после выполнения описанных выше шагов предварительной обработки использует функцию прогнозирования для получения массива для 1000 классов imagenet. Мы используем функцию argmax numpy, чтобы изолировать класс с наибольшей вероятностью, и используем словарь imagenet, чтобы определить имя класса.

from keras.applications.resnet50 import preprocess_input, decode_predictions
def ResNet50_predict_labels(img_path):
    # returns prediction vector for image located at img_path
    img = preprocess_input(path_to_tensor(img_path))
    return np.argmax(ResNet50_model.predict(img))

Категории ImageNet, соответствующие ключам словаря 151–268 включительно, включают все категории от «Чихуахуа» до «Мексиканских голых собак». Таким образом, чтобы проверить, предсказано ли предварительно обученной моделью ResNet-50, что изображение содержит собаку, нам нужно только проверить, возвращает ли функция ResNet50_predict_labels выше значение от 151 до 268 (включительно).

### returns "True" if a dog is detected in the image stored at img_path
def dog_detector(img_path):
    prediction = ResNet50_predict_labels(img_path)
    return ((prediction <= 268) & (prediction >= 151))

### on the images in human_files_short and dog_files_short.
dogs=0
for i in range(len(dog_files_short)):
    dogs += dog_detector(dog_files_short[i])
print(f"Dog faces in Dogs DS: {(dogs/len(dog_files_short)) * 100}%") # 100% of dogs are detected
dogs=0
for i in range(len(human_files_short)):
    dogs += dog_detector(human_files_short[i])
print(f"Dog faces in Human DS: {(dogs/len(human_files_short)) * 100}%")
Dog faces in Dogs DS: 100.0%
Dog faces in Human DS: 0.0%

Шаг 3. Создайте CNN для классификации пород собак (с нуля)

Здесь мы создадим модель CNN с нуля, хотя она не используется в окончательном веб-приложении, но очень полезна для понимания CNN.

Сеть, которую я выбрал, состояла из 4 сверточных слоев с 4max-pooling слоями для уменьшения размерности и увеличения глубины. Использовались фильтры № 16, 32, 64 128 соответственно.

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

Цель состояла в том, чтобы получить модель CNN с точностью >1%. Описанная выше сеть достигла 10,2871% без какой-либо аугментации данных.

Шаг 4. Используйте CNN для классификации пород собак (с помощью трансферного обучения)

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

Особенности узкого места — это концепция, состоящая в том, чтобы взять предварительно обученную модель и отрезать верхний классифицирующий слой, а затем ввести этот «отрезанный» VGG16 в качестве первого слоя для нашей окончательной модели.

Epoch 20/20
6600/6680 [============================>.] - ETA: 0s - loss: 7.7577 - acc: 0.5074Epoch 00020: val_loss improved from 8.52011 to 8.51820, saving model to saved_models/weights.best.VGG16.hdf5
6680/6680 [==============================] - 2s 257us/step - loss: 7.7392 - acc: 0.5084 - val_loss: 8.5182 - val_acc: 0.4000
Test accuracy VGG16: 38.9952%

Шаг 5. Создайте CNN для классификации пород собак (с помощью трансферного обучения)

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

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

Здесь мы определили архитектуру предварительно обученных моделей.

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

Наконец, мы готовы проверить точность всей обученной модели.

### TODO: Calculate classification accuracy on the test dataset.
test_model(VGG19_model,test_VGG19, test_targets, 'VGG19')

Точность теста VGG19: 83,9713%

test_model(Resnet50_model,test_Resnet50, test_targets, 'Resnet50')

Точность теста Resnet50: 81,8182%

test_model(InceptionV3_model,test_InceptionV3, test_targets, 'InceptionV3')

Точность теста InceptionV3: 79,9043%

test_model(Xception_model,test_Xception, test_targets, 'Xception')

Точность теста Xception: 84,3301%

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

### Write a function that takes a path to an image as input
### and returns the dog breed that is predicted by the model.
def Xception_prediction_breed(img_path):
    # extract bottleneck features
    bottleneck_feature = extract_Xception(path_to_tensor(img_path))
    # obtain predicted vector
    predicted_vector = Xception_model.predict(bottleneck_feature)
    # return dog breed that is predicted by the model
    return dog_names[np.argmax(predicted_vector)]

Шаг 6. Напишите свой алгоритм

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

  • если на изображении обнаружена собака, вернуть предсказанную породу.
  • если на изображении обнаружен человек, вернуть похожую породу собаки.
  • если ни один не обнаружен на изображении, предоставьте вывод, указывающий на ошибку.

Шаг 7. Проверьте свой алгоритм

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

Вот некоторые результаты:

Конец примечания:

В начале проекта моей целью было создать CNN с точностью тестирования около 90%, но наша окончательная модель имеет точность тестирования почти 85%.

Однако, если бы у меня было больше времени (я работаю над сроками проекта Udacity!) Я бы поэкспериментировал с классом ImageDataGenerator в Keras для увеличения изображений.

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

Подводя итог, возможные улучшения:

  1. Анализ изображений, используемых для обучения и проверки модели
  2. Увеличение данных
  3. Точная настройка гиперпараметров

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