Tensorflow 自定义损失不兼容的形状

Tensorflow custom loss Incompatible shapes

型号:Deeplab v3+ backbone network:resnet50 自定义loss:binary_crossentropy + 骰子损失

我不知道为什么我在将 binary_crossentropy 损失更改为 binary_crossentropy + 骰子损失后出现此不兼容的形状错误。

这是我的代码。

import os

import cv2

import numpy as np

from glob import glob

from scipy.io import loadmat

import matplotlib.pyplot as plt

import tensorflow as tf

from tensorflow import keras

from tensorflow.keras import layers

IMAGE_SIZE = 400

NUM_CLASSES = 2

img_gen = tf.keras.preprocessing.image.ImageDataGenerator(horizontal_flip=True,vertical_flip=True,rescale=1./255)

mask_gen = tf.keras.preprocessing.image.ImageDataGenerator(horizontal_flip=True,vertical_flip=True,rescale=1./255)

image_generator = img_gen.flow_from_directory("/content/gdrive/MyDrive/Colab Notebooks/my_dataset/road_data/training/img",target_size=(400, 400),class_mode=None,color_mode="rgb",batch_size=8,seed=1)

mask_generator = img_gen.flow_from_directory("/content/gdrive/MyDrive/Colab Notebooks/my_dataset/road_data/training/mask",target_size=(400, 400),class_mode=None,color_mode="grayscale",batch_size=8,seed=1)

train_generator = zip(image_generator, mask_generator)#或train_generator = (image_generator, mask_generator)

image_valid_generator = img_gen.flow_from_directory("/content/gdrive/MyDrive/Colab Notebooks/my_dataset/road_data/valid/img",target_size=(400, 400),class_mode=None,color_mode="rgb",batch_size=8,seed=1)

mask_valid_generator = img_gen.flow_from_directory("/content/gdrive/MyDrive/Colab Notebooks/my_dataset/road_data/valid/mask",target_size=(400, 400),class_mode=None,color_mode="grayscale",batch_size=8,seed=1)

valid_generator = zip(image_valid_generator, mask_valid_generator)

” 找到属于 1 类.

的 320 张图片

找到属于 1 类 的 320 张图像。

找到属于 1 类 的 20 张图片。

找到属于 1 类 的 20 张图片。"

def convolution_block(
    block_input,
    num_filters=256,
    kernel_size=3,
    dilation_rate=1,
    padding="same",
    use_bias=False,
):
    x = layers.Conv2D(
        num_filters,
        kernel_size=kernel_size,
        dilation_rate=dilation_rate,
        padding="same",
        use_bias=use_bias,
        kernel_initializer=keras.initializers.HeNormal(),
    )(block_input)
    x = layers.BatchNormalization()(x)
    return tf.nn.relu(x)


def DilatedSpatialPyramidPooling(dspp_input):
    dims = dspp_input.shape
    x = layers.AveragePooling2D(pool_size=(dims[-3], dims[-2]))(dspp_input)
    x = convolution_block(x, kernel_size=1, use_bias=True)
    out_pool = layers.UpSampling2D(
        size=(dims[-3] // x.shape[1], dims[-2] // x.shape[2]), interpolation="bilinear",
    )(x)

    out_1 = convolution_block(dspp_input, kernel_size=1, dilation_rate=1)
    out_6 = convolution_block(dspp_input, kernel_size=3, dilation_rate=6)
    out_12 = convolution_block(dspp_input, kernel_size=3, dilation_rate=12)
    out_18 = convolution_block(dspp_input, kernel_size=3, dilation_rate=18)

    x = layers.Concatenate(axis=-1)([out_pool, out_1, out_6, out_12, out_18])
    output = convolution_block(x, kernel_size=1)
    return output

def DeeplabV3Plus(image_size, num_classes):
    model_input = keras.Input(shape=(image_size, image_size, 3))
    resnet50 = keras.applications.ResNet50(
        weights="imagenet", include_top=False, input_tensor=model_input
    )
    x = resnet50.get_layer("conv4_block6_2_relu").output
    x = DilatedSpatialPyramidPooling(x)

    input_a = layers.UpSampling2D(
        size=(image_size // 4 // x.shape[1], image_size // 4 // x.shape[2]),
        interpolation="bilinear",
    )(x)
    input_b = resnet50.get_layer("conv2_block3_2_relu").output
    input_b = convolution_block(input_b, num_filters=48, kernel_size=1)

    x = layers.Concatenate(axis=-1)([input_a, input_b])
    x = convolution_block(x)
    x = convolution_block(x)
    x = layers.UpSampling2D(
        size=(image_size // x.shape[1], image_size // x.shape[2]),
        interpolation="bilinear",
    )(x)
    model_output = layers.Conv2D(num_classes, kernel_size=(1, 1), padding="same")(x)
    return keras.Model(inputs=model_input, outputs=model_output)


model = DeeplabV3Plus(image_size=IMAGE_SIZE, num_classes=NUM_CLASSES)
model.summary()

输出层为“conv2d_9 (Conv2D) (None, 400, 400, 2) 514 ['up_sampling2d_2[0][0]']”

from keras import backend as K
def bce_logdice_loss(y_true, y_pred):
    print(y_true.shape)
    print(y_pred.shape)
    intersection = K.sum(y_true * y_pred, axis=[1,2,3])
    union = K.sum(y_true, axis=[1,2,3]) + K.sum(y_pred, axis=[1,2,3])
    dice_loss = K.mean( (2. * intersection + 1) / (union + 1), axis=0)
    return tf.keras.losses.binary_crossentropy(y_true, y_pred) +1.0 - dice_loss


def my_iou(y_true, y_pred, smooth=1):
    y_true_f = K.flatten(y_true)
    y_pred = K.cast(y_pred, 'float32')
    y_pred_f = K.cast(K.greater(K.flatten(y_pred), 0.5), 'float32')
    intersection = y_true_f * y_pred_f
    iou_result = ( K.sum(intersection)+1.0)/(K.sum(y_true_f)+K.sum(y_pred_f)-K.sum(intersection)+1.0)
    return iou_result

from keras.callbacks import Callback, ModelCheckpoint
checkpoint = ModelCheckpoint(
    '/content/gdrive/MyDrive/Colab Notebooks/my_deeplab_model_temp.h5', 
    monitor='val_loss',  
    save_best_only=True, 
    save_weights_only=False,
    mode='auto'
)
    model.compile(loss=bce_logdice_loss, optimizer="adam", metrics=['accuracy',my_iou])


history = model.fit(train_generator, steps_per_epoch=320/8,batch_size=8, epochs=10,validation_data=valid_generator,validation_steps=20/8)

纪元 1/10

(None, None, None, None)

(None, 400, 400, 2)

(None, None, None, None)

(None, 400, 400, 2)


InvalidArgumentError                      Traceback (most recent call last)
<ipython-input-56-7b3b6ce46c0f> in <module>()
      
----> 1 history = model.fit(train_generator, steps_per_epoch=320/8,batch_size=8, epochs=10,validation_data=valid_generator,validation_steps=20/8,callbacks=[checkpoint])

1 frames
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
     57     ctx.ensure_initialized()
     58     tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
---> 59                                         inputs, attrs, num_outputs)
     60   except core._NotOkStatusException as e:
     61     if name is not None:

InvalidArgumentError:  Incompatible shapes: [2560000] vs. [1280000]

我看到一些类似的问题说你可以尝试使用 reshape 函数,但我认为这很奇怪。

因为在Kaggle上看到了一些例子。他们不使用重塑功能。

然后我打印 y_pred 和 y_true 形状以便调试。但是不知道为什么y_true的形状是none.

这段代码是我写的。

mask_test=下一步(img_gen.flow_from_directory("/content/gdrive/MyDrive/Colab Notebooks/my_dataset/road_data/training/mask",target_size=(400, 400),class_mode= None,color_mode="灰度",batch_size=8,种子=1))

打印(mask_test[0].shape)

我得到了这个“(400, 400, 1)”

所以我觉得我的training ground truth是可以的。

我不知道如何处理这个错误。我希望有人能帮助我。

你的 bce_logdice_loss 损失对我来说看起来不错。

你知道 2560000 的来源吗?

请注意,y_predy_true 的形状最初是 None,因为 Tensorflow 在创建计算图时不知道 batch_size。仅创建一次后,模型将使用 batch_size 作为第一个维度的形状,而不是 None.