深度学习–ResNet练习
练习6
时间:2020.8.22
昂:
-
BasicBlock:
- conv1 + bn1 + relu
- conv2 + bn2
- Identity 注意维度一致
-
build_resblock:
- 第一个BasicBlock: 给一个下采样功能
- 其他的BasicBlock: 不进行下采样功能
-
ResNet:
- 一个根部: 第一层
- resblock堆叠: 根据不同的ResNet给予不同的layer_dims进行堆叠
- 分类的fc: h, w 未知搞个均值拉好
-
网络:
- init: 写结构
- cell: 给数据, 用结构返回输出
- 重复的分块
-
resnet18:
-
resnet34:
Something:
也许少了点什么,待补0.0
代码:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, Sequential
class BasicBlock(layers.Layer):
# filter_num: 卷积核的数量,和channel一个意思
def __init__(self, filter_num, stride=1):
super(BasicBlock, self).__init__()
# 第一层:
self.conv1 = layers.Conv2D(filter_num, (3, 3), strides=stride, padding='same')
# http://blog.sina.com.cn/s/blog_628cc2b70102yg6w.html
self.bn1 = layers.BatchNormalization()
self.relu = layers.Activation('relu')
# 第二层:
self.conv2 = layers.Conv2D(filter_num, (3, 3), strides=1, padding='same')
self.bn2 = layers.BatchNormalization()
# Identity 注意保持维度一致
if stride != 1:
self.downsample = Sequential()
self.downsample.add(layers.Conv2D(filter_num, (1, 1), strides=stride)) # w,h,通道数一致
else:
self.downsample = lambda x:x
def call(self, inputs, training=None):
# [b, h, w, c]
out = self.conv1(inputs)
out = self.bn1(out,training=training)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out,training=training)
identity = self.downsample(inputs)
output = layers.add([out, identity])
output = tf.nn.relu(output)
return output
class ResNet(keras.Model):
def __init__(self, layer_dims, num_classes=100): # [2, 2, 2, 2]
super(ResNet, self).__init__()
# 根部:
self.stem = Sequential([layers.Conv2D(64, (3, 3), strides=(1, 1)),
layers.BatchNormalization(),
layers.Activation('relu'),
layers.MaxPool2D(pool_size=(2, 2), strides=(1, 1), padding='same')
])
self.layer1 = self.build_resblock(64, layer_dims[0])
self.layer2 = self.build_resblock(128, layer_dims[1], stride=2)
self.layer3 = self.build_resblock(256, layer_dims[2], stride=2)
self.layer4 = self.build_resblock(512, layer_dims[3], stride=2)
# output: [b, 512, h, w] => [b, 512, 1, 1], 无论h,w是多少,在每个channel所有像素值加起来做一个均值
self.avgpool = layers.GlobalAveragePooling2D()
# 分类:
self.fc = layers.Dense(num_classes)
def call(self, inputs, training=None):
x = self.stem(inputs,training=training)
x = self.layer1(x,training=training)
x = self.layer2(x,training=training)
x = self.layer3(x,training=training)
x = self.layer4(x,training=training)
# [b, c]
x = self.avgpool(x)
# [b, 100]
x = self.fc(x)
return x
# blocks: 一个resblock 由几个 BasicBlock 堆叠
def build_resblock(self, filter_num, blocks, stride=1):
#给第一个block进行下采样功能
res_blocks = Sequential()
# may down sample
res_blocks.add(BasicBlock(filter_num, stride))
#其他的不进行下采样功能
for _ in range(1, blocks):
res_blocks.add(BasicBlock(filter_num, stride=1))
return res_blocks
def resnet18():
return ResNet([2, 2, 2, 2])
def resnet34():
return ResNet([3, 4, 6, 3])