tensorflow - 使用 TF Keras ImageDataGenerator 时 Model.Predict 返回相同的值

标签 tensorflow tensorflow2.0 tf.keras

我正在使用Cat and Dog Dataset使用 Tensorflow Keras 训练模型并且使用 ImageDataGenerator.flow_from_directory 读取文件.

训练和验证的准确性不错,但是当尝试对测试数据进行预测时,模型对所有图像预测相同的类别。

训练代码如下所示:

import os, shutil
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dropout, Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import RMSprop
from tensorflow.keras.losses import binary_crossentropy
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np
import matplotlib.pyplot as plt

# Path to Training Directory
train_dir = 'Dogs_Vs_Cats_Small/train'

# Path to Validation Directory
validation_dir = 'Dogs_Vs_Cats_Small/validation'

#### Create the Convolutional Base

Max_Pool_Size = (2,2)
model = Sequential([
    Conv2D(input_shape = (150, 150, 3), filters = 32, kernel_size = (3,3), activation = 'relu', 
           padding = 'valid', data_format = 'channels_last'),
    MaxPooling2D(pool_size = Max_Pool_Size),
    Conv2D(filters = 64, kernel_size = (3,3), activation = 'relu', padding = 'valid'),
    MaxPooling2D(pool_size = Max_Pool_Size),
    Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'valid'),
    MaxPooling2D(pool_size = Max_Pool_Size),
    Conv2D(filters = 128, kernel_size = (3,3), activation = 'relu', padding = 'valid'),
    MaxPooling2D(pool_size = Max_Pool_Size)
])


#### Define the Dense Layers on Top of Convolutional Base

model.add(Flatten())
model.add(Dense(units = 512, activation = 'relu'))
model.add(Dense(units = 1, activation = 'sigmoid'))
model.summary()

model.compile(optimizer = RMSprop(learning_rate = 0.001), loss = 'binary_crossentropy', metrics = 'acc')

Train_Gen = ImageDataGenerator(1./255)
Val_Gen = ImageDataGenerator(1./255)

Train_Generator = Train_Gen.flow_from_directory(train_dir, target_size = (150,150), batch_size = 20,
                                               class_mode = 'binary')

Val_Generator = Val_Gen.flow_from_directory(validation_dir, target_size = (150, 150), class_mode = 'binary',
                                           batch_size = 20)

batch_size = 20
target_size = (150,150)
No_Of_Training_Images = Train_Generator.classes.shape[0]
No_Of_Val_Images = Val_Generator.classes.shape[0]
steps_per_epoch = No_Of_Training_Images/batch_size
validation_steps = No_Of_Val_Images/batch_size

history = model.fit(x = Train_Generator, shuffle=True, epochs = 20, 
          steps_per_epoch = steps_per_epoch,
          validation_data = Val_Generator
          , validation_steps = validation_steps
         )

现在,我Predict关于Test Data如下图:

Test_Dir = 'Dogs_Vs_Cats_Very_Small/test'

Test_Generator = ImageDataGenerator(1./255).flow_from_directory(Test_Dir, 
           target_size = (150,150), batch_size = 1, 
           shuffle = False, class_mode = 'binary') # This outputs Found 17 images belonging to 2 classes.

No_Of_Samples = len(Test_Generator.filenames)

testPredictions = model.predict(Test_Generator, steps = No_Of_Samples)


predictedClassIndices=np.argmax(testPredictions,axis=1)
print(predictedClassIndices)

filenames = Test_Generator.filenames
for f in range(len(filenames)):
    print(filenames[f],":",predictedClassIndices[f])

上述输出Print声明,即Predicted Classes如下图所示:

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])


cats/cat.1546.jpg : 0
cats/cat.1547.jpg : 0
cats/cat.1548.jpg : 0
cats/cat.1549.jpg : 0
cats/cat.1550.jpg : 0
cats/cat.1566.jpg : 0
cats/cat.1593.jpg : 0
cats/cat.1594.jpg : 0
dogs/dog.1514.jpg : 0
dogs/dog.1520.jpg : 0
dogs/dog.1525.jpg : 0
dogs/dog.1551.jpg : 0
dogs/dog.1555.jpg : 0
dogs/dog.1574.jpg : 0
dogs/dog.1594.jpg : 0
dogs/dog.1597.jpg : 0
dogs/dog.1599.jpg : 0

如上所示,所有图像都预测为 Class = 0Cats .

我已经研究过这个 Stack Overflow Question并且我的数据是平衡的(1000 张猫图像和 1000 张狗图像),因此根据我的理解,重新平衡我的数据集或调整类别权重不适用。我也尝试过“增加训练时间”。

编辑:testPredictions的内容如下图所示:

[[1.0473319e-05]
 [9.8473930e-01]
 [2.9069009e-01]
 [5.0639841e-07]
 [1.8511847e-01]
 [6.0166395e-01]
 [4.2568660e-01]
 [4.6028453e-01]
 [7.8800195e-01]
 [8.5675471e-02]
 [8.2654454e-02]
 [7.2898394e-01]
 [1.5504999e-01]
 [8.2106847e-01]
 [8.7003058e-01]
 [9.9999285e-01]
 [5.1210046e-01]]

有人可以帮我改正吗?

提前谢谢大家。

最佳答案

这里的问题出在将类分配给 testPredictions 结果时的最后一步。 argmax 方法“返回沿轴的最大值的索引”。在您的情况下,它始终为 0,因为沿 axis=1 您只有一个元素(索引为 0)。

由于您正在进行二元分类并且类别是平衡的,因此应用 0.5 概率阈值来分配类别是最有意义的:

predictedClassIndices = testPredictions > 0.5

for idx, filename in enumerate(filenames):
    print(filename,":",predictedClassIndices[idx])

关于tensorflow - 使用 TF Keras ImageDataGenerator 时 Model.Predict 返回相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62209421/

相关文章:

python - 如何使用 TensorFlow 2 数据集从 URL 加载图像

keras - 如何在 google colab 中找到 keras.json 文件?

python - 在 Keras 模型中保存元数据/信息

python-3.x - 在训练用于对象分类/检测的神经网络时,我们如何知道模型收敛了?

python - Keras 模型评估显示 TypeError : 'numpy.float64' object is not iterable for mnist dataset

python - 嵌套的 tf.function 非常慢

python-3.x - ImageDataGenerator.flow_from_directory 到可在 Kfold 中使用的数据集

python - Tensorflow - 带有 sample_weight 的自定义损失函数

algorithm - TensorFlow:它只有 SGD 算法吗?或者它是否也有其他像 LBFGS

python - 如何创建具有共享权重的两层,其中一层是另一层的转置?