第J2周:ResNet50V2算法实现01(Tensorflow硬编码版)
- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
目标
使用tensorflow实现ResNetV50V2的网络结构。本次根据第一层的细节手动硬编码,没有任何的优化,只为了更好的理解细节。
目录结构:
网络结构图见最后
具体实现
(一)环境
语言环境:Python 3.10
编 译 器: PyCharm
框 架: Tensorflow
(二)具体步骤
1. ResNet50V2的实现
from keras import layers
from keras.layers import Input, Activation, BatchNormalization, Flatten, GlobalAveragePooling2D
from keras.layers import Dense, Conv2D,MaxPooling2D,ZeroPadding2D
from keras.models import Model
# 非优化版,直接按照ResNet50V2的网络结构,先写出来训练。
def ResNet50V2(input_shape=[224, 224, 3], classes=1000):
# 输入
img_input = Input(shape=input_shape)
# STAGE 0 第一个卷积层和池化层
x = ZeroPadding2D((1,1), name='conv1_pad')(img_input)
x = Conv2D(64, (7,7), strides = (2,2), name = 'conv1')(x)
x = BatchNormalization(name = 'bn_conv1')(x)
x = Activation('relu')(x)
x = ZeroPadding2D((1,1))(x)
x = MaxPooling2D((3,3), strides = (2,2))(x)
# STAGE 1
# 预激活
x1 = BatchNormalization(name = 'bn_stage1_conv2')(x)
x1 = Activation('relu')(x1)
x1 = Conv2D(64, (1,1), strides = (1,1), name = 'conv2')(x1)
x1 = BatchNormalization(name = 'bn_conv3')(x1)
x1 = Activation('relu')(x1)
x1 = ZeroPadding2D((1,1))(x1)
x1 = Conv2D(64, (3,3), strides = (1,1), name = 'conv3')(x1)
x1 = BatchNormalization(name = 'bn_conv4')(x1)
x1 = Activation('relu')(x1)
x1 = Conv2D(256, (1,1), strides = (1,1), name = 'conv4')(x1)
# 对输入张量进行1x1卷积,以匹配输出张量的维度
shortcut = Conv2D(256, (1, 1), strides=(1, 1), name='conv5')(x)
# 将卷积结果与输入张量相加,实现残差连接
x1 = layers.add([x1, shortcut], name='add1')
# STAGE 2
x2 = BatchNormalization(name='bn1')(x1)
x2 = Activation('relu', name='relu4')(x2)
x2 = Conv2D(64, (1, 1), strides=(1, 1), name='conv6')(x2)
x2 = BatchNormalization(name='bn2')(x2)
x2 = Activation('relu', name='relu5')(x2)
x2 = ZeroPadding2D((1, 1), name='pad1')(x2)
x2 = Conv2D(64, (3, 3), strides=(1, 1), name='conv7')(x2)
x2 = BatchNormalization(name='bn3')(x2)
x2 = Activation('relu', name='relu6')(x2)
x2 = Conv2D(256, (1, 1), strides=(1, 1), name='conv8')(x2)
shortcut = Conv2D(256, (1, 1), strides=(1, 1), name='conv9')(x1)
x2 = layers.add([x2, shortcut], name='add2')
# STAGE 3
x3 = BatchNormalization(name='bn4')(x2)
x3 = Activation('relu', name='relu7')(x3)
x3 = Conv2D(64, (1, 1), strides=(1, 1), name='conv10')(x3)
x3 = BatchNormalization(name='bn5')(x3)
x3 = Activation('relu', name='relu8')(x3)
x3 = ZeroPadding2D((1, 1), name='pad2')(x3)
x3 = Conv2D(64, (3, 3), strides=(2, 2), name='conv11')(x3)
x3 = BatchNormalization(name='bn6')(x3)
x3 = Activation('relu', name='relu9')(x3)
x3 = Conv2D(256, (1, 1), strides=(1, 1), name='conv12')(x3)
shortcut = Conv2D(256, (1, 1), strides=(2, 2), name='conv13')(x2)
x3 = layers.add([x3, shortcut], name='add3')
# STAGE 4
x4 = BatchNormalization(name='bn7')(x3)
x4 = Activation('relu', name='relu10')(x4)
x4 = Conv2D(128, (1, 1), strides=(1, 1), name='conv14')(x4)
x4 = BatchNormalization(name='bn8')(x4)
x4 = Activation('relu', name='relu11')(x4)
x4 = ZeroPadding2D((1, 1), name='pad3')(x4)
x4 = Conv2D(128, (3, 3), strides=(1, 1), name='conv15')(x4)
x4 = BatchNormalization(name='bn9')(x4)
x4 = Activation('relu', name='relu12')(x4)
x4 = Conv2D(512, (1, 1), strides=(1, 1), name='conv16')(x4)
shortcut = Conv2D(512, (1, 1), strides=(1, 1), name='conv17')(x3)
x4 = layers.add([x4, shortcut], name='add4')
# STAGE 5
x5 = BatchNormalization(name='bn10')(x4)
x5 = Activation('relu', name='relu13')(x5)
x5 = Conv2D(128, (1, 1), strides=(1, 1), name='conv18')(x5)
x5 = BatchNormalization(name='bn11')(x5)
x5 = Activation('relu', name='relu14')(x5)
x5 = ZeroPadding2D((1, 1), name='pad4')(x5)
x5 = Conv2D(128, (3, 3), strides=(1, 1), name='conv19')(x5)
x5 = BatchNormalization(name='bn12')(x5)
x5 = Activation('relu', name='relu15')(x5)
x5 = Conv2D(512, (1, 1), strides=(1, 1), name='conv20')(x5)
shortcut = Conv2D(512, (1, 1), strides=(1, 1), name='conv21')(x4)
x5 = layers.add([x5, shortcut], name='add5')
# STAGE 6
x6 = BatchNormalization(name='bn13')(x5)
x6 = Activation('relu', name='relu16')(x6)
x6 = Conv2D(128, (1, 1), strides=(1, 1), name='conv22')(x6)
x6 = BatchNormalization(name='bn14')(x6)
x6 = Activation('relu', name='relu17')(x6)
x6 = ZeroPadding2D((1, 1), name='pad5')(x6)
x6 = Conv2D(128, (3, 3), strides=(1, 1), name='conv23')(x6)
x6 = BatchNormalization(name='bn15')(x6)
x6 = Activation('relu', name='relu18')(x6)
x6 = Conv2D(512, (1, 1), strides=(1, 1), name='conv24')(x6)
shortcut = Conv2D(512, (1, 1), strides=(1, 1), name='conv25')(x5)
x6 = layers.add([x6, shortcut], name='add6')
# STAGE 7
x7 = BatchNormalization(name='bn16')(x6)
x7 = Activation('relu', name='relu19')(x7)
x7 = Conv2D(128, (1, 1), strides=(1, 1), name='conv26')(x7)
x7 = BatchNormalization(name='bn17')(x7)
x7 = Activation('relu', name='relu20')(x7)
x7 = ZeroPadding2D((1, 1), name='pad6')(x7)
x7 = Conv2D(128, (3, 3), strides=(2, 2), name='conv27')(x7)
x7 = BatchNormalization(name='bn18')(x7)
x7 = Activation('relu', name='relu21')(x7)
x7 = Conv2D(512, (1, 1), strides=(1, 1), name='conv28')(x7)
# shortcut = MaxPooling2D(pool_size=(1, 1), strides=(2, 2), padding='valid', name='conv29')(x6)
shortcut = Conv2D(512, (1, 1), strides=(2, 2), name='conv30')(x6)
x7 = layers.add([x7, shortcut], name='add7')
# STAGE 8
x8 = BatchNormalization(name='bn19')(x7)
x8 = Activation('relu', name='relu22')(x8)
x8 = Conv2D(256, (1, 1), strides=(1, 1), name='conv31')(x8)
x8 = BatchNormalization(name='bn20')(x8)
x8 = Activation('relu', name='relu23')(x8)
x8 = ZeroPadding2D((1, 1), name='pad7')(x8)
x8 = Conv2D(256, (3, 3), strides=(1, 1), name='conv32')(x8)
x8 = BatchNormalization(name='bn21')(x8)
x8 = Activation('relu', name='relu24')(x8)
x8 = Conv2D(1024, (1, 1), strides=(1, 1), name='conv33')(x8)
shortcut = Conv2D(1024, (1, 1), strides=(1, 1), name='conv34')(x7)
x8 = layers.add([x8, shortcut], name='add8')
# STAGE 9
x9 = BatchNormalization(name='bn22')(x8)
x9 = Activation('relu', name='relu25')(x9)
x9 = Conv2D(256, (1, 1), strides=(1, 1), name='conv35')(x9)
x9 = BatchNormalization(name='bn23')(x9)
x9 = Activation('relu', name='relu26')(x9)
x9 = ZeroPadding2D((1, 1), name='pad8')(x9)
x9 = Conv2D(256, (3, 3), strides=(1, 1), name='conv36')(x9)
x9 = BatchNormalization(name='bn24')(x9)
x9 = Activation('relu', name='relu27')(x9)
x9 = Conv2D(1024, (1, 1), strides=(1, 1), name='conv37')(x9)
shortcut = Conv2D(1024, (1, 1), strides=(1, 1), name='conv38')(x8)
x9 = layers.add([x9, shortcut], name='add9')
# STAGE 10
x10 = BatchNormalization(name='bn25')(x9)
x10 = Activation('relu', name='relu28')(x10)
x10 = Conv2D(256, (1, 1), strides=(1, 1), name='conv39')(x10)
x10 = BatchNormalization(name='bn26')(x10)
x10 = Activation('relu', name='relu29')(x10)
x10 = ZeroPadding2D((1, 1), name='pad9')(x10)
x10 = Conv2D(256, (3, 3), strides=(1, 1), name='conv40')(x10)
x10 = BatchNormalization(name='bn27')(x10)
x10 = Activation('relu', name='relu30')(x10)
x10 = Conv2D(1024, (1, 1), strides=(1, 1), name='conv41')(x10)
shortcut = Conv2D(1024, (1, 1), strides=(1, 1), name='conv42')(x9)
x10 = layers.add([x10, shortcut], name='add10')
# STAGE 11
x11 = BatchNormalization(name='bn28')(x10)
x11 = Activation('relu', name='relu31')(x11)
x11 = Conv2D(256, (1, 1), strides=(1, 1), name='conv43')(x11)
x11 = BatchNormalization(name='bn29')(x11)
x11 = Activation('relu', name='relu32')(x11)
x11 = ZeroPadding2D((1, 1), name='pad10')(x11)
x11 = Conv2D(256, (3, 3), strides=(1, 1), name='conv44')(x11)
x11 = BatchNormalization(name='bn30')(x11)
x11 = Activation('relu', name='relu33')(x11)
x11 = Conv2D(1024, (1, 1), strides=(1, 1), name='conv45')(x11)
shortcut = Conv2D(1024, (1, 1), strides=(1, 1), name='conv46')(x10)
x11 = layers.add([x11, shortcut], name='add11')
# STAGE 12
x12 = BatchNormalization(name='bn31')(x11)
x12 = Activation('relu', name='relu34')(x12)
x12 = Conv2D(256, (1, 1), strides=(1, 1), name='conv47')(x12)
x12 = BatchNormalization(name='bn32')(x12)
x12 = Activation('relu', name='relu35')(x12)
x12 = ZeroPadding2D((1, 1), name='pad11')(x12)
x12 = Conv2D(256, (3, 3), strides=(2, 2), name='conv48')(x12)
x12 = BatchNormalization(name='bn33')(x12)
x12 = Activation('relu', name='relu36')(x12)
x12 = Conv2D(1024, (1, 1), strides=(1, 1), name='conv49')(x12)
shortcut = MaxPooling2D(pool_size=(1, 1), strides=(2, 2), padding='valid', name='conv50')(x11)
shortcut = Conv2D(1024, (1, 1), strides=(1, 1), name='conv51')(shortcut)
x12 = layers.add([x12, shortcut], name='add12')
# STAGE 13
x13 = BatchNormalization(name='bn34')(x12)
x13 = Activation('relu', name='relu37')(x13)
x13 = Conv2D(512, (1, 1), strides=(1, 1), name='conv52')(x13)
x13 = BatchNormalization(name='bn35')(x13)
x13 = Activation('relu', name='relu38')(x13)
x13 = ZeroPadding2D((1, 1), name='pad12')(x13)
x13 = Conv2D(512, (3, 3), strides=(1, 1), name='conv53')(x13)
x13 = BatchNormalization(name='bn36')(x13)
x13 = Activation('relu', name='relu39')(x13)
x13 = Conv2D(2048, (1, 1), strides=(1, 1), name='conv54')(x13)
shortcut = Conv2D(2048, (1, 1), strides=(1, 1), name='conv55')(x12)
x13 = layers.add([x13, shortcut], name='add13')
# STAGE 14
x14 = BatchNormalization(name='bn37')(x13)
x14 = Activation('relu', name='relu40')(x14)
x14 = Conv2D(512, (1, 1), strides=(1, 1), name='conv56')(x14)
x14 = BatchNormalization(name='bn38')(x14)
x14 = Activation('relu', name='relu41')(x14)
x14 = ZeroPadding2D((1, 1), name='pad13')(x14)
x14 = Conv2D(512, (3, 3), strides=(1, 1), name='conv57')(x14)
x14 = BatchNormalization(name='bn39')(x14)
x14 = Activation('relu', name='relu42')(x14)
x14 = Conv2D(2048, (1, 1), strides=(1, 1), name='conv58')(x14)
shortcut = Conv2D(2048, (1, 1), strides=(1, 1), name='conv59')(x13)
x14 = layers.add([x14, shortcut], name='add14')
# STAGE 15
x15 = BatchNormalization(name='bn40')(x14)
x15 = Activation('relu', name='relu43')(x15)
x15 = Conv2D(512, (1, 1), strides=(1, 1), name='conv60')(x15)
x15 = BatchNormalization(name='bn41')(x15)
x15 = Activation('relu', name='relu44')(x15)
x15 = ZeroPadding2D((1, 1), name='pad14')(x15)
x15 = Conv2D(512, (3, 3), strides=(1, 1), name='conv61')(x15)
x15 = BatchNormalization(name='bn42')(x15)
x15 = Activation('relu', name='relu45')(x15)
x15 = Conv2D(2048, (1, 1), strides=(1, 1), name='conv62')(x15)
shortcut = Conv2D(2048, (1, 1), strides=(1, 1), name='conv63')(x14)
x15 = layers.add([x15, shortcut], name='add15')
# STAGE 16
x16 = BatchNormalization(name='bn43')(x15)
x16 = Activation('relu', name='relu46')(x16)
x16 = GlobalAveragePooling2D()(x16)
x16 = Flatten()(x16)
x16 = Dense(classes, activation='softmax', name='fc1000')(x16)
model = Model(img_input, x16, name='ResNet50V2')
return model
if __name__=='__main__':
model = ResNet50V2()
model.summary()
2.训练代码
import numpy as np
import tensorflow as tf
from models.ResNet50V2 import ResNet50V2
from tensorflow.python.data import AUTOTUNE
# 设置GPU
# 获取当前系统中所有可用的物理GPU设备
gpus = tf.config.list_physical_devices("GPU")
# 如果系统中存在GPU设备
if gpus:
# 设置第一个GPU设备的内存增长模式为动态增长,以避免一次性占用所有显存
tf.config.experimental.set_memory_growth(gpus[0], True)
# 设置当前可见的GPU设备为第一个GPU,确保程序仅使用该GPU进行计算
tf.config.set_visible_devices([gpus[0]], "GPU")
# 导入数据
import matplotlib.pyplot as plt
import os, PIL, pathlib
from tensorflow import keras
from tensorflow.keras import layers, models
# 设置matplotlib的字体为SimHei,以支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置matplotlib的负号显示为正常符号,避免显示为方块
plt.rcParams['axes.unicode_minus'] = False
# 定义数据目录路径
data_dir = "./data/bird_photos"
# 将路径转换为pathlib.Path对象,方便后续操作
data_dir = pathlib.Path(data_dir)
# 使用glob方法获取所有子目录下的jpg文件,并计算其数量
image_count = len(list(data_dir.glob('*/*.jpg')))
# 打印图片数量
print("图片数量:",image_count)
# 数据预处理
# 定义批量大小和图像尺寸
batch_size = 8
img_height = 224
img_width = 224
# 使用 `tf.keras.preprocessing.image_dataset_from_directory` 从指定目录加载训练数据集
# 参数说明:
# - data_dir: 包含图像数据的目录路径
# - validation_split: 用于验证集的数据比例,此处为20%
# - subset: 指定加载的数据子集,此处为训练集
# - seed: 随机种子,确保数据分割的可重复性
# - image_size: 图像将被调整到的尺寸,此处为224x224
# - batch_size: 每个批次的图像数量,此处为8
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 使用 `tf.keras.preprocessing.image_dataset_from_directory` 从指定目录加载验证数据集
# 参数说明与训练集相同,但 `subset` 参数指定为验证集
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 从训练数据集中获取类别名称
class_names = train_ds.class_names
# 打印类别名称
print("类别:", class_names)
# 可视化数据
# 可视化训练数据集中的部分图像及其对应的标签
# 该代码块创建一个大小为10x5的图形窗口,并在窗口中展示训练数据集中的前8张图像及其标签。
plt.figure(figsize=(10, 5)) # 创建一个大小为10x5的图形窗口
plt.suptitle("训练数据集可视化") # 设置图形的标题为"训练数据集可视化"
# 从训练数据集中取出一批数据(images和labels),并展示其中的前8张图像
for images, labels in train_ds.take(1):
for i in range(8):
ax = plt.subplot(2, 4, i+1) # 在2行4列的网格中创建第i+1个子图
plt.imshow(images[i].numpy().astype("uint8")) # 显示第i张图像,并将其转换为uint8类型
plt.title(class_names[labels[i]]) # 设置子图的标题为对应的类别名称
plt.axis("off") # 关闭子图的坐标轴显示
# 检查数据
"""
遍历训练数据集中的批次,并打印图像批次和标签批次的形状。
该代码片段从训练数据集 `train_ds` 中获取一个批次的数据,并打印该批次中图像和标签的形状。
`train_ds` 是一个可迭代对象,通常包含图像和标签的批次数据。
代码执行流程:
1. 从 `train_ds` 中获取一个批次的图像和标签。
2. 打印图像批次的形状。
3. 打印标签批次的形状。
4. 使用 `break` 语句提前退出循环,仅处理第一个批次。
"""
for image_batch, labels_batch in train_ds:
# 打印图像批次的形状,通常为 (batch_size, height, width, channels) print(image_batch.shape)
# 打印标签批次的形状,通常为 (batch_size,) print(labels_batch.shape)
# 仅处理第一个批次后退出循环
break
# 配置数据集
# 设置自动调优参数,用于优化数据加载和预处理性能
AUTOTUNE = tf.data.AUTOTUNE
# 对训练数据集进行优化处理:
# 1. `cache()`: 将数据集缓存到内存或磁盘,避免在每个epoch重复加载数据,提高训练效率。
# 2. `shuffle(1000)`: 对数据集进行随机打乱,缓冲区大小为1000,确保训练数据的随机性。
# 3. `prefetch(buffer_size=AUTOTUNE)`: 使用自动调优的缓冲区大小,预取数据以重叠数据加载和模型训练,提高整体性能。
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
# 对验证数据集进行优化处理:
# 1. `cache()`: 将数据集缓存到内存或磁盘,避免在每个epoch重复加载数据,提高验证效率。
# 2. `prefetch(buffer_size=AUTOTUNE)`: 使用自动调优的缓冲区大小,预取数据以重叠数据加载和模型验证,提高整体性能。
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
# 初始化一个ResNet50V2模型实例
# 参数说明:
# - input_shape: 输入图像的形状,格式为[height, width, channels],此处为[224, 224, 3],表示224x224像素的RGB图像
# - classes: 分类任务的类别数量,此处为class_names列表的长度,表示模型将输出对应类别的概率
model = ResNet50V2(classes=4)
# 打印模型的摘要信息,包括每一层的名称、输出形状和参数数量
model.summary()
model.compile(
# 使用Adam优化器,学习率初始值为0.001
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
# 设置损失函数为交叉熵损失函数
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
# 设置性能指标列表,将在模型训练时监控列表中的指标
metrics=['accuracy']
)
# 训练模型并记录训练过程中的历史数据
#
# 参数:
# train_ds: 训练数据集,通常是一个tf.data.Dataset对象,包含训练数据。
# validation_data: 验证数据集,通常是一个tf.data.Dataset对象,用于在训练过程中评估模型性能。
# epochs: 训练的轮数,即模型将遍历整个训练数据集的次数。
#
# 返回值:
# history: 一个History对象,包含训练过程中的损失和评估指标的历史记录。
epochs = 10
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
# 评估模型
# 该代码块用于绘制模型训练过程中的准确率和损失曲线,以便可视化模型在训练集和验证集上的表现。
# 从训练历史记录中提取训练集和验证集的准确率及损失值
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
# 生成一个范围,表示训练的轮数(epochs)
epochs_range = range(epochs)
# 创建一个大小为12x4的图形窗口
plt.figure(figsize=(12, 4))
# 在图形窗口的第一个子图中绘制训练集和验证集的准确率曲线
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right') # 添加图例,位置在右下角
plt.title('Training and Validation Accuracy') # 设置子图标题
# 在图形窗口的第二个子图中绘制训练集和验证集的损失曲线
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right') # 添加图例,位置在右上角
plt.title('Training and Validation Loss') # 设置子图标题
# 显示绘制的图形
plt.show()
# 预测
# 该函数用于展示验证数据集中的图片,并使用训练好的模型对图片进行预测,显示预测结果。
# 函数的主要步骤包括:
# 1. 创建一个大小为10x5的图形窗口。
# 2. 设置图形的总标题为“图片预测”。
# 3. 从验证数据集中取出一批图片和标签。
# 4. 对每张图片进行预测,并在子图中显示图片和预测结果。
# 5. 关闭子图的坐标轴显示。
plt.figure(figsize=(10, 5)) # 创建一个大小为10x5的图形窗口
plt.suptitle("图片预测") # 设置图形的总标题为“图片预测”
# 从验证数据集中取出一批图片和标签
for images, labels in val_ds.take(1):
# 遍历前8张图片,并在子图中显示图片和预测结果
for i in range(8):
ax = plt.subplot(2, 4, i+1) # 创建2行4列的子图,并选择第i+1个子图
plt.imshow(images[i].numpy().astype("uint8")) # 显示第i张图片
# 对图片进行预测
img_array = tf.expand_dims(images[i], 0) # 扩展图片的维度以适应模型输入
predictions = model.predict(img_array) # 使用模型进行预测
# 在子图标题中显示预测结果
plt.title(class_names[np.argmax(predictions)])
plt.axis("off") # 关闭子图的坐标轴显示
结果:
Model: "ResNet50V2"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 224, 224, 3 0 []
)]
conv1_pad (ZeroPadding2D) (None, 226, 226, 3) 0 ['input_1[0][0]']
conv1 (Conv2D) (None, 110, 110, 64 9472 ['conv1_pad[0][0]']
)
bn_conv1 (BatchNormalization) (None, 110, 110, 64 256 ['conv1[0][0]']
)
activation (Activation) (None, 110, 110, 64 0 ['bn_conv1[0][0]']
)
zero_padding2d (ZeroPadding2D) (None, 112, 112, 64 0 ['activation[0][0]']
)
max_pooling2d (MaxPooling2D) (None, 55, 55, 64) 0 ['zero_padding2d[0][0]']
bn_conv2 (BatchNormalization) (None, 55, 55, 64) 256 ['max_pooling2d[0][0]']
activation_1 (Activation) (None, 55, 55, 64) 0 ['bn_conv2[0][0]']
conv2 (Conv2D) (None, 55, 55, 64) 4160 ['activation_1[0][0]']
bn_conv3 (BatchNormalization) (None, 55, 55, 64) 256 ['conv2[0][0]']
activation_2 (Activation) (None, 55, 55, 64) 0 ['bn_conv3[0][0]']
zero_padding2d_1 (ZeroPadding2 (None, 57, 57, 64) 0 ['activation_2[0][0]']
D)
conv3 (Conv2D) (None, 55, 55, 64) 36928 ['zero_padding2d_1[0][0]']
bn_conv4 (BatchNormalization) (None, 55, 55, 64) 256 ['conv3[0][0]']
activation_3 (Activation) (None, 55, 55, 64) 0 ['bn_conv4[0][0]']
conv4 (Conv2D) (None, 55, 55, 256) 16640 ['activation_3[0][0]']
conv5 (Conv2D) (None, 55, 55, 256) 16640 ['max_pooling2d[0][0]']
add1 (Add) (None, 55, 55, 256) 0 ['conv4[0][0]',
'conv5[0][0]']
bn1 (BatchNormalization) (None, 55, 55, 256) 1024 ['add1[0][0]']
relu4 (Activation) (None, 55, 55, 256) 0 ['bn1[0][0]']
conv6 (Conv2D) (None, 55, 55, 64) 16448 ['relu4[0][0]']
bn2 (BatchNormalization) (None, 55, 55, 64) 256 ['conv6[0][0]']
relu5 (Activation) (None, 55, 55, 64) 0 ['bn2[0][0]']
pad1 (ZeroPadding2D) (None, 57, 57, 64) 0 ['relu5[0][0]']
conv7 (Conv2D) (None, 55, 55, 64) 36928 ['pad1[0][0]']
bn3 (BatchNormalization) (None, 55, 55, 64) 256 ['conv7[0][0]']
relu6 (Activation) (None, 55, 55, 64) 0 ['bn3[0][0]']
conv8 (Conv2D) (None, 55, 55, 256) 16640 ['relu6[0][0]']
conv9 (Conv2D) (None, 55, 55, 256) 65792 ['add1[0][0]']
add2 (Add) (None, 55, 55, 256) 0 ['conv8[0][0]',
'conv9[0][0]']
bn4 (BatchNormalization) (None, 55, 55, 256) 1024 ['add2[0][0]']
relu7 (Activation) (None, 55, 55, 256) 0 ['bn4[0][0]']
conv10 (Conv2D) (None, 55, 55, 64) 16448 ['relu7[0][0]']
bn5 (BatchNormalization) (None, 55, 55, 64) 256 ['conv10[0][0]']
relu8 (Activation) (None, 55, 55, 64) 0 ['bn5[0][0]']
pad2 (ZeroPadding2D) (None, 57, 57, 64) 0 ['relu8[0][0]']
conv11 (Conv2D) (None, 28, 28, 64) 36928 ['pad2[0][0]']
bn6 (BatchNormalization) (None, 28, 28, 64) 256 ['conv11[0][0]']
relu9 (Activation) (None, 28, 28, 64) 0 ['bn6[0][0]']
conv12 (Conv2D) (None, 28, 28, 256) 16640 ['relu9[0][0]']
conv13 (Conv2D) (None, 28, 28, 256) 65792 ['add2[0][0]']
add3 (Add) (None, 28, 28, 256) 0 ['conv12[0][0]',
'conv13[0][0]']
bn7 (BatchNormalization) (None, 28, 28, 256) 1024 ['add3[0][0]']
relu10 (Activation) (None, 28, 28, 256) 0 ['bn7[0][0]']
conv14 (Conv2D) (None, 28, 28, 128) 32896 ['relu10[0][0]']
bn8 (BatchNormalization) (None, 28, 28, 128) 512 ['conv14[0][0]']
relu11 (Activation) (None, 28, 28, 128) 0 ['bn8[0][0]']
pad3 (ZeroPadding2D) (None, 30, 30, 128) 0 ['relu11[0][0]']
conv15 (Conv2D) (None, 28, 28, 128) 147584 ['pad3[0][0]']
bn9 (BatchNormalization) (None, 28, 28, 128) 512 ['conv15[0][0]']
relu12 (Activation) (None, 28, 28, 128) 0 ['bn9[0][0]']
conv16 (Conv2D) (None, 28, 28, 512) 66048 ['relu12[0][0]']
conv17 (Conv2D) (None, 28, 28, 512) 131584 ['add3[0][0]']
add4 (Add) (None, 28, 28, 512) 0 ['conv16[0][0]',
'conv17[0][0]']
bn10 (BatchNormalization) (None, 28, 28, 512) 2048 ['add4[0][0]']
relu13 (Activation) (None, 28, 28, 512) 0 ['bn10[0][0]']
conv18 (Conv2D) (None, 28, 28, 128) 65664 ['relu13[0][0]']
bn11 (BatchNormalization) (None, 28, 28, 128) 512 ['conv18[0][0]']
relu14 (Activation) (None, 28, 28, 128) 0 ['bn11[0][0]']
pad4 (ZeroPadding2D) (None, 30, 30, 128) 0 ['relu14[0][0]']
conv19 (Conv2D) (None, 28, 28, 128) 147584 ['pad4[0][0]']
bn12 (BatchNormalization) (None, 28, 28, 128) 512 ['conv19[0][0]']
relu15 (Activation) (None, 28, 28, 128) 0 ['bn12[0][0]']
conv20 (Conv2D) (None, 28, 28, 512) 66048 ['relu15[0][0]']
conv21 (Conv2D) (None, 28, 28, 512) 262656 ['add4[0][0]']
add5 (Add) (None, 28, 28, 512) 0 ['conv20[0][0]',
'conv21[0][0]']
bn13 (BatchNormalization) (None, 28, 28, 512) 2048 ['add5[0][0]']
relu16 (Activation) (None, 28, 28, 512) 0 ['bn13[0][0]']
conv22 (Conv2D) (None, 28, 28, 128) 65664 ['relu16[0][0]']
bn14 (BatchNormalization) (None, 28, 28, 128) 512 ['conv22[0][0]']
relu17 (Activation) (None, 28, 28, 128) 0 ['bn14[0][0]']
pad5 (ZeroPadding2D) (None, 30, 30, 128) 0 ['relu17[0][0]']
conv23 (Conv2D) (None, 28, 28, 128) 147584 ['pad5[0][0]']
bn15 (BatchNormalization) (None, 28, 28, 128) 512 ['conv23[0][0]']
relu18 (Activation) (None, 28, 28, 128) 0 ['bn15[0][0]']
conv24 (Conv2D) (None, 28, 28, 512) 66048 ['relu18[0][0]']
conv25 (Conv2D) (None, 28, 28, 512) 262656 ['add5[0][0]']
add6 (Add) (None, 28, 28, 512) 0 ['conv24[0][0]',
'conv25[0][0]']
bn16 (BatchNormalization) (None, 28, 28, 512) 2048 ['add6[0][0]']
relu19 (Activation) (None, 28, 28, 512) 0 ['bn16[0][0]']
conv26 (Conv2D) (None, 28, 28, 128) 65664 ['relu19[0][0]']
bn17 (BatchNormalization) (None, 28, 28, 128) 512 ['conv26[0][0]']
relu20 (Activation) (None, 28, 28, 128) 0 ['bn17[0][0]']
pad6 (ZeroPadding2D) (None, 30, 30, 128) 0 ['relu20[0][0]']
conv27 (Conv2D) (None, 14, 14, 128) 147584 ['pad6[0][0]']
bn18 (BatchNormalization) (None, 14, 14, 128) 512 ['conv27[0][0]']
relu21 (Activation) (None, 14, 14, 128) 0 ['bn18[0][0]']
conv28 (Conv2D) (None, 14, 14, 512) 66048 ['relu21[0][0]']
conv30 (Conv2D) (None, 14, 14, 512) 262656 ['add6[0][0]']
add7 (Add) (None, 14, 14, 512) 0 ['conv28[0][0]',
'conv30[0][0]']
bn19 (BatchNormalization) (None, 14, 14, 512) 2048 ['add7[0][0]']
relu22 (Activation) (None, 14, 14, 512) 0 ['bn19[0][0]']
conv31 (Conv2D) (None, 14, 14, 256) 131328 ['relu22[0][0]']
bn20 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv31[0][0]']
relu23 (Activation) (None, 14, 14, 256) 0 ['bn20[0][0]']
pad7 (ZeroPadding2D) (None, 16, 16, 256) 0 ['relu23[0][0]']
conv32 (Conv2D) (None, 14, 14, 256) 590080 ['pad7[0][0]']
bn21 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv32[0][0]']
relu24 (Activation) (None, 14, 14, 256) 0 ['bn21[0][0]']
conv33 (Conv2D) (None, 14, 14, 1024 263168 ['relu24[0][0]']
)
conv34 (Conv2D) (None, 14, 14, 1024 525312 ['add7[0][0]']
)
add8 (Add) (None, 14, 14, 1024 0 ['conv33[0][0]',
) 'conv34[0][0]']
bn22 (BatchNormalization) (None, 14, 14, 1024 4096 ['add8[0][0]']
)
relu25 (Activation) (None, 14, 14, 1024 0 ['bn22[0][0]']
)
conv35 (Conv2D) (None, 14, 14, 256) 262400 ['relu25[0][0]']
bn23 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv35[0][0]']
relu26 (Activation) (None, 14, 14, 256) 0 ['bn23[0][0]']
pad8 (ZeroPadding2D) (None, 16, 16, 256) 0 ['relu26[0][0]']
conv36 (Conv2D) (None, 14, 14, 256) 590080 ['pad8[0][0]']
bn24 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv36[0][0]']
relu27 (Activation) (None, 14, 14, 256) 0 ['bn24[0][0]']
conv37 (Conv2D) (None, 14, 14, 1024 263168 ['relu27[0][0]']
)
conv38 (Conv2D) (None, 14, 14, 1024 1049600 ['add8[0][0]']
)
add9 (Add) (None, 14, 14, 1024 0 ['conv37[0][0]',
) 'conv38[0][0]']
bn25 (BatchNormalization) (None, 14, 14, 1024 4096 ['add9[0][0]']
)
relu28 (Activation) (None, 14, 14, 1024 0 ['bn25[0][0]']
)
conv39 (Conv2D) (None, 14, 14, 256) 262400 ['relu28[0][0]']
bn26 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv39[0][0]']
relu29 (Activation) (None, 14, 14, 256) 0 ['bn26[0][0]']
pad9 (ZeroPadding2D) (None, 16, 16, 256) 0 ['relu29[0][0]']
conv40 (Conv2D) (None, 14, 14, 256) 590080 ['pad9[0][0]']
bn27 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv40[0][0]']
relu30 (Activation) (None, 14, 14, 256) 0 ['bn27[0][0]']
conv41 (Conv2D) (None, 14, 14, 1024 263168 ['relu30[0][0]']
)
conv42 (Conv2D) (None, 14, 14, 1024 1049600 ['add9[0][0]']
)
add10 (Add) (None, 14, 14, 1024 0 ['conv41[0][0]',
) 'conv42[0][0]']
bn28 (BatchNormalization) (None, 14, 14, 1024 4096 ['add10[0][0]']
)
relu31 (Activation) (None, 14, 14, 1024 0 ['bn28[0][0]']
)
conv43 (Conv2D) (None, 14, 14, 256) 262400 ['relu31[0][0]']
bn29 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv43[0][0]']
relu32 (Activation) (None, 14, 14, 256) 0 ['bn29[0][0]']
pad10 (ZeroPadding2D) (None, 16, 16, 256) 0 ['relu32[0][0]']
conv44 (Conv2D) (None, 14, 14, 256) 590080 ['pad10[0][0]']
bn30 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv44[0][0]']
relu33 (Activation) (None, 14, 14, 256) 0 ['bn30[0][0]']
conv45 (Conv2D) (None, 14, 14, 1024 263168 ['relu33[0][0]']
)
conv46 (Conv2D) (None, 14, 14, 1024 1049600 ['add10[0][0]']
)
add11 (Add) (None, 14, 14, 1024 0 ['conv45[0][0]',
) 'conv46[0][0]']
bn31 (BatchNormalization) (None, 14, 14, 1024 4096 ['add11[0][0]']
)
relu34 (Activation) (None, 14, 14, 1024 0 ['bn31[0][0]']
)
conv47 (Conv2D) (None, 14, 14, 256) 262400 ['relu34[0][0]']
bn32 (BatchNormalization) (None, 14, 14, 256) 1024 ['conv47[0][0]']
relu35 (Activation) (None, 14, 14, 256) 0 ['bn32[0][0]']
pad11 (ZeroPadding2D) (None, 16, 16, 256) 0 ['relu35[0][0]']
conv48 (Conv2D) (None, 7, 7, 256) 590080 ['pad11[0][0]']
bn33 (BatchNormalization) (None, 7, 7, 256) 1024 ['conv48[0][0]']
relu36 (Activation) (None, 7, 7, 256) 0 ['bn33[0][0]']
conv50 (MaxPooling2D) (None, 7, 7, 1024) 0 ['add11[0][0]']
conv49 (Conv2D) (None, 7, 7, 1024) 263168 ['relu36[0][0]']
conv51 (Conv2D) (None, 7, 7, 1024) 1049600 ['conv50[0][0]']
add12 (Add) (None, 7, 7, 1024) 0 ['conv49[0][0]',
'conv51[0][0]']
bn34 (BatchNormalization) (None, 7, 7, 1024) 4096 ['add12[0][0]']
relu37 (Activation) (None, 7, 7, 1024) 0 ['bn34[0][0]']
conv52 (Conv2D) (None, 7, 7, 512) 524800 ['relu37[0][0]']
bn35 (BatchNormalization) (None, 7, 7, 512) 2048 ['conv52[0][0]']
relu38 (Activation) (None, 7, 7, 512) 0 ['bn35[0][0]']
pad12 (ZeroPadding2D) (None, 9, 9, 512) 0 ['relu38[0][0]']
conv53 (Conv2D) (None, 7, 7, 512) 2359808 ['pad12[0][0]']
bn36 (BatchNormalization) (None, 7, 7, 512) 2048 ['conv53[0][0]']
relu39 (Activation) (None, 7, 7, 512) 0 ['bn36[0][0]']
conv54 (Conv2D) (None, 7, 7, 2048) 1050624 ['relu39[0][0]']
conv55 (Conv2D) (None, 7, 7, 2048) 2099200 ['add12[0][0]']
add13 (Add) (None, 7, 7, 2048) 0 ['conv54[0][0]',
'conv55[0][0]']
bn37 (BatchNormalization) (None, 7, 7, 2048) 8192 ['add13[0][0]']
relu40 (Activation) (None, 7, 7, 2048) 0 ['bn37[0][0]']
conv56 (Conv2D) (None, 7, 7, 512) 1049088 ['relu40[0][0]']
bn38 (BatchNormalization) (None, 7, 7, 512) 2048 ['conv56[0][0]']
relu41 (Activation) (None, 7, 7, 512) 0 ['bn38[0][0]']
pad13 (ZeroPadding2D) (None, 9, 9, 512) 0 ['relu41[0][0]']
conv57 (Conv2D) (None, 7, 7, 512) 2359808 ['pad13[0][0]']
bn39 (BatchNormalization) (None, 7, 7, 512) 2048 ['conv57[0][0]']
relu42 (Activation) (None, 7, 7, 512) 0 ['bn39[0][0]']
conv58 (Conv2D) (None, 7, 7, 2048) 1050624 ['relu42[0][0]']
conv59 (Conv2D) (None, 7, 7, 2048) 4196352 ['add13[0][0]']
add14 (Add) (None, 7, 7, 2048) 0 ['conv58[0][0]',
'conv59[0][0]']
bn40 (BatchNormalization) (None, 7, 7, 2048) 8192 ['add14[0][0]']
relu43 (Activation) (None, 7, 7, 2048) 0 ['bn40[0][0]']
conv60 (Conv2D) (None, 7, 7, 512) 1049088 ['relu43[0][0]']
bn41 (BatchNormalization) (None, 7, 7, 512) 2048 ['conv60[0][0]']
relu44 (Activation) (None, 7, 7, 512) 0 ['bn41[0][0]']
pad14 (ZeroPadding2D) (None, 9, 9, 512) 0 ['relu44[0][0]']
conv61 (Conv2D) (None, 7, 7, 512) 2359808 ['pad14[0][0]']
bn42 (BatchNormalization) (None, 7, 7, 512) 2048 ['conv61[0][0]']
relu45 (Activation) (None, 7, 7, 512) 0 ['bn42[0][0]']
conv62 (Conv2D) (None, 7, 7, 2048) 1050624 ['relu45[0][0]']
conv63 (Conv2D) (None, 7, 7, 2048) 4196352 ['add14[0][0]']
add15 (Add) (None, 7, 7, 2048) 0 ['conv62[0][0]',
'conv63[0][0]']
bn43 (BatchNormalization) (None, 7, 7, 2048) 8192 ['add15[0][0]']
relu46 (Activation) (None, 7, 7, 2048) 0 ['bn43[0][0]']
global_average_pooling2d (Glob (None, 2048) 0 ['relu46[0][0]']
alAveragePooling2D)
flatten (Flatten) (None, 2048) 0 ['global_average_pooling2d[0][0]'
]
fc1000 (Dense) (None, 4) 8196 ['flatten[0][0]']
==================================================================================================
Total params: 35,969,668
Trainable params: 35,927,172
Non-trainable params: 42,496
__________________________________________________________________________________________________
(三)总结
结果不是很理想,网络结构应该还有瑕疵。后续优化代码解决拟合问题。
resnet50v2的详细网络结构: