我在尝试训练一个TensorFlow模型来为我的学校项目分类睁眼和闭眼。
我使用OpenCV库从网络摄像头录制的视频中提取我的眼睛。我大约有4000张睁眼的图片和4000张闭眼的图片。其中一半是左眼,一半是右眼。
数据集看起来像这样:
睁眼:
闭眼:
我有8000张这样的图片,具有不同的光照条件和角度。
我的代码:
我使用以下代码将数据集导入为数组。
import numpy as npimport cv2import osfrom random import shufflefrom tqdm import tqdmimport matplotlib.pyplot as pltTraining_Data = []Eyes_Open_Data = []Eyes_Closed_Data=[]Labels_Data=[]only_eyes_open = 'C:/Users/Ibrahim/Desktop/Staj 2020/only_eyes_open'only_eyes_closed = 'C:/Users/Ibrahim/Desktop/Staj 2020/only_eyes_closed'for item in os.listdir('only_eyes_open'): img_array= cv2.imread(os.path.join(only_eyes_open, item), cv2.IMREAD_GRAYSCALE) new_array = cv2.resize(img_array, (50,50)) Eyes_Open_Data.append(new_array) Labels_Data.append(1)for item in os.listdir('only_eyes_closed'): img_array= cv2.imread(os.path.join(only_eyes_closed, item), cv2.IMREAD_GRAYSCALE) new_array = cv2.resize(img_array, (50,50)) Eyes_Closed_Data.append(new_array) Labels_Data.append(0)
我使用以下代码合并左眼和右眼数据以及标签。然后我对其进行打乱,并将其分成训练数据和标签。
Training_Data = Eyes_Open_Data + Eyes_Closed_DataTraining_Data = list(zip(Training_Data, Labels_Data))shuffle(Training_Data)Labels_Data = [b for a,b in Training_Data]Training_Data = [a for a,b in Training_Data]X = []y = []X = Training_Datay = Labels_DataX = np.array(X).reshape(-1, 50, 50, 1)
我使用以下代码创建了我的模型:
import tensorflow as tffrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2DX = np.array(X/255.0)y= np.array(y)model = Sequential()model.add(Conv2D(32, (3, 3), input_shape=X.shape[1:]))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Conv2D(32, (3, 3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Conv2D(64, (3, 3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2)))model.add(Flatten()) # this converts our 3D feature maps to 1D feature vectorsmodel.add(Dense(128))model.add(Dense(1))model.add(Activation('sigmoid'))model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])model.fit(X, y, batch_size=32, epochs=1, verbose=1, validation_split=0.1, shuffle=True)
上述代码的输出:
226/226 [==============================] - 11s 47ms/step - loss: 0.0908 - accuracy: 0.9582 - val_loss: 0.0028 - val_accuracy: 1.0000<tensorflow.python.keras.callbacks.History at 0x1ac4c2e55b0>
到目前为止,一切看起来都正常,直到我用不同的数据实际测试模型。我又捕捉了四张我的眼睛的图片,就像我的数据集中的图片一样。前两张是睁眼的,后两张是闭眼的。
所以我期望预测结果是:[1,1,0,0]
我使用以下代码导入测试数据:
test_data = 'C:/Users/Ibrahim/Desktop/Staj 2020/testing'test_array = []for item in os.listdir(test_data): img_array = cv2.imread(os.path.join(test_data,item), cv2.IMREAD_GRAYSCALE) new_array = cv2.resize(img_array,(50,50)) plt.imshow(new_array) test_array.append(new_array)test_array = np.array(test_array).reshape(-1,50,50,1)
我运行以下代码进行预测:
model.predict(test_array)
这是输出结果:
array([[1.], [1.], [1.], [1.]], dtype=float32)
如果我没记错的话,这意味着它预测所有图片都是睁眼的。所以我决定用我在训练中使用的图片尝试预测。
我将测试数据的位置更改为我的数据集位置:
test_data = 'C:/Users/Ibrahim/Desktop/Staj 2020/only_eyes_closed'
输出是正确的:
array([[0.], [0.], [0.], ..., [0.], [0.], [0.]], dtype=float32)
在这一点之后,无论我使用什么数据进行测试,它都只预测1。唯一的例外是我用于训练的数据。
回答:
好的,可能需要考虑的场景包括:
- 训练多个
epochs
。 - 调整超参数,使用学习率衰减函数。
- 尝试
tf.keras.layers.BatchNormalization
和tf.keras.layers.Dropout
。 - 查看
tf.keras.preprocessing.image.ImageDataGenerator
以了解图像增强技术。 - 如果问题仍然存在,尝试给闭眼数据更多的权重。
- 微调预定义的架构
(VGG19/EfficientNet)
,即保持其起始层冻结(因为它们捕捉基本特征)。 - 由于这是一个二元分类,你应该查看其他指标,如
ROC/精确度/召回率
等。 - 至少仔细查看你的现实世界数据集和训练数据集,看看它们有多少不同之处。