有任何问题欢迎在下面留言
本篇文章的代码运行界面均在Jupyter Notebook中进行
本篇文章配套的代码资源已经上传
Resnet实战1
Resnet实战2
Resnet实战3
def get_model():
model = resnet50.ResNet50()
if config.model == "resnet34":
model = resnet34.ResNet34()
if config.model == "resnet101":
model = resnet101.ResNet101()
if config.model == "resnet152":
model = resnet152.ResNet152()
model.build(input_shape=(None, config.image_height, config.image_width, config.channels))
model.summary()
tf.keras.utils.plot_model(model, to_file='model.png')
return model
# create model
model = get_model()
调用get_model()函数构建模型
get_model()函数:
import tensorflow as tf
from models.residual_block import build_res_block_2
from config import NUM_CLASSES
class ResNet50(tf.keras.Model):
def __init__(self, num_classes=NUM_CLASSES):
super(ResNet50, self).__init__()
self.pre1 = tf.keras.layers.Conv2D(filters=64, kernel_size=(7, 7), strides=2, padding='same')
self.pre2 = tf.keras.layers.BatchNormalization()
self.pre3 = tf.keras.layers.Activation(tf.keras.activations.relu)
self.pre4 = tf.keras.layers.MaxPool2D(pool_size=(3, 3), strides=2)
self.layer1 = build_res_block_2(filter_num=64, blocks=3)
self.layer2 = build_res_block_2(filter_num=128, blocks=4, stride=2)
self.layer3 = build_res_block_2(filter_num=256, blocks=6, stride=2)
self.layer4 = build_res_block_2(filter_num=512, blocks=3, stride=2)
self.avgpool = tf.keras.layers.GlobalAveragePooling2D()
self.fc1 = tf.keras.layers.Dense(units=1000, activation=tf.keras.activations.relu)
self.drop_out = tf.keras.layers.Dropout(rate=0.5)
self.fc2 = tf.keras.layers.Dense(units=num_classes, activation=tf.keras.activations.softmax)
def call(self, inputs, training=None, mask=None):
pre1 = self.pre1(inputs)
pre2 = self.pre2(pre1, training=training)
pre3 = self.pre3(pre2)
pre4 = self.pre4(pre3)
l1 = self.layer1(pre4, training=training)
l2 = self.layer2(l1, training=training)
l3 = self.layer3(l2, training=training)
l4 = self.layer4(l3, training=training)
avgpool = self.avgpool(l4)
fc1 = self.fc1(avgpool)
drop = self.drop_out(fc1)
out = self.fc2(drop)
return out
class ResNet50(tf.keras.Model),这个类定义了ResNet50模型的结构,以及前向传播的方式、顺序
ResNet50类解析:
class BottleNeck(tf.keras.layers.Layer):
def __init__(self, filter_num, stride=1,with_downsample=True):
super(BottleNeck, self).__init__()
self.with_downsample = with_downsample
self.conv1 = tf.keras.layers.Conv2D(filters=filter_num, kernel_size=(1, 1), strides=1, padding='same')
self.bn1 = tf.keras.layers.BatchNormalization()
self.conv2 = tf.keras.layers.Conv2D(filters=filter_num, kernel_size=(3, 3), strides=stride, padding='same')
self.bn2 = tf.keras.layers.BatchNormalization()
self.conv3 = tf.keras.layers.Conv2D(filters=filter_num * 4, kernel_size=(1, 1), strides=1, padding='same')
self.bn3 = tf.keras.layers.BatchNormalization()
self.downsample = tf.keras.Sequential()
self.downsample.add(tf.keras.layers.Conv2D(filters=filter_num * 4, kernel_size=(1, 1), strides=stride))
self.downsample.add(tf.keras.layers.BatchNormalization())
def call(self, inputs, training=None):
identity = self.downsample(inputs)
conv1 = self.conv1(inputs)
bn1 = self.bn1(conv1, training=training)
relu1 = tf.nn.relu(bn1)
conv2 = self.conv2(relu1)
bn2 = self.bn2(conv2, training=training)
relu2 = tf.nn.relu(bn2)
conv3 = self.conv3(relu2)
bn3 = self.bn3(conv3, training=training)
if self.with_downsample == True:
output = tf.nn.relu(tf.keras.layers.add([identity, bn3]))
else:
output = tf.nn.relu(tf.keras.layers.add([inputs, bn3]))
return output
BottleNeck类解析:
self.downsample
),这个层是一个包含卷积层和批量归一化的 Sequential
模型,用于匹配输入和残差的维度identity
)与最后一个卷积层的输出(bn3
)相加inputs
)与最后一个卷积层的输出(bn3
)相加def build_res_block_2(filter_num, blocks, stride=1):
res_block = tf.keras.Sequential()
res_block.add(BottleNeck(filter_num, stride=stride))
for _ in range(1, blocks):
res_block.add(BottleNeck(filter_num, stride=1,with_downsample=False))
return res_block
build_res_block_2函数解析:
Resnet实战1
Resnet实战2
Resnet实战3