【问题标题】:ImageDataGenerator Predict Class - Why are the predictions not correctly converting from probabilities to predicted class?ImageDataGenerator 预测类 - 为什么预测不能正确地从概率转换为预测类?
【发布时间】:2022-03-09 18:40:05
【问题描述】:

我有一个这样设置的目录:

图片

-- val
    --class1
    --class2
-- test
   --all_classes
-- train
    --class1
    --class2

每个目录中都有一组图像。我想预测测试中的每个图像是属于 1 类还是 2 类。

我写这个是为了读入训练和验证数据:

train_path = "/content/drive/train/"
valid_path = "/content/drive/val/"

train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)

train_generator=train_datagen.flow_from_directory(
  directory=train_path,
  batch_size=32,
  class_mode='binary',
  target_size=(150,150)
)

validation_generator=test_datagen.flow_from_directory(
  directory=valid_path,
  batch_size=32,
  class_mode='binary',
  target_size=(150,150)
)

创建了一个网络:

def create_network(): 
  model = Sequential()
  model.add(Input(shape=(150,150,3)))

  model.add(Conv2D(32, kernel_size=3,strides=(1, 1),activation='relu', padding='valid', dilation_rate=1))
  model.add(MaxPooling2D(pool_size=(2, 2)))

  model.add(Conv2D(64, kernel_size=3, strides=(1, 1), activation='relu',padding='valid', dilation_rate=1))
  model.add(MaxPooling2D(pool_size=(2, 2)))

  model.add(Flatten())
  model.add(Dense(512, activation='relu'))

  model.add(Dense(1, activation='sigmoid'))
  plot_model(model, to_file='/content/drive/question1_model.png', show_shapes=True, show_layer_names=True)

  model.compile(optimizer = 'adam',
                   loss = 'binary_crossentropy', 
                   metrics = ['accuracy'])
  return model

拟合模型:

def fit_model(train_generator=train_generator, validation_generator=validation_generator,network=create_network()):
  checkpoint_path = "/content/drive/question1_checkpoint.h5"
  checkpoint_dir = os.path.dirname(checkpoint_path)

  callbacks_list = [
      callbacks.EarlyStopping(
          monitor = 'accuracy',
          patience = 5,
      ),

      callbacks.ModelCheckpoint(
          filepath=checkpoint_path,
          monitor = 'val_loss',
          #save_weights_only=True,
          save_best_only=True,
      ),

  ]

  model = network
  history = model.fit(train_generator,
                      epochs=200,
                      validation_data=validation_generator,
                      batch_size=32, 
                      callbacks = callbacks_list,
                      verbose=1
                      )
  return history,model,time_taken

history,model = fit_model(train_generator,validation_generator)

模型的accuracy和val准确率>80%,我重新加载进去预测:

model = load_model('/content/drive/question1_checkpoint.h5')

然后我想预测测试目录中的一组图像:

test_datagen = ImageDataGenerator(rescale=1./255)
test_path = "/content/drive/test/"

test_generator = test_datagen.flow_from_directory(
  directory=test_path,
  batch_size=16,
  class_mode='binary',
  target_size=(150,150),
  shuffle = False
)
test_generator.reset()
filenames = test_generator.filenames
nb_samples = len(filenames)
batch_size=16
predict = model.predict(test_generator,steps=test_generator.n/batch_size)

当我打印 predict 的开始时,我可以看到:

[[6.09035552e-01]
 [2.47541070e-02]
 [7.37663209e-02]
 [5.22839129e-02]
 [2.94408262e-01]
 [1.39171720e-01]
 [6.15863085e-01]

我认为这给了我第 1 类正确的概率。但是当我打印每个预测的类时:

predicted_class_indices=np.argmax(predict,axis=-1)
print(predicted_class_indices)

输出是:

[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0]

这意味着我的预测概率没有正确地转换为类,对吧?因为例如 2.47541070e-02 是 0.02,而 6.09035552e-01 是 0.60,所以不应该预测这些属于不同的类别吗?谁能告诉我哪里出错了?

【问题讨论】:

    标签: python keras scikit-learn tf.keras


    【解决方案1】:

    这段代码给了我下面的输出:(在用相同的二进制类数据集训练模型后,我已经拍摄了 10 张图像进行测试 - 5 张狗的图像,5 张猫的图像)。

    nb_samples = len(filenames)
    batch_size=5
    predict = model.predict(test_generator,steps=test_generator.n/batch_size)
    predict
    

    输出:

    array([[0.06690815],
           [0.7787118 ],
           [0.109512  ],
           [0.39706784],
           [0.07243159],
           [0.61042166],
           [0.5808931 ],
           [0.86361384],
           [0.9961897 ],
           [0.61571515]], dtype=float32)
    

    这是正确的,因为您在最后一层使用了sigmoid 激活函数,那么输出范围将从 0 到 1。

    请不要将argmax 用于sigmoid 值。您可以使用argmax 方法,同时使用softmax 激活函数来查找其他类概率中类的最高概率值。

    这里你可以使用下面的代码:

    import tensorflow as tf
    
    predictions = tf.where(predict <= 0.5, 0, 1)
    
    print('Predictions:\n', predictions.numpy())
    

    输出:

    Predictions:
    
     [[0]
     [1]
     [0]
     [0]
     [0]
     [1]
     [1]
     [1]
     [1]
     [1]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-16
      • 2017-01-04
      • 2015-11-15
      • 2018-12-24
      • 2018-10-12
      • 2016-05-23
      • 1970-01-01
      相关资源
      最近更新 更多