面部表情是人類之間交流的重要方式。
在人工智能研究中,深度學習技術已成爲增強人機交互的強大工具。心理學中面部表情和情緒的分析和評估涉及評估預測個人或群體情緒的決定。
本研究旨在开發一種能夠使用卷積神經網絡(CNN)算法和特徵提取技術預測和分類面部情緒的系統。
該過程包括三個主要階段:數據預處理、面部特徵提取和面部情緒分類。通過採用卷積神經網絡(CNN)算法,系統准確預測面部表情,成功率爲62.66%。
該算法的性能使用FER2013數據庫進行評估,該數據庫是一個公开可用的數據集,包含35,887張48x48灰度面部圖像,每張圖像代表一種不同的情緒。
現在讓我們從編碼开始。
!pip install scikit-plot
此代碼使用 pip 安裝 scikit-plot 包,pip 是一個 Python 包,提供了一系列有用的工具來可視化機器學習模型的性能。
具體來說,scikit-plot提供了多種函數來生成模型評估中使用的常見圖,例如ROC曲线,精度召回率曲线,混淆矩陣等。
在Python環境中執行命令“!pip install scikit-plot”後,你應該能夠在代碼中導入和使用scikit-plot函數。
import pandas as pd
import numpy as np
import scikitplot
import random
import seaborn as sns
import keras
import os
from matplotlib import pyplot
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.utils import to_categorical
import warnings
from tensorflow.keras.models import Sequential
from keras.callbacks import EarlyStopping
from keras import regularizers
from keras.callbacks import ModelCheckpoint,EarlyStopping
from tensorflow.keras.optimizers import Adam,RMSprop,SGD,Adamax
from keras.preprocessing.image import ImageDataGenerator,load_img
from keras.utils.vis_utils import plot_model
from keras.layers import Conv2D, MaxPool2D, Flatten,Dense,Dropout,BatchNormalization,MaxPooling2D,Activation,Input
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
warnings.simplefilter("ignore")
from keras.models import Model
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from keras.regularizers import l1, l2
import plotly.express as px
from matplotlib import pyplot as plt
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
該代碼導入機器學習和深度學習任務中常用的各種 Python 庫和模塊。
這些庫包括pandas,numpy,scikit-plot,random,seaborn,keras,os,matplotlib,tensorflow和scikit-learn。
每個 import 語句導入一組執行機器學習或深度學習任務所需的特定工具或函數,例如數據操作、數據可視化、模型構建和性能評估。
總體而言,此代碼准備了執行各種機器學習和深度學習任務(如數據預處理、模型訓練和模型評估)所需的必要工具和模塊。
從這裏下載代碼:http://onepagecode.s3-website-us-east-1.amazonaws.com/
加載數據集data = pd.read_csv("/input/fer2013/fer2013.csv")
data.shape
此代碼使用 pandas 的read_csv()函數讀取名爲“fer2013.csv”的 CSV 文件,該文件位於“/input/fer2013/“ 目錄,並將生成的數據幀分配給名爲data的變量。
然後,在數據幀上調用shape屬性以檢索其維度,這將返回表單的元組。這行代碼將輸出數據幀data中的行數和列數(rows, columns)。
data.isnull().sum()
此代碼將返回數據幀data的每一列中所有缺失值的總和。
數據幀的isnull()方法返回一個布爾數據幀,該幀指示原始數據幀中的每個元素是否丟失。然後將sum()方法應用於此布爾數據幀,該幀返回每列中缺失值的總和。
這是檢查數據幀中是否存在任何缺失值的快速方法。如果存在缺失值,則可能需要在將數據用於建模之前插補或刪除這些值。
data.head()
此代碼將返回數據幀data的前 5 行。
數據幀的head()方法返回數據幀的前n行(默認情況下爲n=5 )。這是快速瀏覽數據幀中的數據的有用方法,尤其是在處理大型數據集時。
輸出將顯示數據幀data的前 5 行,其中可能包括列名稱和前幾行數據,具體取決於數據幀的結構。
數據頭的輸出
數據預處理CLASS_LABELS = ['Anger', 'Disgust', 'Fear', 'Happy', 'Neutral', 'Sadness', "Surprise"]
fig = px.bar(x = CLASS_LABELS,
y = [list(data['emotion']).count(i) for i in np.unique(data['emotion'])] ,
color = np.unique(data['emotion']) ,
color_continuous_scale="Emrld")
fig.update_xaxes(title="Emotions")
fig.update_yaxes(title = "Number of Images")
fig.update_layout(showlegend = True,
title = {
'text': 'Train Data Distribution ',
'y':0.95,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'})
fig.show()
此代碼使用 Plotly Express 庫創建條形圖,該條形圖顯示數據幀data中情緒的分布。
首先,在CLASS_LABELS中定義一個類標籤列表,它對應於數據集中的不同情緒。
然後,調用px.bar()函數,其中 x 軸表示類標籤,y 軸表示每個情緒的圖像數量。顏色參數設置爲不同的情感類,color_continuous_scale參數設置爲“Emrld”,這是 Plotly Express 中預定義的色階。
接下來,調用各種update_方法來修改繪圖的布局和外觀。例如,update_xaxes()和update_yaxes()用於分別設置 x 軸和 y 軸標題。 update_layout()用於設置打印標題及其位置。
最後,在圖形對象上調用show()方法以顯示繪圖。
輸出將顯示一個條形圖,該條形圖顯示數據幀data中每個情緒的圖像數,每個情緒根據指定的色階進行顏色編碼。
隨機打亂數據data = data.sample(frac=1)
DataFrame 的sample()方法用於隨機採樣數據幀中行的一小部分,並指定frac要返回的行部分(在本例中爲 frac=1,這意味着將返回所有行)。當frac=1時,sample()方法有效地對數據幀中的行進行洗牌。
這是機器學習和深度學習任務中的常見操作,隨機打亂數據以防止在數據具有任何固有順序或結構時可能引入的任何偏差非常重要。
One Hot編碼labels = to_categorical(data[['emotion']], num_classes=7)
輸出是一個形狀爲(n_samples, n_classes)的 numpy 數組,其中:
n_samples是數據幀中的樣本數n_classes是數據中唯一類的數量(在本例中爲 7)數組data的每一行表示數據幀中單個樣本的One Hot編碼標籤。train_pixels = data["pixels"].astype(str).str.split(" ").tolist()
train_pixels = np.uint8(train_pixels)
此代碼對數據DataFrame的像素列中的像素值進行預處理。
首先,astype()方法用於將pixels列轉換爲字符串數據類型,這允許在列的每一行上調用split()方法。
接下來,對pixels列的每一行調用split()方法,以將像素值拆分爲字符串列表。然後使用tolist()將生成的列表轉換爲 numpy 數組。
最後,對 numpy 數組調用np.uint8(),將像素值從字符串轉換爲無符號 8 位整數,這是通常用於表示圖像像素值的數據類型。
輸出是一個形狀爲(n_samples, n_pixels)的 numpy 數組,其中n_samples是數據幀中的樣本數,n_pixels是數據中每個圖像的像素數。數組data的每一行表示數據幀中單個圖像的像素值。
標准化pixels = train_pixels.reshape((35887*2304,1))
此代碼將train_pixels numpy數組從形狀的三維數組(n_samples,n_rows,n_columns)重新整形爲形狀的二維數組(n_samples*n_row,1)。
numpy數組的reshape()方法用於更改其形狀。在這種情況下,train_pixels陣列通過將其重塑爲具有一列的2D陣列而被展平。
得到的像素陣列的形狀爲(n_samples*n_rows,1),其中n_samples是DataFrame中的樣本數,n_rows是每個圖像的行數,1 表示DataFrame中每個圖像的展平像素值。陣列的每一行表示DataFrame中單個圖像的單個像素值。
scaler = StandardScaler()
pixels = scaler.fit_transform(pixels)
此代碼使用scikit learn的StandardScaler()函數將標准化應用於像素numpy數組。
StandardScaler()函數是一個預處理步驟,用於縮放數據的每個特徵(在本例中爲每個像素值),使其均值爲 0,方差爲 1。這是機器學習和深度學習任務中常用的技術,可確保每個特徵對模型的貢獻相同。
然後在像素numpy數組上調用StandardScaler()對象的fit_transform()方法,該方法計算數據的平均值和標准偏差,並相應地縮放數據。然後將得到的縮放數據分配回像素numpy數組。
輸出是一個與原始pixels數組形狀相同的 numpy 數組,但每個像素值都已標准化。
重塑數據 (48,48)pixels = train_pixels.reshape((35887, 48, 48,1))
此代碼將train_pixels numpy數組從2維形狀數組(n_samples*n_rows,1)重新整形爲4維形狀陣列(n_samples,n_rows、n_columns、n_channels)。
numpy數組的reshape()方法用於更改其形狀。在這種情況下,train_pixels陣列被重塑爲具有1個通道的4D陣列。
得到的像素陣列的形狀爲(n_samples,n_rows,n_columns,n_channels),其中n_samples是DataFrame中的樣本數量,n_row是每個圖像的行數,n_column是每個圖像中的列數,n_channel表示每個圖像中顏色通道的數量。
由於原始數據集是灰度級的,因此n_channels設置爲1。像素陣列的每個元素表示DataFrame中單個灰度圖像的像素值。
訓練測試驗證拆分
現在,我們有 35887 張圖像,每張圖像包含 48x48 像素。我們將數據拆分爲訓練、測試和驗證數據,以 10% 的比例提供、評估和驗證我們的數據。
X_train, X_test, y_train, y_test = train_test_split(pixels, labels, test_size=0.1, shuffle=False)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.1, shuffle=False)
該代碼使用scikit-learn的train_test_split()函數將經過預處理的圖像數據像素和一個熱編碼的標籤標籤拆分爲訓練集、驗證集和測試集。
函數train_test_split()根據test_size參數將數據隨機拆分爲訓練和測試子集,test_size指定應用於測試的數據部分。在這種情況下,test_size=0.1,這意味着10%的數據將用於測試。
shuffle參數設置爲False以保留DataFrame中樣本的原始順序。
生成的X_train、X_val和X_test數組分別包含訓練集、驗證集和測試集的像素值。y_train、y_val和y_test數組包含對應集合的one hot編碼標籤。
再次使用train_test_split()將訓練集進一步拆分爲訓練集和驗證集,test_size=0.1。這將數據分成80%用於訓練,10%用於驗證,10%用於測試。
print(X_train.shape)
print(X_test.shape)
print(X_val.shape)
在將數據拆分爲訓練集、驗證集和測試集之後,這些代碼行打印X_train、X_test和X_val數組的形狀。
numpy數組的shape屬性返回數組維度的元組。在這種情況下,X_train、X_test和X_val數組的形狀將取決於每個集合中的樣本數量和每個樣本的維度。
輸出將以格式(n_samples、n_rows、n_columns、n_channel)顯示陣列的形狀,其中n_samples是集合中的樣本數,n_rows是每個圖像的行數,n_columns是每個圖像中的列數,n_channel表示每個圖像中顏色通道的數量。
在這個繪圖代碼的幫助下,我們可以看到一些包含每個類的一個樣本的訓練數據。
plt.figure(figsize=(15,23))
label_dict = {0 : 'Angry', 1 : 'Disgust', 2 : 'Fear', 3 : 'Happiness', 4 : 'Sad', 5 : 'Surprise', 6 : 'Neutral'}
i = 1
for i in range (7):
img = np.squeeze(X_train[i])
plt.subplot(1,7,i+1)
plt.imshow(img)
index = np.argmax(y_train[i])
plt.title(label_dict[index])
plt.axis('off')
i += 1
plt.show()
此代碼使用 matplotlib 的plt.subplots()函數從訓練集中創建圖像的 7x1 子圖網格。
numpy數組的scruze()方法用於從數組的形狀中刪除任何一維條目,有效地將4D數組轉換爲3D數組。
對於每個子圖,imshow()函數用於顯示相應的圖像,title()函數用來顯示相應的標籤。
axis()函數用於關閉每個子圖的軸。
輸出是訓練集中的前 7 個圖像的可視化,以及它們對應的標籤。
使用圖像數據生成器進行數據增強
我們可以進行數據增強,以獲得更多數據來訓練和驗證我們的模型,以防止過度擬合。數據增強可以在訓練集和驗證集上完成,因爲它有助於模型變得更加通用和健壯。
datagen = ImageDataGenerator( width_shift_range = 0.1,
height_shift_range = 0.1,
horizontal_flip = True,
zoom_range = 0.2)
valgen = ImageDataGenerator( width_shift_range = 0.1,
height_shift_range = 0.1,
horizontal_flip = True,
zoom_range = 0.2)
此代碼創建兩個ImageDataGenerator對象,datagen和valgen,它們將用於訓練和驗證期間的數據擴充。
ImageDataGenerator類是一個Keras預處理實用程序,可以實時執行各種類型的圖像增強,如移位、翻轉、旋轉和縮放。
datagen對象包括許多增強技術:
width_shift_range和height_shift_range分別將圖像在水平和垂直方向上隨機移動圖像寬度和高度的最大10%。horizontal_flip隨機水平翻轉圖像。zoom_range將圖像隨機縮放高達20%的倍數。
valgen對象包含與datagen相同的擴充技術,但僅在訓練期間應用於驗證集。
通過在訓練過程中應用數據擴充,模型將暴露於更大、更多樣的訓練數據集,這有助於防止過度擬合,並提高模型泛化到新數據的能力。
datagen.fit(X_train)
valgen.fit(X_val)
這幾行代碼分別將ImageDataGenerator對象datagen和valgen與訓練數據和驗證數據相匹配。
ImageDataGenerator對象的fit()方法計算執行數據擴充所需的任何內部統計信息,例如像素值的平均值和方差。在這種情況下,在datagen和valgen上調用fit()方法,並將訓練集和驗證集作爲輸入來計算這些統計數據。
將ImageDataGenerator對象擬合到數據後,可以使用它們在訓練和驗證期間實時應用數據增強。
train_generator = datagen.flow(X_train, y_train, batch_size=64)
val_generator = datagen.flow(X_val, y_val, batch_size=64)
這些代碼行創建了兩個ImageDataGenerator迭代器,train_generator和val_generator,可用於在訓練和驗證期間生成一批增強數據。
ImageDataGenerator對象的flow()方法接收輸入數據和標籤的numpy數組,並動態生成一批增強數據。
在這種情況下,使用datagen上的flow()方法創建train_generator,輸入訓練數據X_train和y_train,批量大小爲64。val_generator在valgen上使用相同的方法創建,輸入驗證數據X_val和y_val,批量大小爲64。
在訓練期間,train_generator(迭代器)將用於爲每個訓練時期動態生成一批增強數據。類似地,val_generator迭代器將用於爲每個驗證epoch生成一批增強數據。
代碼下載
http://onepagecode.s3-website-us-east-1.amazonaws.com/
設計模型卷積神經網絡(CNN)模型
CNN模型有許多層,具有不同的單元,例如卷積層,最大池化層,批量歸一化和退出層,以規範模型。
def cnn_model():
model= tf.keras.models.Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), padding='same', activation='relu', input_shape=(48, 48,1)))
model.add(Conv2D(64,(3,3), padding='same', activation='relu' ))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128,(5,5), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(512,(3,3), padding='same', activation='relu', kernel_regularizer=regularizers.l2(0.01)))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(512,(3,3), padding='same', activation='relu', kernel_regularizer=regularizers.l2(0.01)))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(512,(3,3), padding='same', activation='relu', kernel_regularizer=regularizers.l2(0.01)))
model.add(BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256,activation = 'relu'))
model.add(BatchNormalization())
model.add(Dropout(0.25))
model.add(Dense(512,activation = 'relu'))
model.add(BatchNormalization())
model.add(Dropout(0.25))
model.add(Dense(7, activation='softmax'))
model.compile(
optimizer = Adam(lr=0.0001),
loss='categorical_crossentropy',
metrics=['accuracy'])
return model
該代碼使用Keras Sequential API定義了卷積神經網絡(CNN)模型。
CNN體系結構由幾個具有批量歸一化、最大池化和丟棄正則化的卷積層組成,然後是幾個具有批量規範化和丟棄的全連接(密集)層。最後一層使用softmax激活函數來輸出7個可能的情緒類別上的概率分布。
Conv2D層創建了一個卷積核,該卷積核與層輸入進行卷積,以產生輸出張量。
BatchNormalization層應用一個變換,將平均激活保持在接近0的水平,將激活標准偏差保持在接近1的水平。
MaxPooling2D層沿着空間維度對輸入進行下採樣。
Dropout層在訓練過程中隨機丟棄一些單元,以防止過度擬合。
Dense層展平輸入,然後將其輸入到完全連接的層中。
模型的compile()方法指定了要在訓練過程中使用的優化器、損失函數和評估度量。在這種情況下,優化器是Adam,學習率爲0.0001,損失函數是分類交叉熵,評估指標是准確性。
該函數返回已編譯的模型對象。
model = cnn_model()
這行代碼通過調用前面定義的CNN_model()函數來創建CNN模型的一個新實例。
模型對象表示可以在數據上訓練的神經網絡模型,以預測面部圖像的情緒標籤。
然後,我們使用Adam優化器以0.0001的學習率編譯我們的模型,並選擇度量作爲准確性,然後選擇損失作爲分類交叉熵
model.compile(
optimizer = Adam(lr=0.0001),
loss='categorical_crossentropy',
metrics=['accuracy'])
這行代碼通過指定要在訓練期間使用的優化器、損失函數和評估指標來編譯 CNN 模型。
Keras 模型的compile()方法用於在訓練前配置學習過程。在這種情況下,優化器是學習率爲0.0001的Adam,損失函數是分類交叉熵,評估指標是准確性。
優化器負責在訓練過程中更新模型參數,Adam 是一種流行的優化算法,它根據損失函數的梯度調整學習率。
損失函數用於計算預測標籤和實際標籤之間的差異,分類交叉熵是多類分類問題的標准損失函數。准確性指標用於在訓練和驗證期間評估模型的性能。
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_6 (Conv2D) (None, 48, 48, 32) 320
_________________________________________________________________
conv2d_7 (Conv2D) (None, 48, 48, 64) 18496
_________________________________________________________________
batch_normalization_7 (Batch (None, 48, 48, 64) 256
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 24, 24, 64) 0
_________________________________________________________________
dropout_7 (Dropout) (None, 24, 24, 64) 0
_________________________________________________________________
conv2d_8 (Conv2D) (None, 24, 24, 128) 204928
_________________________________________________________________
batch_normalization_8 (Batch (None, 24, 24, 128) 512
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 12, 12, 128) 0
_________________________________________________________________
dropout_8 (Dropout) (None, 12, 12, 128) 0
_________________________________________________________________
conv2d_9 (Conv2D) (None, 12, 12, 512) 590336
_________________________________________________________________
batch_normalization_9 (Batch (None, 12, 12, 512) 2048
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 6, 6, 512) 0
_________________________________________________________________
dropout_9 (Dropout) (None, 6, 6, 512) 0
_________________________________________________________________
conv2d_10 (Conv2D) (None, 6, 6, 512) 2359808
_________________________________________________________________
batch_normalization_10 (Batc (None, 6, 6, 512) 2048
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 3, 3, 512) 0
_________________________________________________________________
dropout_10 (Dropout) (None, 3, 3, 512) 0
_________________________________________________________________
conv2d_11 (Conv2D) (None, 3, 3, 512) 2359808
_________________________________________________________________
batch_normalization_11 (Batc (None, 3, 3, 512) 2048
_________________________________________________________________
max_pooling2d_9 (MaxPooling2 (None, 1, 1, 512) 0
_________________________________________________________________
dropout_11 (Dropout) (None, 1, 1, 512) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 512) 0
_________________________________________________________________
dense_3 (Dense) (None, 256) 131328
_________________________________________________________________
batch_normalization_12 (Batc (None, 256) 1024
_________________________________________________________________
dropout_12 (Dropout) (None, 256) 0
_________________________________________________________________
dense_4 (Dense) (None, 512) 131584
_________________________________________________________________
batch_normalization_13 (Batc (None, 512) 2048
_________________________________________________________________
dropout_13 (Dropout) (None, 512) 0
_________________________________________________________________
dense_5 (Dense) (None, 7) 3591
=================================================================
Total params: 5,810,183
Trainable params: 5,805,191
Non-trainable params: 4,992
_________________________________________________________________
這行代碼打印了 CNN 模型體系結構的摘要。
Keras 模型的summary()方法打印模型架構的摘要,包括每層中的參數、每層的輸出形狀以及模型中的參數總數。
摘要包括有關模型中每個層的信息,包括層類型、輸出形狀、參數數和激活函數(如果適用)。摘要還包括有關模型中可訓練參數總數的信息,這對於了解模型復雜性和過度擬合的可能性非常有用。
提前停止
添加檢查指針以實現提前停止以防止過度擬合。
checkpointer = [EarlyStopping(monitor = 'val_accuracy', verbose = 1,
restore_best_weights=True,mode="max",patience = 5),
ModelCheckpoint('best_model.h5',monitor="val_accuracy",verbose=1,
save_best_only=True,mode="max")]
此代碼定義將在 CNN 模型訓練期間使用的 Keras 回調列表。
回調是可以在訓練過程中的各個階段應用的函數,例如在每個epoch結束時或驗證精度達到特定閾值時。它們可用於執行操作,例如保存最佳模型權重、提前停止以防止過度擬合或在模型未改進時降低學習率。
在這種情況下,checkpointer列表包含兩個回調:
EarlyStopping:此回調監控驗證精度,如果精度在一定數量的 epoch(由patience參數指定)後沒有提高,則停止訓練過程。restore_best_weights參數設置爲 True 以在停止訓練後恢復最佳模型的權重。ModelCheckpoint:此回調將訓練期間最佳模型的權重保存到名爲best_model.h5的文件中。save_best_only參數設置爲 True 以僅保存導致最高驗證精度的權重。history = model.fit(train_generator,
epochs=30,
batch_size=64,
verbose=1,
callbacks=[checkpointer],
validation_data=val_generator)
此代碼使用 fit() 方法在訓練數據上訓練 CNN 模型。
Keras 模型的fit()方法在指定數量的 epoch 的輸入數據上訓練模型。在這種情況下,模型一次使用 30 個圖像的批次訓練 64 個 epoch。
train_generator和val_generator對象分別用於生成用於訓練和驗證的一批增強圖像。回調參數設置爲前面定義的檢查指針列表,該列表指定在訓練期間要使用的早期停止和模型檢查點回調。
fit()該方法返回的history對象包含有關訓練過程的信息,包括每個時期的訓練和驗證損失和准確性。此信息可用於可視化模型隨時間推移的性能,並做出有關進一步訓練或模型調整的決策。
可視化結果plt.plot(history.history["loss"],'r', label="Training Loss")
plt.plot(history.history["val_loss"],'b', label="Validation Loss")
plt.legend()
此代碼繪制 CNN 模型在訓練過程中的訓練和驗證損失。
fit()方法返回的history對象包含有關訓練過程的信息,包括每個時期的訓練和驗證損失和准確性。此信息可用於可視化模型隨時間推移的性能。
plt.plot()函數用於繪制紅色的訓練損失和藍色的驗證損失,標籤參數指定每行的圖例標籤。調用legend()函數是爲了在繪圖上顯示圖例。
這段代碼允許我們查看模型的學習情況,以及它是否過度擬合到訓練數據。如果驗證損失开始增加,而訓練損失繼續減少,則表明過度擬合,這意味着模型正在記憶訓練數據,而不是很好地泛化到新數據。
plt.plot(history.history["accuracy"],'r',label="Training Accuracy")
plt.plot(history.history["val_accuracy"],'b',label="Validation Accuracy")
plt.legend()
此代碼繪制 CNN 模型在訓練過程中的訓練和驗證准確性。
fit()方法返回的history對象包含有關訓練過程的信息,包括每個時期的訓練和驗證損失和准確性。此信息可用於可視化模型隨時間推移的性能。
plt.plot()函數用於繪制紅色的訓練精度和藍色的驗證精度,標籤參數指定每行的圖例標籤。調用legend()函數是爲了在繪圖上顯示圖例。
這段代碼允許我們查看模型的學習情況,以及它是否過度擬合到訓練數據。如果驗證精度开始下降,而訓練精度繼續增加,則表明過度擬合,這意味着模型正在記憶訓練數據,而不是很好地推廣到新數據。
loss = model.evaluate(X_test,y_test)
print("Test Acc: " + str(loss[1]))
此代碼評估測試集上經過訓練的 CNN 模型的性能。
Keras 模型的evaluate()方法計算給定測試集上的損失和指標(在模型編譯期間指定)。
X_test和y_test數組分別包含測試圖像及其相應的標籤。model.evaluate()方法用於計算模型在測試集上的損失和准確性。evaluate()方法將損失值和精度值作爲數組返回。
測試精度是使用model.eevaluate()返回的loss對象打印的。測試精度讓我們了解了模型在新的、看不見的數據上的表現。
preds = model.predict(X_test)
y_pred = np.argmax(preds , axis = 1 )
此代碼使用經過訓練的 CNN 模型生成測試集的預測。
Keras 模型的predict()方法爲給定的輸入數據集X_test生成預測。在這種情況下,數組包含我們要對其進行預測的測試圖像。
preds數組包含每個測試圖像的每個類的預測概率,數組的每一行對應於一個測試圖像,每列對應於一個類。
np.argmax()函數用於提取每個測試圖像具有最高預測概率的類的索引。這爲我們提供了測試集的預測類標籤。
可以將預測的類標籤與真實的類標籤y_test進行比較,以評估模型在測試集上的性能。
label_dict = {0 : 'Angry', 1 : 'Disgust', 2 : 'Fear', 3 : 'Happiness', 4 : 'Sad', 5 : 'Surprise', 6 : 'Neutral'}
figure = plt.figure(figsize=(20, 8))
for i, index in enumerate(np.random.choice(X_test.shape[0], size=24, replace=False)):
ax = figure.add_subplot(4, 6, i + 1, xticks=[], yticks=[])
ax.imshow(np.squeeze(X_test[index]))
predict_index = label_dict[(y_pred[index])]
true_index = label_dict[np.argmax(y_test,axis=1)[index]]
ax.set_title("{} ({})".format((predict_index),
(true_index)),
color=("green" if predict_index == true_index else "red"))
此代碼生成測試圖像的隨機子集及其真實和預測標籤的可視化。
label_dict字典將整數類標籤映射到它們對應的字符串標籤。
然後,該代碼生成一個包含24個子圖(4行6列)的圖形,每個子圖顯示一個隨機測試圖像及其預測和真實標籤。函數的作用是從X_test數組中隨機選擇24個索引。
對於每個子圖,使用imshow()顯示測試圖像,並使用set_title()在子圖的標題中顯示預測標籤和真實標籤。如果預測標籤與真實標籤匹配,則以綠色突出顯示,否則以紅色突出顯示。
CLASS_LABELS = ['Anger', 'Disgust', 'Fear', 'Happy', 'Neutral', 'Sadness', "Surprise"]
cm_data = confusion_matrix(np.argmax(y_test, axis = 1 ), y_pred)
cm = pd.DataFrame(cm_data, columns=CLASS_LABELS, index = CLASS_LABELS)
cm.index.name = 'Actual'
cm.columns.name = 'Predicted'
plt.figure(figsize = (15,10))
plt.title('Confusion Matrix', fontsize = 20)
sns.set(font_scale=1.2)
ax = sns.heatmap(cm, cbar=False, cmap="Blues", annot=True, annot_kws={"size": 16}, fmt='g')
此代碼生成測試集上模型預測的混淆矩陣的熱圖。
CLASS_LABELS列表包含七個情感類的名稱。
scikit learn的metrics模塊中的confusion_matrix()函數用於計算模型在測試集上的預測的混淆矩陣。函數np.argmax()用於將one hot編碼的真實標籤和預測標籤轉換爲整數標籤。
生成的混淆矩陣存儲在pandas DataFrame cm中,類名作爲行和列標籤。然後使用seaborn的heatmap()函數將DataFrame顯示爲熱圖。熱圖使用混淆矩陣的值進行注釋,並使用sns.set(font_scale=1.2)增加字體大小。
from sklearn.metrics import classification_report
print(classification_report(np.argmax(y_test, axis = 1 ),y_pred,digits=3))
classification_report()的輸出含義如下:
Precision:預測的陽性病例與實際陽性病例的比例。在數學上,它是TP /(TP + FP),其中TP是真陽性的數量,FP是誤報的數量。高精度分數表示模型在預測正類時是准確的。Recall:模型正確預測爲陽性的實際陽性事例的比例。在數學上,它是TP / (TP + FN),其中FN是假陰性的數量。較高的召回率分數表示模型能夠正確識別陽性病例。F1 分數:精度和召回率的調和平均值。它同時考慮了精度和召回率,並提供平衡兩者的單一分數。在數學上,它是 2 * (precision * recall) / (precision + recall).Support:類在測試數據中實際出現的次數。
下面是分類報告中不同行的說明:
Precision:第一行顯示每個類的精度分數。Recall:第二行顯示每個班級的召回分數。F1 分數:第三行顯示每個類的 F1 分數。Support:最後一行顯示測試數據中每個類的出現次數。
請注意,宏觀平均值和加權平均值也位於報告底部。
微調模型model = cnn_model()
model.compile(optimizer=tf.keras.optimizers.SGD(0.001),
loss='categorical_crossentropy',
metrics = ['accuracy'])
該模型的優化器已從Adam更改爲SGD,學習率爲0.001。損失函數保持不變,即類別交叉熵。精度度量也是相同的。
history = model.fit(train_generator,
epochs=30,
batch_size=64,
verbose=1,
callbacks=[checkpointer],
validation_data=val_generator)
使用train_generator和val_generator分別作爲訓練和驗證數據,再次對模型進行 30 個時期的訓練,批量大小爲64。
檢查指針回調還用於保存基於驗證准確性的最佳模型。
loss = model.evaluate(X_test,y_test)
print("Test Acc: " + str(loss[1]))
打印使用SGD優化器微調模型後的測試精度,學習率爲0.001。
plt.plot(history.history["loss"],'r', label="Training Loss")
plt.plot(history.history["val_loss"],'b', label="Validation Loss")
plt.legend()
該圖顯示了模型訓練期間各個時期的訓練損失(紅色)和驗證損失(藍色)。x 軸表示周期數,y 軸表示損失。它有助於確定模型是過度擬合還是擬合不足。
如果訓練損失在減少,但驗證損失在增加或不減少,則意味着模型過度擬合。如果訓練和驗證損失都很高,則意味着模型擬合不足。
從圖中看,訓練和驗證損失似乎在減少,這意味着模型正在從數據中學習。
更改epoch編號model.compile(
optimizer = Adam(lr=0.0001),
loss='categorical_crossentropy',
metrics=['accuracy'])
checkpointer = [EarlyStopping(monitor = 'val_accuracy', verbose = 1,
restore_best_weights=True,mode="max",patience = 10),
ModelCheckpoint('best_model.h5',monitor="val_accuracy",verbose=1,
save_best_only=True,mode="max")]
history = model.fit(train_generator,
epochs=50,
batch_size=64,
verbose=1,
callbacks=[checkpointer],
validation_data=val_generator)
更新後的代碼再次訓練模型 50 個epoch,並提前停止回調,耐心等待 10 個epoch。最佳模型將保存爲“best_model.h5”,具有最大的驗證精度。
該模型將使用 Adam 優化器進行編譯,學習率爲 0.0001,分類交叉熵損失和准確性作爲指標。訓練生成器和驗證生成器是之前使用數據增強技術定義的。
loss = model.evaluate(X_test,y_test)
print("Test Acc: " + str(loss[1]))
CLASS_LABELS = ['Anger', 'Disgust', 'Fear', 'Happy', 'Neutral', 'Sadness', "Surprise"]
cm_data = confusion_matrix(np.argmax(y_test, axis = 1 ), y_pred)
cm = pd.DataFrame(cm_data, columns=CLASS_LABELS, index = CLASS_LABELS)
cm.index.name = 'Actual'
cm.columns.name = 'Predicted'
plt.figure(figsize = (20,10))
plt.title('Confusion Matrix', fontsize = 20)
sns.set(font_scale=1.2)
ax = sns.heatmap(cm, cbar=False, cmap="Blues", annot=True, annot_kws={"size": 16}, fmt='g')
原文標題 : 使用 CNN 進行面部情緒識別
標題:使用 CNN 進行面部情緒識別
地址:https://www.utechfun.com/post/214190.html