Пару месяцев назад Южно-Китайский университет опубликовал статью и набор данных о Прогнозировании красоты лица. Вы можете найти это здесь". Набор данных включает 5500 человек, которые оценили свою привлекательность от 1 до 5.

Вот несколько примеров из статьи:

Также в наборе несколько известных людей. Средняя оценка этой фотографии Джулии Роберт - 3,78:

Эта фотография известной израильской модели Бар Рафаэли получила оценку 3,7:

Это может выглядеть как низкие оценки, но оценка 3,7 означает, что полоса более привлекательна, чем ~ 80% людей в наборе данных.

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

В этом посте я хочу воспроизвести их результат и проверить, насколько я привлекательна.

В исходной статье реализовано множество различных моделей, включая классические модели машинного обучения с функциями ручной работы и 3 модели глубокого обучения: AlexNet, ResNet18 и ResNext50.
Я хочу, чтобы моя работа была максимально простой (я не хочу для реализации и обучения всей resnet сети с нуля), я хочу точно настроить некоторую существующую модель, которая будет выполнять эту работу. В keras есть модуль под названием applications, который представляет собой набор различных предварительно обученных моделей. Один из них resnet50. К сожалению, в keras.applications нет ResNet18 или ResNext50, поэтому я не смогу воспроизвести ту же самую работу, но я должен быть достаточно близок с resnet50.

from keras.applications import ResNet50

ResNet - это глубокая сверточная сеть, разработанная Microsoft и выигравшая в 2015 году конкурс ImageNet, который представляет собой задачу классификации изображений.
Когда мы запускаем resnet50 model в keras, мы создаем модель с архитектурой ResNet50, а также загружаем обученные веса, как были обучены на наборе данных ImageNet.

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

resnet = ResNet50(include_top=False, pooling=’avg’)
model = Sequential()
model.add(resnet)
model.add(Dense(1))
model.layers[0].trainable = False
print model.summary()
# Output:
  Layer (type)                 Output Shape              Param #    ================================================================= resnet50 (Model)             (None, 2048)              23587712   _________________________________________________________________ dense_1 (Dense)              (None, 1)                 2049       ================================================================= Total params: 23,589,761 
Trainable params: 23,536,641 
Non-trainable params: 53,120

Вы можете видеть, что я сделал первый уровень (модель resnet) необучаемым, поэтому у меня есть только 2049 обучаемых параметров вместо 23 589 761.

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

model.compile(loss='mean_squared_error', optimizer=Adam())
model.fit(batch_size=32, x=train_X, y=train_Y, epochs=30)

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

Здесь train_X - фотографии, то есть numpy массивы формы (350, 350, 3), а train_Y - оценки изображений, которые были помечены.

Результаты

В статье модели обучались с использованием двух методов: 5-кратной перекрестной проверки и 60% -40% тестового разделения. Они измерили свои результаты с использованием корреляции Пирсона (ПК), средней абсолютной ошибки (MAE) и среднеквадратичной ошибки (RMSE). Вот результаты, которые они получили с помощью 5-кратной перекрестной проверки:

И вот результаты, которые они получили, используя разделение поездов 60% -40%:

Я проведу разделение обучающих тестов на 80% -20%, так что это похоже на выполнение одинарной части перекрестной проверки.

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

RMSE: 0.301799791952313 
MAE: 0.2333630505619627 
PC: 0.9012570266136678

Вполне нормально. Также всегда приятно посмотреть на диаграмму рассеяния и гистограммы оценок:

Исходное распределение баллов (нормализованное):

Распределение прогнозируемых баллов (нормализованное):

Результаты выглядят неплохо. А теперь давайте посмотрим, что эта глубокая нейронная сеть говорит обо мне. Сначала я использовал это фото:

У меня 2,85, что означает, что я привлекательнее, чем 52% людей в этом наборе данных. Должен сказать, что я немного разочарован, я надеялся, что буду лучше, чем это. Итак, я попытался улучшить свое положение.

Я сделал много фотографий и в итоге получил оценку 3,15, что означает, что я более привлекателен, чем 64% людей в наборе данных.

Это намного лучше, я должен быть честным и сказать, что надеялся на лучшее :)

И последнее замечание: я построил и настроил эту модель с помощью Google Colaboratory, короче говоря, это дает вам ноутбук на Python, который использует графический процессор бесплатно!

Надеюсь, вам понравился пост.