图像识别模型每次都猜同 Class

Image Recognition Model Guessing the Same Class Every Time

我正在尝试在 HAM10000 skin lesion database 上训练默认的 Squeezenet 实现,而我的模型一直在猜测 nv。如果您查看数据库,您会发现 nv 病变明显多于任何其他 class。 test/train 拆分后,我获得了这些数字:{0: 271, 1: 412, 2: 869, 3: 88, 4: 899, 5: 5367, 6: 119} 作为我的训练数据集。 5这里代表nv。我尝试了几种不同的损失函数(categorical_crossentropy、categorical_hinge)、几种不同的优化器(sgd、adam)和几种不同的实现方法class_weights(total/count、5367/ count, log(5367/count),以及手动设置 5 的权重小于 1)。在所有这一切之后,我要么得到不间断的 nv 猜测,要么我给 nv 赋予非常低的权重并获得子猜测准确率。我 运行 没有想法,想知道我还能做些什么。我还考虑过重做我的 test/train 拆分,以便测试中每个 class 的计数是统一的,但我担心这会花费很多时间而无法工作。

这是模型的代码

img_input = Input(shape=input_shape)

x = Conv2D(64, (3, 3), strides=(2, 2), padding='valid', name='conv1')(img_input)
x = Activation('relu', name='relu_conv1')(x)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool1')(x)

x = fire_module(x, fire_id=2, squeeze=16, expand=64)
x = fire_module(x, fire_id=3, squeeze=16, expand=64)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool3')(x)

x = fire_module(x, fire_id=4, squeeze=32, expand=128)
x = fire_module(x, fire_id=5, squeeze=32, expand=128)
x = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool5')(x)

x = fire_module(x, fire_id=6, squeeze=48, expand=192)
x = fire_module(x, fire_id=7, squeeze=48, expand=192)
x = fire_module(x, fire_id=8, squeeze=64, expand=256)
x = fire_module(x, fire_id=9, squeeze=64, expand=256)
x = Dropout(0.5, name='drop9')(x)

x = Conv2D(7, (1, 1), padding='valid', name='conv10')(x) #uses classes
x = Activation('softmax', name='loss')(x)
x = GlobalAveragePooling2D(data_format='channels_last')(x)

inputs = img_input

model = Model(inputs, x, name='squeezenet')

这是我用于 运行

的代码
np.random.seed(333)
train_data_dir = 'data/imgs/train'
validation_data_dir = 'data/imgs/test'
nb_train_samples = 8025
nb_validation_samples = 1990
epochs = 100 #todo change
batch_size = 32
img_width = 600
img_height = 450
class_weight = {0: 2.99, 1: 2.56, 2: 1.82, 3: 4.11, 4: 1.79, 5: 0.3, 6: 3.8} #this is the class weight for my most recent run, which is currently oscillating between always guessing nv and <15% accuracy

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

name = 'Squeezenet'

model = initModel(name, input_shape) # This gets the model from the above code snippit
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

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(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='categorical')

    validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='categorical')

history = model.fit_generator(
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size,
    class_weight=class_weight)

model.save('models/{0}_cat.h5'.format(name))

更改最后一层的顺序。更改自:

x = Activation('softmax', name='loss')(x)
x = GlobalAveragePooling2D(data_format='channels_last')(x)

x = GlobalAveragePooling2D(data_format='channels_last')(x)
x = Activation('softmax', name='loss')(x)