【问题标题】:Why is tensorflow model always predicting same class?为什么张量流模型总是预测同一类?
【发布时间】:2020-06-04 14:12:05
【问题描述】:

我的 TensorFlow 模型总是以 100% 的信任度预测同一类。

首先简要描述一下我的设置:任务是使用 7 个类进行图像分类并从网络摄像头读取图像。对于模型的训练、验证和测试,我将 TensorFlow 与数据生成器结合使用。

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(32,(3,3), activation='elu',input_shape=(image_heigth,image_width,3)))
model.add(tf.keras.layers.Conv2D(64,(3,3), activation='elu'))
model.add(tf.keras.layers.MaxPooling2D((2,2)))
model.add(tf.keras.layers.Conv2D(128,(3,3), activation='elu'))
model.add(tf.keras.layers.MaxPooling2D((2,2)))
model.add(tf.keras.layers.Conv2D(256,(3,3), activation='elu'))
model.add(tf.keras.layers.Conv2D(256,(3,3), activation='elu'))
model.add(tf.keras.layers.MaxPooling2D((2,2)))
model.add(tf.keras.layers.Conv2D(512,(3,3), activation='elu'))
model.add(tf.keras.layers.MaxPooling2D((2,2)))
model.add(tf.keras.layers.Dropout(0.3))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(512, activation='elu'))
model.add(tf.keras.layers.Dense(7, activation='softmax'))

model.summary()

model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop(lr=1e-4), metrics=['acc'])

仅供参考,这是我的模型。使用以下代码完成训练、验证和测试:

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, rotation_range=40, shear_range=0.2,zoom_range=0.2, horizontal_flip=True)
validation_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(train_dir, target_size=(image_heigth,image_width),batch_size=batch_size, class_mode='categorical', shuffle=True)
validation_generator = validation_datagen.flow_from_directory(validation_dir, target_size=(image_heigth,image_width), batch_size=5, class_mode='categorical')

for data_batch, labels_batch in train_generator:
    print('Shape des Datenstapels:', data_batch.shape)
    print('Shape des Klassenbzeichnungsstabels:', labels_batch.shape)
    break

history = model.fit(train_generator,steps_per_epoch=steps_per_epoch, epochs=epochs, validation_data=validation_generator,validation_steps=10, callbacks=callback_list)

# Testing the Model
test_generator = test_datagen.flow_from_directory(test_dir, target_size=(image_heigth,image_width), batch_size=5, class_mode='categorical')
test_loss, test_acc = model.evaluate(test_generator, steps=5)
predictions = model.predict(test_generator)
image_batch, label_batch = next (test_generator) 

我的正确分类率高达 90%。我的损失函数降至 0.3 左右。 调试测试并观察预测得到预期值,如 [0.08;0.06;0.56;0.04;0.10;0.09;0.07]。

最后,我使用 TensorFlow 方法将我的模型保存为 h5。

在另一个 python 程序中,我正在加载这个 h5 并想预测网络摄像头图像。但现在输出始终为 [1.0;0.0;0.0;0.0;0.0;0.0;0.0]。这是我的代码:

 import numpy as np
import cv2
import tensorflow as tf

model = tf.keras.models.load_model('/home/poppe/Dokumente/Models/Proto2.h5')

classes = ['One', 'two', 'three', 'four', 'five', 'six', 'seven']

model.summary()

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Our operations on the frame come here
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    rezised = cv2.resize(frame, (150, 150))
    expandArrayImage = np.expand_dims(rezised, axis=0)


    prediction = model.predict(expandArrayImage)

    print (np.max(prediction))
    print(classes[np.argmax(prediction)])

    # Display the resulting frame
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything is done, release the capture
cap.release()
cv2.destroyAllWindows()

如您所见,我正在使用 OpenCV 从网络摄像头读取数据。

为了解决我的问题,我尝试了以下方法: 将我的模型降到最低 --> 没有效果

将我的问题简化为二元分类 --> 没有效果(总是以 100% 预测两个类别之一)

加载和预测单个图像 --> 没有效果

代码后直接加载和预测单张图片进行测试(不必保存和加载模型)-->没有效果,图片是我的测试图片之一...通过测试这个图片被分类了正确,将其作为单个图像加载并使用 predict 方法,我遇到了与 bevor 相同的错误。

因此,由于测试按预期运行,我认为我的数据或模型没有问题。将网络摄像头图像从 OpenCV 转换为 TensorFlow 模型有什么问题吗?

您还有其他想法可以解决我的问题吗?

非常感谢! :)

【问题讨论】:

  • 您的训练集是否与您的网络摄像头提供给网络的内容相似(就像获取完全相同的条件一样)?
  • 您似乎也没有对网络摄像头输入进行标准化,而您对训练集进行了标准化。
  • 是的...训练集是分类可能位置的照片。所以条件是一样的。在已知和未知条件下测试了我的网络,但总是得到 100% 的相同预测。该值始终相同,并且不会因为移动相机而在短时间内发生变化。

标签: python numpy opencv tensorflow machine-learning


【解决方案1】:

cv2.VideoCapture().read() 将返回一个值在 (0,255) 范围内的 numpy 数组,但您的模型希望它们在 (0, 1) 范围内

您可以传递预期范围内的图像,例如:

rezised = cv2.resize(frame, (150, 150)) / 255
expandArrayImage = np.expand_dims(rezised, axis=0)
# rest of the code

【讨论】:

    猜你喜欢
    • 2017-11-22
    • 1970-01-01
    • 2018-06-04
    • 1970-01-01
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多