【问题标题】:Keras Model Output is float32 instead of uint8... despite data labels being uint8Keras 模型输出是 float32 而不是 uint8 ...尽管数据标签是 uint8
【发布时间】:2019-03-26 01:11:22
【问题描述】:

我正在训练一个模型来预测医学图像中的分割。在训练数据中,输入数据的类型为:numpy.float64,ground truth 标签的类型为:numpy.uint8。问题是由于某种原因我的模型产生了 numpy.float32 的输出类型。

图片显示: example of data types

# Defining the model
segmenter = Model(input_img, segmenter(input_img))

# Training the model (type of train_ground is numpy.uint8)
segmenter_train = segmenter.fit(train_X, train_ground, batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(valid_X, valid_ground))

模型定义:

def segmenter(input_img):
    #encoder
    #input = 28 x 28 x 1 (wide and thin)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(input_img) #28 x 28 x 32
    conv1 = BatchNormalization()(conv1)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
    conv1 = BatchNormalization()(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1) #14 x 14 x 32
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1) #14 x 14 x 64
    conv2 = BatchNormalization()(conv2)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    conv2 = BatchNormalization()(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) #7 x 7 x 64
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2) #7 x 7 x 128 (small and thick)
    conv3 = BatchNormalization()(conv3)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    conv3 = BatchNormalization()(conv3)


    #decoder
    conv4 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv3) #7 x 7 x 128
    conv4 = BatchNormalization()(conv4)
    conv4 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv4)
    conv4 = BatchNormalization()(conv4)
    up1 = UpSampling2D((2,2))(conv4) # 14 x 14 x 128
    conv5 = Conv2D(32, (3, 3), activation='relu', padding='same')(up1) # 14 x 14 x 64
    conv5 = BatchNormalization()(conv5)
    conv5 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv5)
    conv5 = BatchNormalization()(conv5)
    up2 = UpSampling2D((2,2))(conv5) # 28 x 28 x 64

    conv6 = Conv2D(64, (3, 3), activation='relu', padding='same')(up2) #7 x 7 x 128
    conv6 = BatchNormalization()(conv6)
    conv6 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv6)
    conv6 = BatchNormalization()(conv6)
    up3 = UpSampling2D((2,2))(conv6) # 14 x 14 x 128

    conv7 = Conv2D(64, (3, 3), activation='relu', padding='same')(up3) #7 x 7 x 128
    conv7 = BatchNormalization()(conv7)
    conv7 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv7)
    conv7 = BatchNormalization()(conv7)
    up4 = UpSampling2D((2,2))(conv7) # 14 x 14 x 128

    decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(up4) # 28 x 28 x 1
    return decoded

在此先感谢您的帮助:)

【问题讨论】:

  • 嗯,模型的结构和数据类型在构建模型的时候是固定的,在你调用 .fit() 之前就已经确定好了,所以训练时提供的数据标签的类型不能对其有任何影响。模型的结构是什么,具体来说,最后一层到底是什么?
  • 谢谢@Peteris,我刚刚添加了模型构造的细节,包括最后一层。如果还有什么有用的,请告诉我!
  • 没问题,神经网络的输出总是一个实数,要得到二元决策,你必须对输出进行阈值化才能得到二元决策。如果你使用 softmax 激活,那么你选择概率更高的类。

标签: python numpy keras deep-learning uint8array


【解决方案1】:

Sigmoid 返回一个实数

最后一层恰好是 sigmoid 激活函数。它返回一个从 0 到 1 的实数,而不是整数。

此外,重要的是错误度量,即正确答案和计算值之间的差异,是连续的而不是离散的,因为这是可微分的,并且允许通过反向传播正确学习神经网络权重。

只需转换和四舍五入

为了训练网络,只需将真值标签转换为浮点值。

一旦您训练了网络并想要使用它的输出,只需将它们四舍五入以将它们转换为整数 - sigmoid 激活非常适合。

【讨论】:

  • 谢谢,这很有意义。 sigmoid 函数只能返回最大值 1,但测试数据标签的值高于 1。我可以缩放训练数据标签,使最大值为 1,这将允许模型学习正确的输出。跨度>
  • 另一方面,这对我来说是一个有趣的错误!我必须在训练和验证集上有相当高的损失,因为由于最大值为 1,该函数无法真正匹配目标数据输出。
  • @aksg87 如果您希望网络返回一组离散数字中的一个,那么 sigmoid 很可能不适合最后一层,而您可能想要使用例如如果它本质上是一个分类问题,则具有分类交叉熵的 one-hot 编码;或者如果它是一个标量但离散的输出,则对最后一层使用线性或 ReLU 激活。
  • 是的,这些不同的选项现在很有意义,谢谢!我正在预测每个像素(0、1、2、3、4)具有离散值的图像掩码。我认为这个问题与其他帖子(stackoverflow.com/questions/45178513/…)类似。现在看来,交叉熵损失是最合适的!
猜你喜欢
  • 1970-01-01
  • 2018-08-10
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 2019-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多