Tensorflow 用于二元分类的DCNN收敛到50%/50%

Tensorflow 用于二元分类的DCNN收敛到50%/50%,tensorflow,machine-learning,keras,classification,cnn,Tensorflow,Machine Learning,Keras,Classification,Cnn,我是Keras的新手,从来没有问过任何问题,所以请原谅我可能犯的任何新手错误。 我想做的是实现一个二进制分类器,对图像进行操作(确切地说是CT) 我的模型基于一个预训练的网络,该网络对14个类进行了分类(参见此处的精彩git) 正如俗话所说,“先爬后走,先走后跑”,我目前的拙劣目标是在大约100个示例上实现网络的过度拟合。 我目前的问题是,网络收敛到一个奇怪的解决方案,输出神经元(我使用的是sigmoid)总是非常接近50%,100%的预测都属于一类(这样我的准确率就高达50%)。我的损失和准确

我是Keras的新手,从来没有问过任何问题,所以请原谅我可能犯的任何新手错误。 我想做的是实现一个二进制分类器,对图像进行操作(确切地说是CT)

我的模型基于一个预训练的网络,该网络对14个类进行了分类(参见此处的精彩git)

正如俗话所说,“先爬后走,先走后跑”,我目前的拙劣目标是在大约100个示例上实现网络的过度拟合。 我目前的问题是,网络收敛到一个奇怪的解决方案,输出神经元(我使用的是sigmoid)总是非常接近50%,100%的预测都属于一类(这样我的准确率就高达50%)。我的损失和准确度从第一个纪元开始就没有改变

我尝试/考虑的事情:

  • 使用不同的优化器(我使用了Adam优化器和下面的SGD)
  • 还尝试使用分类交叉熵(最后是softmax层,而不是sigmoid,因为有人说它可能会表现更好[)
  • 添加一个额外的denselayer(我想我可能不太合适)
  • 尝试将batchsize更改为128(并在1000个示例中过度拟合)
所有这些都失败得很惨,所以我在这里有点不知所措。如果需要,我很乐意提供更多细节,并感谢您提供的任何帮助或见解。我的代码的主要部分附在附件中。请注意,我正在加载和使用的ModelFactory()是经过预训练的

提前谢谢

数据生成器代码

rescale = 1./255.0
target_size = (224, 224)
batch_size = 128

train_datagen = ImageDataGenerator(
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    rescale=rescale
)

train_generator = train_datagen.flow_from_dataframe(
    train_csv,
    directory=train_path,
    x_col='image_name',
    y_col='class',
    target_size=target_size,
    color_mode='rgb',
    class_mode='binary',
    batch_size=batch_size,
    shuffle=True,
    )
我的型号

def get_model():
  file_name='/content/brucechou1983_CheXNet_Keras_0.3.0_weights.h5'
  base_model = ModelFactory().get_model(class_names=[str(i) for i in range(14)],
                                        weights_path=file_name)
  x = base_model.output
  x = keras.layers.Dense(1024, activation='relu')(x)
  x = keras.layers.BatchNormalization(trainable=True)(x)
  predictions = keras.layers.Dense(1, activation='sigmoid')(x)
  model = keras.models.Model(inputs=base_model.inputs, outputs=predictions)
  for layer in base_model.layers:
    layer.trainable = False

  model.summary()
  return model
class_weight = sklearn.utils.class_weight.compute_class_weight('balanced',np.unique(train_csv['class']), train_csv['class'])
model.compile(keras.optimizers.SGD(lr=1e-6, decay=1e-6, momentum=0.9, nesterov=True),
              loss='binary_crossentropy',
              metrics=['binary_accuracy'])
history = model.fit_generator(
    train_generator,
    steps_per_epoch=len(train_generator),
    epochs=10,
    verbose=1,
    class_weight=class_weight
)
培训模型

def get_model():
  file_name='/content/brucechou1983_CheXNet_Keras_0.3.0_weights.h5'
  base_model = ModelFactory().get_model(class_names=[str(i) for i in range(14)],
                                        weights_path=file_name)
  x = base_model.output
  x = keras.layers.Dense(1024, activation='relu')(x)
  x = keras.layers.BatchNormalization(trainable=True)(x)
  predictions = keras.layers.Dense(1, activation='sigmoid')(x)
  model = keras.models.Model(inputs=base_model.inputs, outputs=predictions)
  for layer in base_model.layers:
    layer.trainable = False

  model.summary()
  return model
class_weight = sklearn.utils.class_weight.compute_class_weight('balanced',np.unique(train_csv['class']), train_csv['class'])
model.compile(keras.optimizers.SGD(lr=1e-6, decay=1e-6, momentum=0.9, nesterov=True),
              loss='binary_crossentropy',
              metrics=['binary_accuracy'])
history = model.fit_generator(
    train_generator,
    steps_per_epoch=len(train_generator),
    epochs=10,
    verbose=1,
    class_weight=class_weight
)

如果您的目标是过度拟合数据。请使用。他们擅长完整地学习数据。也许可以尝试删除类权重?这可能会提高精度,但在二进制分类任务中,我发现使用roc_auc分数和f1分数更好。此外,您能包括softmax分类的数据生成器中使用的代码吗?@JodhSingh-我将是su关于第二条评论,我不确定你的确切意思,因为代码只需要一些修改(使用“分类”而不是二进制加载数据,使用“分类精度”而不是二进制加载数据,并且明显地将密度从1个节点更改为2个节点,并使用softmax而不是sigmoid)。你是指这些东西的代码吗?嗨,对我来说有效的是重写代码(尽管我最终得到了非常相似的代码),在我给它跑100个纪元后,它已经过了头:)我可能修复了一个bug,但可能是因为我从未有过bug,我所需要的只是给它更多的时间。谢谢你的帮助!如果你的目标是过度拟合数据。使用。他们擅长完全学习数据。也许可以尝试删除class_权重?这可能会提高准确性,但在二进制分类任务中,我发现使用ro更好c_auc分数和f1分数。另外,你能包括softmax分类数据生成器中使用的代码吗?@JodhSingh-我一定会尝试auc,我会回复你的。至于第二条评论,我不确定你的确切意思,因为代码只需要一些修改(使用“分类”而不是二进制加载数据,使用“分类精度”而不是二进制加载数据,并且明显地将密度从1个节点更改为2个节点,并使用softmax而不是sigmoid)。你是指这些东西的代码吗?嗨,对我来说有效的是重写代码(尽管我最终得到了非常相似的代码),在我给它运行了100个纪元之后,它已经过好了:)我可能修复了一个bug,但可能是我从来没有过,我所需要的只是给它更多的时间。谢谢你的帮助!