Keras二进制精度与手动计算不同

时间:2020-01-24 19:59:42

标签: python tensorflow keras image-segmentation

我遵循了tensorflow tutorial on image segmentation

我正在处理带有灰度图像的二进制图像分割任务。 我只是将图像复制了3次,以拥有3个通道。

损失函数为binary_crossentropy,指标为binary_accuracy, 在最后一层使用sigmoid激活功能。因此,每个像素只有一个输出值:0或1。我将输入归一化为[0,1],标签也为0或1。

我的问题是,由模型计算的二进制精度不同于我的手动计算。 这是一个完整的小型笔记本示例:

import numpy as np
import tensorflow as tf
# !pip install -q git+https://github.com/tensorflow/examples.git
from tensorflow_examples.models.pix2pix import pix2pix 

IMG_SIZE = 32
OUTPUT_CHANNELS = 1

image = np.random.randint(256, size=(IMG_SIZE, IMG_SIZE))
image = image / 255
image = np.repeat(image[..., np.newaxis], 3, -1) # copy the grayscale value 3 times

label = np.random.randint(2, size=(IMG_SIZE, IMG_SIZE))
label = tf.cast(label, tf.float32)
label = tf.expand_dims(label, 2)

train_data = (tf.expand_dims(image, 0),tf.expand_dims(label, 0)) 
train_data = tf.data.Dataset.from_tensor_slices(train_data).batch(1)

base_model = tf.keras.applications.MobileNetV2(input_shape=[IMG_SIZE, IMG_SIZE, 3], include_top=False)

# Use the activations of these layers
layer_names = [
    'block_1_expand_relu',   # 64x64
    'block_3_expand_relu',   # 32x32
    'block_6_expand_relu',   # 16x16
    'block_13_expand_relu',  # 8x8
    'block_16_project',      # 4x4
]
layers = [base_model.get_layer(name).output for name in layer_names]
down_stack = tf.keras.Model(inputs=base_model.input, outputs=layers)
down_stack.trainable = False # Do not train the encoder

up_stack = [
    pix2pix.upsample(512, 3),  # 4x4 -> 8x8
    pix2pix.upsample(256, 3),  # 8x8 -> 16x16
    pix2pix.upsample(128, 3),  # 16x16 -> 32x32
    pix2pix.upsample(64, 3),   # 32x32 -> 64x64
]

def unet_model(output_channels):
    last = tf.keras.layers.Conv2DTranspose(
        output_channels, 3, strides=2, 
        padding='same', activation='sigmoid')  #64x64 -> 128x128

    inputs = tf.keras.layers.Input(shape=[IMG_SIZE, IMG_SIZE, 3])
    x = inputs

    # Downsampling through the model
    skips = down_stack(x) 
    x = skips[-1] 
    skips = reversed(skips[:-1]) 

    for up, skip in zip(up_stack, skips): 
        x = up(x) 
        concat = tf.keras.layers.Concatenate()
        x = concat([x, skip]) 

    x = last(x) 

    return tf.keras.Model(inputs=inputs, outputs=x)

def create_mask(pred_mask):
    pred_mask = tf.cast(pred_mask.reshape(32,32,1) > 0.5, tf.int32)
    return pred_mask

model = unet_model(OUTPUT_CHANNELS)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['binary_accuracy'])

model_history = model.fit(train_data, epochs=10)

pred_mask = create_mask(model.predict(tf.expand_dims(image, 0)))

TP = len(tf.where((pred_mask==1)&(label==1)))
TN = len(tf.where((pred_mask==0)&(label==0)))
FP = len(tf.where((pred_mask==1)&(label==0)))
FN = len(tf.where((pred_mask==0)&(label==1)))
print("Binary accuracy manual:", (TP+TN)/(TP+FP+FN+TN))
print("Binary accuracy Keras:", tf.keras.metrics.binary_accuracy(pred_mask, tf.cast(label, tf.int32)).numpy().sum()/(32*32))

我认为二进制图像分割任务的设置应该可以:

  • binary_crossentropy
  • binary_accuracy
  • 乙状结肠激活功能
  • 归一化为[0,1]

手动计算二进制精度与使用tf.keras.metrics.binary_accuracy()(最后2个打印语句)相同。但是,它与model.fit()报告的结果不同。

我在这里想念什么? 谢谢!

0 个答案:

没有答案