作者: fchollet
创建日期: 2019/03/20
最后修改: 2020/04/20
描述: 在牛津宠物数据集上从头开始训练的图像分割模型。
!!wget https://www.robots.ox.ac.uk/~vgg/data/pets/data/images.tar.gz
!!wget https://www.robots.ox.ac.uk/~vgg/data/pets/data/annotations.tar.gz
!
!curl -O https://thor.robots.ox.ac.uk/datasets/pets/images.tar.gz
!curl -O https://thor.robots.ox.ac.uk/datasets/pets/annotations.tar.gz
!
!tar -xf images.tar.gz
!tar -xf annotations.tar.gz
% 总计 % 接收 % 转移 平均速度 时间 时间 时间 当前
下载 上传 总计 花费 剩余 速度
100 755M 100 755M 0 0 21.3M 0 0:00:35 0:00:35 --:--:-- 22.2M
% 总计 % 接收 % 转移 平均速度 时间 时间 时间 当前
下载 上传 总计 花费 剩余 速度
100 18.2M 100 18.2M 0 0 7977k 0 0:00:02 0:00:02 --:--:-- 7974k
import os
input_dir = "images/"
target_dir = "annotations/trimaps/"
img_size = (160, 160)
num_classes = 3
batch_size = 32
input_img_paths = sorted(
[
os.path.join(input_dir, fname)
for fname in os.listdir(input_dir)
if fname.endswith(".jpg")
]
)
target_img_paths = sorted(
[
os.path.join(target_dir, fname)
for fname in os.listdir(target_dir)
if fname.endswith(".png") and not fname.startswith(".")
]
)
print("样本数量:", len(input_img_paths))
for input_path, target_path in zip(input_img_paths[:10], target_img_paths[:10]):
print(input_path, "|", target_path)
样本数量: 7390
images/Abyssinian_1.jpg | annotations/trimaps/Abyssinian_1.png
images/Abyssinian_10.jpg | annotations/trimaps/Abyssinian_10.png
images/Abyssinian_100.jpg | annotations/trimaps/Abyssinian_100.png
images/Abyssinian_101.jpg | annotations/trimaps/Abyssinian_101.png
images/Abyssinian_102.jpg | annotations/trimaps/Abyssinian_102.png
images/Abyssinian_103.jpg | annotations/trimaps/Abyssinian_103.png
images/Abyssinian_104.jpg | annotations/trimaps/Abyssinian_104.png
images/Abyssinian_105.jpg | annotations/trimaps/Abyssinian_105.png
images/Abyssinian_106.jpg | annotations/trimaps/Abyssinian_106.png
images/Abyssinian_107.jpg | annotations/trimaps/Abyssinian_107.png
from IPython.display import Image, display
from keras.utils import load_img
from PIL import ImageOps
# 显示输入图像 #7
display(Image(filename=input_img_paths[9]))
# 显示对应目标的自动对比度版本(逐像素类别)
img = ImageOps.autocontrast(load_img(target_img_paths[9]))
display(img)
import keras
import numpy as np
from tensorflow import data as tf_data
from tensorflow import image as tf_image
from tensorflow import io as tf_io
def get_dataset(
batch_size,
img_size,
input_img_paths,
target_img_paths,
max_dataset_len=None,
):
"""返回一个 TF 数据集。"""
def load_img_masks(input_img_path, target_img_path):
input_img = tf_io.read_file(input_img_path)
input_img = tf_io.decode_png(input_img, channels=3)
input_img = tf_image.resize(input_img, img_size)
input_img = tf_image.convert_image_dtype(input_img, "float32")
target_img = tf_io.read_file(target_img_path)
target_img = tf_io.decode_png(target_img, channels=1)
target_img = tf_image.resize(target_img, img_size, method="nearest")
target_img = tf_image.convert_image_dtype(target_img, "uint8")
# 真实标签是 1, 2, 3。减去 1 使其变为 0, 1, 2:
target_img -= 1
return input_img, target_img
# 为了更快的调试,限制数据的大小
if max_dataset_len:
input_img_paths = input_img_paths[:max_dataset_len]
target_img_paths = target_img_paths[:max_dataset_len]
dataset = tf_data.Dataset.from_tensor_slices((input_img_paths, target_img_paths))
dataset = dataset.map(load_img_masks, num_parallel_calls=tf_data.AUTOTUNE)
return dataset.batch(batch_size)
from keras import layers
def get_model(img_size, num_classes):
inputs = keras.Input(shape=img_size + (3,))
### [网络的前半部分: 下采样输入] ###
# 输入块
x = layers.Conv2D(32, 3, strides=2, padding="same")(inputs)
x = layers.BatchNormalization()(x)
x = layers.Activation("relu")(x)
previous_block_activation = x # 保留残差
# 块1, 2, 3 除了特征深度外都是相同的。
for filters in [64, 128, 256]:
x = layers.Activation("relu")(x)
x = layers.SeparableConv2D(filters, 3, padding="same")(x)
x = layers.BatchNormalization()(x)
x = layers.Activation("relu")(x)
x = layers.SeparableConv2D(filters, 3, padding="same")(x)
x = layers.BatchNormalization()(x)
x = layers.MaxPooling2D(3, strides=2, padding="same")(x)
# 投影残差
residual = layers.Conv2D(filters, 1, strides=2, padding="same")(
previous_block_activation
)
x = layers.add([x, residual]) # 加回残差
previous_block_activation = x # 保留下一个残差
### [网络的后半部分: 上采样输入] ###
for filters in [256, 128, 64, 32]:
x = layers.Activation("relu")(x)
x = layers.Conv2DTranspose(filters, 3, padding="same")(x)
x = layers.BatchNormalization()(x)
x = layers.Activation("relu")(x)
x = layers.Conv2DTranspose(filters, 3, padding="same")(x)
x = layers.BatchNormalization()(x)
x = layers.UpSampling2D(2)(x)
# 投影残差
residual = layers.UpSampling2D(2)(previous_block_activation)
residual = layers.Conv2D(filters, 1, padding="same")(residual)
x = layers.add([x, residual]) # 加回残差
previous_block_activation = x # 保留下一个残差
# 添加逐像素分类层
outputs = layers.Conv2D(num_classes, 3, activation="softmax", padding="same")(x)
# 定义模型
model = keras.Model(inputs, outputs)
return model
# 构建模型
model = get_model(img_size, num_classes)
model.summary()
模型: "functional_1"
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┓ ┃ 层 (类型) ┃ 输出形状 ┃ 参数 # ┃ 连接到 ┃ ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━┩ │ input_layer │ (None, 160, 160, │ 0 │ - │ │ (InputLayer) │ 3) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d (Conv2D) │ (None, 80, 80, │ 896 │ input_layer[0][0] │ │ │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalization │ (None, 80, 80, │ 128 │ conv2d[0][0] │ │ (BatchNormalizatio… │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation │ (None, 80, 80, │ 0 │ batch_normalization… │ │ (Activation) │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_1 │ (None, 80, 80, │ 0 │ activation[0][0] │ │ (Activation) │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ separable_conv2d │ (None, 80, 80, │ 2,400 │ activation_1[0][0] │ │ (SeparableConv2D) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 80, 80, │ 256 │ separable_conv2d[0]… │ │ (BatchNormalizatio… │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_2 │ (None, 80, 80, │ 0 │ batch_normalization… │ │ (Activation) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ separable_conv2d_1 │ (None, 80, 80, │ 4,736 │ activation_2[0][0] │ │ (SeparableConv2D) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 80, 80, │ 256 │ separable_conv2d_1[… │ │ (BatchNormalizatio… │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ max_pooling2d │ (None, 40, 40, │ 0 │ batch_normalization… │ │ (MaxPooling2D) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_1 (Conv2D) │ (None, 40, 40, │ 2,112 │ activation[0][0] │ │ │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add (Add) │ (None, 40, 40, │ 0 │ max_pooling2d[0][0], │ │ │ 64) │ │ conv2d_1[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_3 │ (None, 40, 40, │ 0 │ add[0][0] │ │ (Activation) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ separable_conv2d_2 │ (None, 40, 40, │ 8,896 │ activation_3[0][0] │ │ (SeparableConv2D) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 40, 40, │ 512 │ separable_conv2d_2[… │ │ (BatchNormalization │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_4 │ (None, 40, 40, │ 0 │ batch_normalization… │ │ (Activation) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ separable_conv2d_3 │ (None, 40, 40, │ 17,664 │ activation_4[0][0] │ │ (SeparableConv2D) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalization… │ (None, 40, 40, │ 512 │ separable_conv2d_3[… │ │ (BatchNormalization │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ max_pooling2d_1 │ (None, 20, 20, │ 0 │ batch_normalization… │ │ (MaxPooling2D) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_2 (Conv2D) │ (None, 20, 20, │ 8,320 │ add[0][0] │ │ │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add_1 (Add) │ (None, 20, 20, │ 0 │ max_pooling2d_1[0][… │ │ │ 128) │ │ conv2d_2[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_5 │ (无, 20, 20, │ 0 │ add_1[0][0] │ │ (激活) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ separable_conv2d_4 │ (无, 20, 20, │ 34,176 │ activation_5[0][0] │ │ (可分离卷积2D) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (无, 20, 20, │ 1,024 │ separable_conv2d_4[… │ │ (批归一化… │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_6 │ (无, 20, 20, │ 0 │ batch_normalization… │ │ (激活) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ separable_conv2d_5 │ (无, 20, 20, │ 68,096 │ activation_6[0][0] │ │ (可分离卷积2D) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (无, 20, 20, │ 1,024 │ separable_conv2d_5[… │ │ (批归一化… │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ max_pooling2d_2 │ (无, 10, 10, │ 0 │ batch_normalization… │ │ (最大池化2D) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_3 (卷积层) │ (无, 10, 10, │ 33,024 │ add_1[0][0] │ │ │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add_2 (加法层) │ (无, 10, 10, │ 0 │ max_pooling2d_2[0][… │ │ │ 256) │ │ conv2d_3[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_7 │ (无, 10, 10, │ 0 │ add_2[0][0] │ │ (激活层) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose │ (无, 10, 10, │ 590,080 │ activation_7[0][0] │ │ (转置卷积层) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (无, 10, 10, │ 1,024 │ conv2d_transpose[0]… │ │ (批标准化层 │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_8 │ (无, 10, 10, │ 0 │ batch_normalization… │ │ (激活层) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_1 │ (None, 10, 10, │ 590,080 │ activation_8[0][0] │ │ (Conv2DTranspose) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 10, 10, │ 1,024 │ conv2d_transpose_1[… │ │ (BatchNormalizatio… │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_1 │ (None, 20, 20, │ 0 │ add_2[0][0] │ │ (UpSampling2D) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d │ (None, 20, 20, │ 0 │ batch_normalization… │ │ (UpSampling2D) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_4 (Conv2D) │ (None, 20, 20, │ 65,792 │ up_sampling2d_1[0][… │ │ │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add_3 (Add) │ (None, 20, 20, │ 0 │ up_sampling2d[0][0], │ │ │ 256) │ │ conv2d_4[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_9 │ (None, 20, 20, │ 0 │ add_3[0][0] │ │ (Activation) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_2 │ (None, 20, 20, │ 295,040 │ activation_9[0][0] │ │ (Conv2DTranspose) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 20, 20, │ 512 │ conv2d_transpose_2[… │ │ (BatchNormalizatio… │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_10 │ (None, 20, 20, │ 0 │ batch_normalization… │ │ (Activation) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_3 │ (None, 20, 20, │ 147,584 │ activation_10[0][0] │ │ (Conv2DTranspose) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 20, 20, │ 512 │ conv2d_transpose_3[… │ │ (BatchNormalizatio… │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_3 │ (None, 40, 40, │ 0 │ add_3[0][0] │ │ (上采样二维) │ 256) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_2 │ (无, 40, 40, │ 0 │ batch_normalization… │ │ (上采样二维) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_5 (卷积2D) │ (无, 40, 40, │ 32,896 │ up_sampling2d_3[0][… │ │ │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add_4 (加法) │ (无, 40, 40, │ 0 │ up_sampling2d_2[0][… │ │ │ 128) │ │ conv2d_5[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_11 │ (无, 40, 40, │ 0 │ add_4[0][0] │ │ (激活) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_4 │ (无, 40, 40, │ 73,792 │ activation_11[0][0] │ │ (转置卷积2D) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (无, 40, 40, │ 256 │ conv2d_transpose_4[… │ │ (批归一化 │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_12 │ (无, 40, 40, │ 0 │ batch_normalization… │ │ (激活函数) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_5 │ (无, 40, 40, │ 36,928 │ activation_12[0][0] │ │ (反卷积) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (无, 40, 40, │ 256 │ conv2d_transpose_5[… │ │ (批归一化 │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_5 │ (无, 80, 80, │ 0 │ add_4[0][0] │ │ (上采样) │ 128) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_4 │ (无, 80, 80, │ 0 │ batch_normalization… │ │ (上采样) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_6 (卷积) │ (无, 80, 80, │ 8,256 │ up_sampling2d_5[0][… │ │ │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add_5 (加法) │ (无, 80, 80, │ 0 │ up_sampling2d_4[0][… │ │ │ 64) │ │ conv2d_6[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_13 │ (None, 80, 80, │ 0 │ add_5[0][0] │ │ (激活) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_6 │ (None, 80, 80, │ 18,464 │ activation_13[0][0] │ │ (反卷积) │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 80, 80, │ 128 │ conv2d_transpose_6[… │ │ (批量归一化 │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ activation_14 │ (None, 80, 80, │ 0 │ batch_normalization… │ │ (激活) │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_transpose_7 │ (None, 80, 80, │ 9,248 │ activation_14[0][0] │ │ (反卷积) │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ batch_normalizatio… │ (None, 80, 80, │ 128 │ conv2d_transpose_7[… │ │ (批量归一化 │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_7 │ (None, 160, 160, │ 0 │ add_5[0][0] │ │ (UpSampling2D) │ 64) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ up_sampling2d_6 │ (None, 160, 160, │ 0 │ batch_normalization… │ │ (UpSampling2D) │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_7 (Conv2D) │ (None, 160, 160, │ 2,080 │ up_sampling2d_7[0][… │ │ │ 32) │ │ │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ add_6 (Add) │ (None, 160, 160, │ 0 │ up_sampling2d_6[0][… │ │ │ 32) │ │ conv2d_7[0][0] │ ├─────────────────────┼───────────────────┼─────────┼──────────────────────┤ │ conv2d_8 (Conv2D) │ (None, 160, 160, │ 867 │ add_6[0][0] │ │ │ 3) │ │ │ └─────────────────────┴───────────────────┴─────────┴──────────────────────┘
总参数: 2,058,979 (7.85 MB)
可训练参数: 2,055,203 (7.84 MB)
非可训练参数: 3,776 (14.75 KB)
import random
# 将我们的图片路径分成训练集和验证集
val_samples = 1000
random.Random(1337).shuffle(input_img_paths)
random.Random(1337).shuffle(target_img_paths)
train_input_img_paths = input_img_paths[:-val_samples]
train_target_img_paths = target_img_paths[:-val_samples]
val_input_img_paths = input_img_paths[-val_samples:]
val_target_img_paths = target_img_paths[-val_samples:]
# 为每个分割实例化数据集
# 在`max_dataset_len`中限制输入文件,以加快训练时间。
# 在使用完整数据集时,删除`max_dataset_len`参数。
train_dataset = get_dataset(
batch_size,
img_size,
train_input_img_paths,
train_target_img_paths,
max_dataset_len=1000,
)
valid_dataset = get_dataset(
batch_size, img_size, val_input_img_paths, val_target_img_paths
)
# 配置模型以进行训练。
# 我们使用“稀疏”版本的categorical_crossentropy
# 因为我们的目标数据是整数。
model.compile(
optimizer=keras.optimizers.Adam(1e-4), loss="sparse_categorical_crossentropy"
)
callbacks = [
keras.callbacks.ModelCheckpoint("oxford_segmentation.keras", save_best_only=True)
]
# 训练模型,在每个epoch结束时进行验证。
epochs = 50
model.fit(
train_dataset,
epochs=epochs,
validation_data=valid_dataset,
callbacks=callbacks,
verbose=2,
)
Epoch 1/50
WARNING: 所有在 absl::InitializeLog() 调用之前的日志消息都被写入 STDERR
I0000 00:00:1700414690.172044 2226172 device_compiler.h:187] 使用 XLA 编译的集群!该行在进程生命周期内最多记录一次。
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 62s - 2s/步骤 - 损失: 1.6363 - 验证损失: 2.2226
Epoch 2/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 94ms/步骤 - 损失: 0.9223 - 验证损失: 1.8273
Epoch 3/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 82ms/步骤 - 损失: 0.7894 - 验证损失: 2.0044
Epoch 4/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.7174 - 验证损失: 2.3480
Epoch 5/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 82ms/步骤 - 损失: 0.6695 - 验证损失: 2.7528
Epoch 6/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.6325 - 验证损失: 3.1453
Epoch 7/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 84ms/步骤 - 损失: 0.6012 - 验证损失: 3.5611
Epoch 8/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.5730 - 验证损失: 4.0003
Epoch 9/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 85ms/步骤 - 损失: 0.5466 - 验证损失: 4.4798
Epoch 10/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 86ms/步骤 - 损失: 0.5210 - 验证损失: 5.0245
Epoch 11/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.4958 - 验证损失: 5.5950
Epoch 12/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.4706 - 验证损失: 6.1534
Epoch 13/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 85ms/步骤 - 损失: 0.4453 - 验证损失: 6.6107
Epoch 14/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.4202 - 验证损失: 6.8010
Epoch 15/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 84ms/步骤 - 损失: 0.3956 - 验证损失: 6.6751
Epoch 16/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.3721 - 验证损失: 6.0800
Epoch 17/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 84ms/步骤 - 损失: 0.3506 - 验证损失: 5.1820
Epoch 18/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 82ms/步骤 - 损失: 0.3329 - 验证损失: 4.0350
Epoch 19/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 4s - 114ms/步骤 - 损失: 0.3216 - 验证损失: 3.0513
Epoch 20/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 94ms/步骤 - 损失: 0.3595 - 验证损失: 2.2567
Epoch 21/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 100ms/步骤 - 损失: 0.4417 - 验证损失: 1.5873
Epoch 22/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 101ms/步骤 - 损失: 0.3531 - 验证损失: 1.5798
Epoch 23/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 96ms/步骤 - 损失: 0.3353 - 验证损失: 1.5525
Epoch 24/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 95ms/步骤 - 损失: 0.3392 - 验证损失: 1.4625
Epoch 25/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 95ms/步骤 - 损失: 0.3596 - 验证损失: 0.8867
Epoch 26/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 94ms/步骤 - 损失: 0.3528 - 验证损失: 0.8021
Epoch 27/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 92ms/步骤 - 损失: 0.3237 - 验证损失: 0.7986
Epoch 28/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 89ms/步骤 - 损失: 0.3198 - 验证损失: 0.8533
Epoch 29/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 84ms/步骤 - 损失: 0.3272 - 验证损失: 1.0588
Epoch 30/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 88ms/步骤 - 损失: 0.3164 - 验证损失: 1.1889
Epoch 31/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 85ms/步骤 - 损失: 0.2987 - 验证损失: 0.9518
Epoch 32/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.2749 - 验证损失: 0.9011
Epoch 33/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 84ms/步骤 - 损失: 0.2595 - 验证损失: 0.8872
Epoch 34/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.2552 - 验证损失: 1.0221
Epoch 35/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 82ms/步骤 - 损失: 0.2628 - 验证损失: 1.1553
Epoch 36/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 85ms/步骤 - 损失: 0.2788 - 验证损失: 2.1549
Epoch 37/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 94ms/步骤 - 损失: 0.2870 - 验证损失: 1.6282
Epoch 38/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 89ms/步骤 - 损失: 0.2702 - 验证损失: 1.3201
Epoch 39/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 91ms/步骤 - 损失: 0.2569 - 验证损失: 1.2364
Epoch 40/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 106ms/步骤 - 损失: 0.2523 - 验证损失: 1.3673
Epoch 41/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 86ms/步骤 - 损失: 0.2570 - 验证损失: 1.3999
Epoch 42/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.2680 - 验证损失: 0.9976
Epoch 43/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.2558 - 验证损失: 1.0209
Epoch 44/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 85ms/步骤 - 损失: 0.2403 - 验证损失: 1.3271
Epoch 45/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.2414 - 验证损失: 1.1993
Epoch 46/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 84ms/步骤 - 损失: 0.2516 - 验证损失: 1.0532
Epoch 47/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.2695 - 验证损失: 1.1183
Epoch 48/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 87ms/步骤 - 损失: 0.2555 - 验证损失: 1.0432
Epoch 49/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 82ms/步骤 - 损失: 0.2290 - 验证损失: 0.9444
Epoch 50/50
损坏的 JPEG 数据:标记 0xd9 前有 240 个多余的字节
32/32 - 3s - 83ms/步骤 - 损失: 0.1994 - 验证损失: 1.2182
<keras.src.callbacks.history.History 在 0x7fe01842dab0>
# 生成验证集中所有图像的预测
val_dataset = get_dataset(
batch_size, img_size, val_input_img_paths, val_target_img_paths
)
val_preds = model.predict(val_dataset)
def display_mask(i):
"""用于快速显示模型预测的工具。"""
mask = np.argmax(val_preds[i], axis=-1)
mask = np.expand_dims(mask, axis=-1)
img = ImageOps.autocontrast(keras.utils.array_to_img(mask))
display(img)
# 显示验证图像 #10 的结果
i = 10
# 显示输入图像
display(Image(filename=val_input_img_paths[i]))
# 显示真实目标掩码
img = ImageOps.autocontrast(load_img(val_target_img_paths[i]))
display(img)
# 显示我们模型预测的掩码
display_mask(i) # 注意模型只看到150x150的输入。
32/32 ━━━━━━━━━━━━━━━━━━━━ 5s 100ms/step