В 2013 году Kaggle организовала соревнование по распознаванию выражений лица, в котором участники должны были построить модель для распознавания 7 видов выражений лица человека. Хотя прошло уже несколько лет и одни результаты исследований появлялись один за другим, это по-прежнему очень интересная тема. В этой статье я (автор Сефик Серенгил — прим. переводчика) покажу, как использовать Keras для распознавания мимики людей.
набор данных
В нашем тренировочном наборе и тестовом наборе по-прежнему используется набор данных Fec2013, использовавшийся в соревновании Kaggle в том году, нажмитездесьможет быть получен. Сжатый размер набора данных составляет 92 МБ, а несжатая версия — 295 МБ. Набор данных содержит 28 000 тренировочных фотографий и 30 000 тестовых фотографий. Каждая фотография хранится в формате 48 X 48 пикселей. Чистый набор данных содержит пиксели изображения (48 X 48 = 2304 значения), выражение лица на каждом изображении и тип использования (для обучения или тестирования).
После загрузки набора данных в локальную папку данных используйте следующий код для чтения содержимого набора данных:
with open("/data/fer2013.csv") as f:
content = f.readlines()
lines = np.array(content)
num_of_instances = lines.size
print("number of instances: ",num_of_instances)
процесс изучения
В последние годы методы глубокого обучения доминировали в исследованиях компьютерного зрения, и даже академические конференции по компьютерному зрению превратились в семинары по глубокому обучению. Здесь мы будем использовать сверточные нейронные сети в глубоком обучении для выполнения этой задачи. Затем мы воспользуемся бэкендом TensorFlow для построения сверточной нейронной сети с помощью Keras.
Теперь, когда мы загрузили набор данных локально, теперь мы можем хранить обучающие и тестовые наборы как выделенные переменные.
x_train, y_train, x_test, y_test = [], [], [], []
for i in range(1,num_of_instances):
emotion, img, usage = lines[i].split(",")
val = img.split(" ")
pixels = np.array(val, 'float32')
emotion = keras.utils.to_categorical(emotion, num_classes)
if 'Training' in usage:
y_train.append(emotion)
x_train.append(pixels)
elif 'PublicTest' in usage:
y_test.append(emotion)
x_test.append(pixels)
Затем постройте архитектуру сверточной нейронной сети:
model = Sequential()
#第一个卷积层
model.add(Conv2D(64, (5, 5), activation='relu', input_shape=(48,48,1)))
model.add(MaxPooling2D(pool_size=(5,5), strides=(2, 2)))
#第二个卷积层
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(AveragePooling2D(pool_size=(3,3), strides=(2, 2)))
#第三个卷积层
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(AveragePooling2D(pool_size=(3,3), strides=(2, 2)))
model.add(Flatten())
#全连接神经网络
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))
После построения модели приступаем к обучению нейронной сети. Чтобы сократить время обучения, я предпочитаю случайным образом выбирать обучающий набор для обучения модели, что является причиной использования fit_generator в Keras. Опять же, функция потерь будет кросс-энтропийной, так как наша задача — проблема мультиклассовой классификации.
gen = ImageDataGenerator()
train_generator = gen.flow(x_train, y_train, batch_size=batch_size)
model.compile(loss='categorical_crossentropy'
, optimizer=keras.optimizers.Adam()
, metrics=['accuracy']
)
model.fit_generator(train_generator, steps_per_epoch=batch_size, epochs=epochs)
После выполнения функции подгонки мы оцениваем модель:
train_score = model.evaluate(x_train, y_train, verbose=0)
print('Train loss:', train_score[0])
print('Train accuracy:', 100*train_score[1])
test_score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', test_score[0])
print('Test accuracy:', 100*test_score[1])
Чтобы не переобучать, я в итоге получаю следующие результаты, но когда я увеличиваю количество эпох, происходит переобучение:
Test loss: 2.27945706329
Test accuracy: 57.4254667071
Train loss: 0.223031098232
Train accuracy: 92.0512731201
Окончательная построенная модель распознавания выражения лица имеет точность 57%.
Протестируйте модель с пользовательскими фотографиями
Теперь мы пытаемся заставить модель распознавать выражения лица на фотографиях, которые мы нашли сами, потому что частота ошибок в тестовом наборе сама по себе мало о чем говорит.
img = image.load_img("/data/pablo.png", grayscale=True, target_size=(48, 48))
x = image.img_to_array(img)
x = np.expand_dims(x, axis = 0)
x /= 255
custom = model.predict(x)
emotion_analysis(custom[0])
x = np.array(x, 'float32')
x = x.reshape([48, 48]);
plt.gray()
plt.imshow(x)
plt.show()
Храните выражения лица в виде числовых значений и маркируйте их от 0 до 6. Keras сгенерирует выходной массив, включающий эти 7 различных оценок выражений. Мы можем визуализировать прогнозы для каждого выражения в виде гистограммы.
def emotion_analysis(emotions):
objects = ('angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral')
y_pos = np.arange(len(objects))
plt.bar(y_pos, emotions, align='center', alpha=0.5)
plt.xticks(y_pos, objects)
plt.ylabel('percentage')
plt.title('emotion')
plt.show()
Если вы видели сериал Netflix «Нарко», вы должны быть знакомы с этой фотографией. Фотография ниже была сделана, когда наркобарон Пабло Эскобар был арестован и заключен в тюрьму. Узнав эту фотографию с моделью, которую мы только что построили, видно, что Пабло был в то время в очень хорошем настроении.
Затем мы использовали второе фото, «старика» Марлона Брандо Корлеоне в «Крестном отце», когда он увидел тело своего сына. Результаты теста показали, что модель также могла распознавать огорченное и грустное выражение лица Корлеоне.
Я также хотел проверить выражение гнева, и когда дело доходит до гнева, «Росомаха» Хью Джекмана является типичным примером, это он. Я выбрал образ ярости Росомахи из Людей Икс. Результаты испытаний показали большой успех.
Наконец, бросьте вызов модели на сложное фото:улыбка Моны Лизы. Художники до сих пор не понимают настроения героев «Моны Лизы» Леонардо да Винчи. После идентификации с нашей моделью видно, что Мона Лиза в то время была в очень мирном и естественном настроении.
Эпилог
В этой статье мы строим сверточную нейронную сеть для распознавания выражений лица человека. Точность окончательной модели составляет 57%, что приемлемо, поскольку самый высокий показатель точности в конкурсе Kaggle составил 34%. Точность может быть дополнительно улучшена, если лица на обнаруженном изображении обрабатываются вместо обработки всего изображения. Поэтому перед запуском нейронной модели я немного обрезал лица на изображении. Я планирую обучить готовую модель в Inception для выполнения этой задачи в следующий раз и поделюсь ею с вами, когда придет время.
нажмитездесьПосмотрите код этого проекта.
Добро пожаловать, чтобы следовать за нами, учебные ресурсы, учебные пособия по искусственному интеллекту, интерпретация документов, интересные проекты, все, что вы хотите увидеть, здесь!