Keras不对称数据糖尿病视网膜病变检测

时间:2017-01-29 10:33:22

标签: python machine-learning keras theano-cuda

我正在尝试为Diabetic Retinopathy Detection制作预测模型。比赛的trainig数据集包括非对称图像的非对称分为5类:正常-25807图像-73.48%; Mild-2442图像-6.96%;中等-5291图像-15.07%;严重的873图像-2.48%和增殖-708图像 - 2.01%。 为此,我使用带有Theano后端的Keras框架(用于CUDA计算)。

对于图像增强,我使用了ImageDataGenerator(代码如下)。我已将图像重新调整为299x299,并将它们分成5个文件夹,相应地分类:

train_datagen=ImageDataGenerator(rescale=1./255, rotation_range=40, zoom_range=0.2, horizontal_flip=True, fill_mode="constant", zca_whitening=True)
train_generator=train_datagen.flow_from_directory('data/~huge_data/preprocessed_imgs/', target_size=(299, 299), batch_size=32, class_mode='categorical')

起初,仅仅是为了测试,我决定使用一个简单的卷积模型:

model=Sequential()
model.add(Convolution2D(32,3,3, input_shape=(3, 299, 299), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(32, 3, 3, activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Convolution2D(64, 3, 3, activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(5, activation='softmax'))

model.compile(loss='categorical_crossentropy', 
              optimizer='rmsprop', 
              metrics=['accuracy'])

在拟合图像生成器时,我指出了class_weights以修复数据的不对称性:class_weight = {0:25807.,1:2442。,2:5291。,3:873。,4:708。};

model.fit_generator(train_generator,
                   samples_per_epoch=2000,
                   nb_epoch=50, 
                    verbose=2, 
                   callbacks=callbacks_list,
                   class_weight ={0: 25807., 1:2442., 2:5291., 3:873., 4:708.})

My folders with images

问题:

  1. 模型输出具有高损耗和高精度。为什么?
  2. 大纪元1/50 110s - 损失:5147.2669 - acc:0.7366

    大纪元2/50 105s - 损失:5052.3844 - acc:0.7302

    大纪元3/50 105s - 损失:5042.0261 - acc:0.7421

    大纪元4/50 105s - 损失:4986.3544 - acc:0.7361

    大纪元5/50 105s - 损失:4999.4177 - acc:0.7361

    1. 每个图像模型预测为'0'类:
    2. datagen_2 = ImageDataGenerator(重新缩放= 1/255)

      val_generator=datagen_2.flow_from_directory('data/color_validation_images/',
                                               target_size=(299,299),
                                               batch_size=100,
                                                 class_mode='categorical')
      
      y_predict=model.predict_generator(val_generator,
                             val_samples=82)
      
      
      [np.argmax(i) for i in y_predict]
      

      它的输出是:

      0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0,
       0
      

      没有argmax(部分)

      array([  9.47651565e-01,   7.30426749e-03,   4.40788604e-02,
                6.25302084e-04,   3.39932943e-04], dtype=float32),
       array([  9.51994598e-01,   6.50278665e-03,   4.07058187e-02,
                5.17037639e-04,   2.79774162e-04], dtype=float32),
       array([  9.49448049e-01,   6.50656316e-03,   4.32702228e-02,
                5.20388770e-04,   2.54814397e-04], dtype=float32),
       array([  9.47873473e-01,   7.13181263e-03,   4.40776311e-02,
                6.00705389e-04,   3.16353660e-04], dtype=float32),
       array([  9.53514516e-01,   6.13699574e-03,   3.96034382e-02,
                4.82603034e-04,   2.62484333e-04], dtype=float32),
      ....
      

      如果我尝试使用class_weight ='auto'。在这种情况下,模型显示“可预测的”输出:

      大纪元1/50 107s - 损失:0.9036 - acc:0.7381

      大纪元2/50 104s - 损失:0.9333 - acc:0.7321

      大纪元3/50 105s - 损失:0.8865 - acc:0.7351

      大纪元4/50 106s - 损失:0.8978 - acc:0.7351

      大纪元5/50 105s - 损失:0.9158 - acc:0.7302

      但是,它仍然不起作用:

      severe_DR=plt.imread('data/~huge_data/preprocessed_imgs/3_Severe/99_left.jpeg')
      mild_DR=plt.imread('data/~huge_data/preprocessed_imgs/1_Mild/15_left.jpeg')
      moderate_DR=plt.imread('data/~huge_data/preprocessed_imgs/2_Moderate/78_right.jpeg')
      
      model.predict(mild_DR.reshape((1,)+x[1].shape))
      array([[ 1.,  0.,  0.,  0.,  0.]], dtype=float32)
      
      model.predict(severe_DR.reshape((1,)+x[1].shape))
      array([[ 1.,  0.,  0.,  0.,  0.]], dtype=float32)
      
      model.predict(moderate_DR.reshape((1,)+x[1].shape))
      array([[ 1.,  0.,  0.,  0.,  0.]], dtype=float32)
      

      我做错了什么?

      在回答Sergii Gryshkevych后,我修复了我的模型:我已将class_weight更改为{0:1,1:10.57,2:4.88,3:29,4:35}(我将每个类中的图像分成最大值图像(在头等舱))。接下来,我将指标更改为categorical_accuracy。我在模型中提取了层数(如here)。 所以,5个时期之后的输出是:

      大纪元1/5 500/500 [==============================] - 52s - 损失:5.6944 - categorical_accuracy:0.1840
      大纪元2/5 500/500 [==============================] - 52s - 损失:6.7357 - categorical_accuracy:0.2040
      大纪元3/5 500/500 [==============================] - 52s - 损失:6.7373 - categorical_accuracy:0.0800
      大纪元4/5 500/500 [==============================] - 52s - 损失:6.0311 - categorical_accuracy:0.0180
      大纪元5/5 500/500 [==============================] - 51s - 损失:4.9924 - categorical_accuracy:0.0560

      这是对的吗?

      有没有办法在keras中指定二次加权kappa作为指标?

1 个答案:

答案 0 :(得分:2)

“高”精度约73-74%来自所有图像被归类为0类的事实。您的数据集是不平衡的,因为大多数类占样本的73%。因此,在这种情况下准确性并不多,您需要使用从混淆矩阵中获得的其他指标,如精度,召回,F1得分等。

多类日志丢失功能极其严重地惩罚错误的预测。对于除0之外的所有类,您的预测几乎为零,因此在如此高的损失值中没有任何意外。

总而言之,您面临着经典的阶级失衡问题。减轻它的两种最常见的方法是

  1. 调整班级重量。使少数民族课“更重要”,因此学习算法不会忽略它们。您可以将自定义类权重作为fit方法的参数提供:
  2.   

    class_weight:将类映射到权重值的字典,用于缩放损失函数(仅在训练期间)。

    1. 过采样/欠。简单地过滤少数类的示例以使您的数据集平衡,或者将其与欠采样相结合,当在每个学习时期的开始时丢弃多数类的一些随机选择的示例。
    2. 类失衡问题并不新鲜,因此有很多关于此主题的阅读材料,例如thisthis介绍性帖子。