Итак, ребята, в сегодняшнем блоге мы будем строить модель детектора эмоций в Keras с использованием сверточных нейронных сетей. Это один из моих любимых проектов, поэтому я очень рад начать с него, так что без лишних слов.
Полную статью с исходным кодом читайте здесь —https://machinelearningprojects.net/emotion-detector-using-keras/
Давай сделаем это…
Шаг 1 — Импорт необходимых библиотек для Детектора эмоций.
from keras.preprocessing.image import ImageDataGenerator from keras.layers import Dense,Dropout,Activation,Conv2D,MaxPooling2D,BatchNormalization,Flatten from keras.models import Sequential from keras.optimizers import rmsprop_v2 from keras.callbacks import EarlyStopping,ReduceLROnPlateau,ModelCheckpoint from keras.models import load_model import cv2 from PIL import Image import numpy as np import pandas as pd import os from keras.utils.np_utils import to_categorical import seaborn as sns
Шаг 2 — Чтение всех изображений и сохранение их в кадре данных.
int2emotions = {0:'Angry',1:'Fear',2:'Happy',3:'Neutral',4:'Sad',5:'Surprise'} emotions2int = {'Angry':0,'Fear':1,'Happy':2,'Neutral':3,'Sad':4,'Surprise':5} dic = {'images':[], 'labels':[], 'purpose':[]} for d in os.listdir('fer2013/'): print(d) for emotion in os.listdir(f'fer2013/{d}'): print(emotion) for i in os.listdir(f'fer2013/{d}/{emotion}'): img = cv2.imread(f'fer2013/{d}/{emotion}/{i}',0) img = img.reshape(48,48,1) dic['images'].append(img) dic['labels'].append(emotion) if d=='train': dic['purpose'].append('T') else: dic['purpose'].append('V') df = pd.DataFrame(dic) df.head()
- Здесь мы просто читаем наши данные и сохраняем их в кадре данных pandas.
- Изображения содержат изображения с формой 48X48X1.
- Этикетки изображают эмоции этого изображения.
- Цель имеет 2 значения T и V. T для обучения и V для проверки.
Шаг 3 — Извлечение данных обучения и данных проверки.
train_data = df[df['purpose']=='T'] val_data = df[df['purpose']=='V']
- Создание 2 разных фреймов данных.
- Первый для обучения и второй для проверки.
Проверьте голову обучающих данных.
train_data.head()
Проверьте заголовок данных проверки.
val_data.head()
Шаг 4 — Проверьте значения в столбце меток данных поезда.
train_data[‘labels’].value_counts()
- Как мы видим на изображении ниже, метки очень несбалансированы в обучающих данных, поэтому мы сбалансируем их на следующем шаге.
Шаг 5 — Взять равные экземпляры всех классов.
happy_df = train_data[train_data['labels']=='Happy'].sample(n=3171) neutral_df = train_data[train_data['labels']=='Neutral'].sample(n=3171) sad_df = train_data[train_data['labels']=='Sad'].sample(n=3171) fear_df = train_data[train_data['labels']=='Fear'].sample(n=3171) angry_df = train_data[train_data['labels']=='Angry'].sample(n=3171) surprise_df = train_data[train_data['labels']=='Surprise'].sample(n=3171) train_data = pd.concat([happy_df,neutral_df,sad_df,fear_df,angry_df,surprise_df]) train_data = train_data.sample(frac=1) train_data.reset_index(inplace=True) train_data.drop('index',inplace=True,axis=1) train_data.head()
- Здесь мы берем 3171 экземпляр каждой эмоциональной рекламы, связывающейся с ними, чтобы сделать один окончательный кадр данных.
Шаг 6 — Снова проверка значений в столбце меток данных поезда.
train_data[‘labels’].value_counts()
- Теперь снова проверяем подсчеты, и теперь мы видим, что все классы сбалансированы.
Построение столбца.
sns.countplot(train_data[‘labels’])
Шаг 7 — Объявление некоторых констант.
batch_size= 32 classes = 6 rows,columns=48,48
Шаг 8 — Получение данных для модели детектора эмоций в правильной форме.
train_labels = list(train_data['labels'].replace(emotions2int)) train_labels = to_categorical(train_labels) val_labels = list(val_data['labels'].replace(emotions2int)) val_labels = to_categorical(val_labels) train_data = list(train_data['images']) train_data = np.array(train_data) val_data = list(val_data['images']) val_data = np.array(val_data)
- Строка 1–2. Преобразование эмоций в целые числа, например Angry в 0, Fear в 1 и т. д., а затем преобразование этих чисел в горячее кодирование с помощью to_categorical. Это данные о поездах.
- Строка 4–5 — Делаем то же самое, что и выше, для данных проверки.
- Строка 7–8 — Преобразование столбца изображения в список, а затем в массив NumPy для целей обучения, потому что мы не будем использовать столбцы фрейма данных для целей обучения, поэтому мы преобразуем их в массивы.
- Строка 10–11 — Делаем то же самое, что и выше, для данных проверки.
Проверка формы обучающих данных.
train_data.shape
Проверка формы данных проверки.
val_data.shape
Шаг 9 — Создание модели детектора эмоций.
model = Sequential() # First Block model.add(Conv2D(64,(3,3),activation='elu',input_shape=(rows,columns,1),kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(Conv2D(64,(3,3),activation='elu',input_shape=(rows,columns,1),kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) # Second Block model.add(Conv2D(128,(3,3),activation='elu',kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(Conv2D(128,(3,3),activation='elu',kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) # Third Block model.add(Conv2D(256,(3,3),activation='elu',kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(Conv2D(256,(3,3),activation='elu',kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) # Fourth Block model.add(Conv2D(512,(3,3),activation='elu',kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(Conv2D(512,(3,3),activation='elu',kernel_initializer='he_normal',padding='same')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) model.add(Dropout(0.2)) # Fifth Block model.add(Flatten()) model.add(Dense(256,activation='elu',kernel_initializer='he_normal')) model.add(BatchNormalization()) model.add(Dropout(0.5)) # Sixth Block model.add(Dense(128,activation='elu',kernel_initializer='he_normal')) model.add(BatchNormalization()) model.add(Dropout(0.5)) # Seventh Block model.add(Dense(64,activation='elu',kernel_initializer='he_normal')) model.add(BatchNormalization()) model.add(Dropout(0.5)) # Eighth Block model.add(Dense(classes,activation='softmax',kernel_initializer='he_normal')) print(model.summary())
- Создание нашей модели сверточной нейронной сети.
- Создание 4 блоков слоев Conv2D — BatchNormalization — Conv2D — BatchNormalization — MaxPooling2D — Dropout.
- Создание 3 блоков слоев Dense — Batch — Dropout и, наконец, создание 1 Dense слоя с 6 нейронами/узлами.
Шаг 10 — Объявление обратных вызовов.
checkpoint = ModelCheckpoint('model\\6_class_emotion_detector_V2.h5', save_best_only=True, mode='min', monitor='val_loss', verbose=1) earlystopping = EarlyStopping(patience=10, verbose=1, min_delta=0, monitor='val_loss', restore_best_weights=True) callbacks = [checkpoint, earlystopping] model.compile(metrics=['accuracy'], optimizer='rmsprop', loss='categorical_crossentropy')
- Создание обратных вызовов EarlyStopping и Checkpoint.
Шаг 11 — Обучение модели.
train_samples = 28273 validation_samples = 3534 batch_size = 64 epochs=30 history = model.fit(train_data, train_labels, epochs=epochs, steps_per_epoch=train_samples//batch_size, validation_data=(val_data,val_labels), validation_steps=validation_samples//batch_size, callbacks=callbacks)
- Наконец обучение модели.
Шаг 12 — Живой прогноз.
import cv2 from keras.models import load_model import numpy as np int2emotions = {0:'Angry',1:'Fear',2:'Happy',3:'Neutral',4:'Sad',5:'Surprise'} model = load_model('model\\6_class_emotion_detector_V2.h5') cap = cv2.VideoCapture(0) classifier = cv2.CascadeClassifier('Haarcascades\\haarcascade_frontalface_default.xml') def detect_face(frame): faces=classifier.detectMultiScale(frame,1.3,4) if faces==(): return frame for x,y,w,h in faces: cv2.rectangle(frame,(x,y),(x+w,y+h),(172,42,251),2) face = frame[y:y+h,x:x+w] face = cv2.cvtColor(face,cv2.COLOR_BGR2GRAY) face = cv2.resize(face,(48,48)) face = face.reshape(1,48,48,1) cv2.putText(frame,text=int2emotions[np.argmax(model.predict(face))], org=(x,y-15),fontFace=cv2.FONT_HERSHEY_SIMPLEX,fontScale=1,color=(106,40,243),thickness=2) return frame while 1: ret,frame= cap.read() if ret==True: cv2.imshow('emotion_detector',detect_face(frame)) if cv2.waitKey(1)==27: break cap.release() cv2.destroyAllWindows()
Дайте мне знать, если есть какие-либо вопросы относительно Детектора эмоций, связавшись со мной по электронной почте или LinkedIn.
Чтобы узнать больше о машинном обучении, глубоком обучении, компьютерном зрении, НЛП и проектах Flask, посетите мой блог — Проекты машинного обучения
Для дальнейшего объяснения кода и исходного кода посетите здесь — https://machinelearningprojects.net/emotion-detector-using-keras/
Итак, это все для этого блога, ребята, спасибо за то, что прочитали его, и я надеюсь, что вы возьмете что-то с собой после прочтения этого и до следующего раза 👋…
Прочитайте мой предыдущий пост: КЛАССИФИКАЦИЯ ПОРОД ОБЕЗЬЯН С ИСПОЛЬЗОВАНИЕМ ПЕРЕДАЧИ ОБУЧЕНИЯ