【问题标题】:How to train a tensorflow model to accurately classify open eyes and closed eyes?如何训练一个张量流模型来准确分类睁眼和闭眼?
【发布时间】:2020-11-10 19:26:39
【问题描述】:

我正在尝试训练一个张量流模型来为我的学校项目分类睁眼和闭眼。

我使用 OpenCV 库从网络摄像头录制的视频中提取我的眼睛。我有大约 4000 张睁眼的图像和 4000 张闭眼的图像。一半是左眼,一半是右眼。

数据集如下所示:

睁开眼睛:

闭上眼睛:

我有 8000 张这样的图像,具有不同的光照条件和角度。

我的密码:

我使用此代码将数据集作为数组导入。

import numpy as np
import cv2
import os
from random import shuffle
from tqdm import tqdm
import matplotlib.pyplot as plt
Training_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_Data

Training_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_Data
y = Labels_Data

X = np.array(X).reshape(-1, 50, 50, 1)

我使用以下代码创建了我的模型:

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Activation, Flatten, Conv2D, MaxPooling2D


X = 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 vectors

model.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。唯一的例外是我用于训练的数据。

【问题讨论】:

    标签: python tensorflow machine-learning computer-vision


    【解决方案1】:

    好的,可能需要研究的场景:

    • 训练多个epochs
    • 使用衰减学习率函数调整超参数。
    • 试试tf.keras.layers.BatchNormalizationtf.keras.layers.Dropout
    • 查看tf.keras.preprocessing.image.ImageDataGenerator 了解图像增强技术。
    • 如果问题仍然存在,请尝试给予闭眼数据更多权重。
    • 微调预定义架构(VGG19/EfficientNet),即保持其起始层冻结(因为它们捕获基本特征)。
    • 由于这是一个二元分类,您应该查看其他指标,例如 ROC/Precision/Recall 等。
    • 至少对您的真实数据集和训练数据集进行一次适当的了解,看看它们有多大不同。

    【讨论】:

      【解决方案2】:

      我解决了这个问题。问题是当我闭上眼睛拍照时,OpenCV 会无法检测到我的眼睛并重写之前的图像。这在我的数据集中造成了巨大的不平衡。所以我从闭眼文件夹中删除了重复的图像,并从睁眼文件夹中删除了相同数量的随机图像。我也稍微改变了我的模型。

      这是我的新模型:

      lr_schedule = tf.keras.optimizers.schedules.ExponentialDecay(
          initial_learning_rate=1e-2,
          decay_steps=10000,
          decay_rate=0.9)
      optimizer = tf.keras.optimizers.SGD(learning_rate=lr_schedule)
      X = np.array(X/255.0)
      y= np.array(y)
      
      model = Sequential()
      
      model.add(Flatten()) 
      
      model.add(Dense(16))
      model.add(Activation('relu'))
      
      model.add(Dense(16))
      model.add(Activation('relu'))
      
      model.add(Dense(1))
      model.add(Activation('sigmoid'))
      
      model.compile(loss='binary_crossentropy',
                    optimizer=optimizer,
                    metrics=['accuracy'])
      
      model.fit(X, y, batch_size=1, epochs=4, verbose=1, validation_split=0.1, shuffle=True)
      

      当我试图预测一个有 6 只睁眼和 6 只闭眼的测试集时:

      array([[1.],
             [1.],
             [1.],
             [1.],
             [1.],
             [1.],
             [0.],
             [0.],
             [0.],
             [0.],
             [0.],
             [0.]], dtype=float32)
      

      输出是 100% 正确的。

      【讨论】:

        猜你喜欢
        • 2015-05-02
        • 2012-09-21
        • 2017-05-11
        • 1970-01-01
        • 2021-12-04
        • 2020-09-05
        • 2015-06-17
        • 2020-02-29
        • 1970-01-01
        相关资源
        最近更新 更多