【问题标题】:Keras CNN prediction output is only predicting within a range of numbersKeras CNN 预测输出仅在一个数字范围内进行预测
【发布时间】:2020-11-10 07:48:18
【问题描述】:

我正在尝试使用 CNN 根据他们的评估分数来预测 3D 医学大脑图像,但是我收到的准确度分数在一个数字范围内(例如:有 7 个可能的测试分数:1、1.5、 2, 2.5, 3, 4, 5 并且输出仅给出 1-1.5 范围内的预测)

我已将图像调整大小、规范化并将其分离为训练 (66 个图像)、测试 (22 个图像) 和验证 (22 个图像) 集。由于图像太少,我添加了一个自定义 3D 图像增强(来自 github),因此图像总数增加到原来的 10 倍。

我尝试更改网络中的大多数(如果不是全部)参数(批量大小、优化器、学习率、更简单/复杂的神经网络、激活、损失等),但无济于事。我也在网上找了类似的问题,希望有人遇到同样的问题并解决了。

这是我正在使用的示例图像:

此图像的大小为 (96, 96, 96),其数组值的一条带为(标准化后):

[0.54124768 0.59549533 0.61464823 0.59833751 0.50441322 0.33578409
 0.40528049 0.4359369  0.39544678 0.32074109 0.20008253 0.28538722
 0.27870766 0.37098099 0.13504691 0.2372147  0.4171059  0.56398624
 0.38187722 0.71896363 0.44387385 0.41523819 0.31195372 0.10586056
 0.12634818 0.13454185 0.57811427 0.6465261  0.61814963 0.61493715]

经过预处理步骤后,我将其输入到我的 CNN 模型中:

batch_size = 3

model = Sequential()

model.add(Conv3D(32, [3, 3, 3], padding='same', activation='relu',
                 input_shape=input_size))
model.add(Conv3D(32, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))

model.add(Conv3D(64, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(64, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
model.add(Dropout(0.5))

model.add(Conv3D(128, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(128, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(128, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))

model.add(Conv3D(256, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(256, [3, 3, 3], padding='same', activation='relu'))
model.add(Conv3D(256, [3, 3, 3], padding='same', activation='relu'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), padding='same'))
model.add(Dropout(0.5))

model.add(Flatten())
model.add(Dense(1024, activation='relu'))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='linear'))

opt = optimizers.Adam(lr=1e-6)
model.compile(loss='mean_squared_logarithmic_error', optimizer=opt, metrics=['accuracy'])

train_datagen = customImageDataGenerator(shear_range=0.2,
                                         zoom_range=0.2,
                                         horizontal_flip=True)

val_datagen = customImageDataGenerator()

test_datagen = customImageDataGenerator()



training_set = train_datagen.flow(x_train, y_train, batch_size=batch_size, shuffle=True)

validation_set = val_datagen.flow(x_val, y_val, batch_size=batch_size, shuffle=False)

testing_set = test_datagen.flow(x_test, y_test, batch_size=batch_size, shuffle=False)



earlystop = EarlyStopping(monitor='val_loss', patience=30)

history = model.fit(
                    training_set,
                    steps_per_epoch = len(x_train)//batch_size,
                    epochs = 50,
                    #callbacks = [earlystop],
                    validation_data = validation_set,
                    validation_steps = len(x_val)//batch_size
                    )

我创建了一个自定义准确性检查来可视化以下输出:

Predicted score: [1.8405123] True score: 3.0
Predicted score: [1.4033222] True score: 3.0
Predicted score: [1.4690828] True score: 1.0
Predicted score: [1.5127727] True score: 3.0
Predicted score: [1.6159409] True score: 1.0
Predicted score: [1.4333361] True score: 1.5
Predicted score: [1.7470968] True score: 3.0
Predicted score: [1.2196972] True score: 1.5
Predicted score: [1.5940914] True score: 4.0
Predicted score: [1.4052064] True score: 1.0
Predicted score: [1.5127727] True score: 1.0
Predicted score: [1.4584785] True score: 1.0
Predicted score: [1.7860543] True score: 3.0
Predicted score: [1.4752649] True score: 2.5
Predicted score: [1.8568267] True score: 1.0
Predicted score: [1.4793051] True score: 3.0
Predicted score: [1.395096] True score: 2.5
Predicted score: [1.6011616] True score: 4.0
Predicted score: [1.9094267] True score: 1.0
Predicted score: [1.6322718] True score: 1.0
Predicted score: [1.7284409] True score: 4.0
Predicted score: [1.5262214] True score: 1.5
Out: 0.09090909090909091

如您所见,即使测试分数在 2.5、3、4 和 5 范围内,预测值也在 1-2 范围内。

print(y_pred.min(), y_pred.max())
1.2196972 1.9094267

最后,这是我的图表:

如您所见,损失减少得很漂亮,但准确性在中途冻结,我不确定可能是什么原因。

抱歉,帖子很长,但我会很感激任何答案,谢谢!

【问题讨论】:

  • 我遇到了同样的问题。你的问题解决了吗?

标签: python keras deep-learning regression


【解决方案1】:

有几件事可能有助于提高模型的准确性。

  1. 在每个 Conv3D 层之后添加 BatchNomalization,它可以提高收敛性。
  2. 尝试将分数缩放到 [0, 1] 范围内。当您有足够的数据时,这通常不是问题,但如果您的数据集很小,则可能会成为问题。这还需要在最后一层激活softmax
  3. 0.5 的下降可能有点极端。尝试在每个 Conv3D 之后添加一个较小的 dropout。它可以方便地与命题 1) 结合使用以下包装器:
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Layer, Conv3D, BatchNormalization, Dropout, InputLayer


class ConvBlock(Layer):
  def __init__(self, filters=32, kernel_size = [3, 3, 3], 
               padding='same', activation='relu', dropout=0.1):
    super(ConvBlock, self).__init__()
    self.conv = Conv3D(filters=filters, 
                       kernel_size=kernel_size, 
                       activation=activation, 
                       padding=padding)
    self.norm = BatchNormalization()
    self.dropout = Dropout(dropout)

  def call(self, input, training=False):
    x = self.conv(input)
    x = self.norm(x)
    x = self.dropout(x, training=training)
    return x
  
  
model = Sequential()

model.add(InputLayer((96, 96, 96, 1)))
model.add(ConvBlock())

model.summary()

希望这有助于改进它至少一点点。

【讨论】:

  • 啊,谢谢你的回复!对于 #2,由于分数是 1-5,我是否应该将它们全部除以 5 以将它们缩放到 [0, 1]?对于#3,包装器到底是什么,它比我拥有的格式更好吗?抱歉,我对深度学习还很陌生,知识也不那么渊博。也许有一些资源可以发给我,因为我自己找不到。谢谢
  • 对于你的第一个问题,最好是 -1,然后是 /4,所以它严格在 0 和 1 之间。包装器只是让事情变得更短。知道这是一件好事,因为您可以实现更复杂的块,例如使用它跳过连接。查看this tensorflow 指南。
  • 另外,尝试更高的学习率,从1e-3 开始,因为1e-6 似乎太小了。
  • 您好,我已经尝试了您提供的建议,但是他们无法解决问题。添加批量标准化增加了输出的范围,但损失值停滞不前。较高的学习率给出了-500的不准确输出值。由于输出仍在特定范围内而不是整个频谱内,因此缩放分数并没有太大改善。减少 dropout 使我的图表略微过拟合。我没有尝试过包装器技术,因为我觉得在没有一定程度的保证它可以工作的情况下学习和实施它需要相当长的时间
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 1970-01-01
  • 2020-01-02
  • 2017-08-27
  • 2020-03-13
  • 2018-02-16
相关资源
最近更新 更多