【连载15】Residual Networks、Maxout Networks和Network in Network
ResNet产生的动机
恒等映射
模型集成角度看残差网络
残差网络中的短路径
代码实践
# -*- coding: utf-8 -*-
from keras import backend as K
from keras.layers.merge import add
from keras.layers import Input, Activation, Dense, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D, AveragePooling2D
from keras.layers.normalization import BatchNormalization
from keras.regularizers import l1_l2
from keras.models import Model
class ResNet(object):
'''残差网络基本模块定义'''
name = 'resnet'
def __init__(self, n):
self.name = n
def bn_relu(self, input):
'''构建propoesd残差block中BN与ReLU子结构,针对tensorflow'''
normalize = BatchNormalization(axis=3)(input)
return Activation("relu")(normalize)
def bn_relu_weight(self, filters, kernel_size, strides):
'''构建propoesd残差block中BN->ReLu->Weight的子结构'''
def inner_func(input):
act = self.bn_relu(input)
conv = Conv2D(filters=filters,
kernel_size=kernel_size,
strides=strides,
padding='same',
kernel_initializer='he_normal',
kernel_regularizer=l1_l2(0.0001))(act)
return conv
return inner_func
def weight_bn_relu(self, filters, kernel_size, strides):
'''构建propoesd残差block中BN->ReLu->Weight的子结构'''
def inner_func(input):
return self.bn_relu(Conv2D(filters=filters,
kernel_size=kernel_size,
strides=strides,
padding='same',
kernel_initializer='he_normal',
kernel_regularizer=l1_l2(0.0001))(input))
return inner_func
def shortcut(self, left, right):
'''构建propoesd残差block中恒等映射的子结构,分两种情况,输入、输出维度一致&维度不一致'''
left_shape = K.int_shape(left)
right_shape = K.int_shape(right)
stride_width = int(round(left_shape[1] / right_shape[1]))
stride_height = int(round(left_shape[2] / right_shape[2]))
equal_channels = left_shape[3] == right_shape[3]
x_l = left
# 如果输入输出维度不一致需要通过映射变一致,否则一致则返回单位矩阵,这个映射发生在两个不同维度block之间(论文中虚线部分)
if left_shape != right_shape:
x_l = Conv2D(filters=right_shape[3],
kernel_size=(1, 1),
strides=(int(round(left_shape[1] / right_shape[1])),
int(round(left_shape[2] / right_shape[2]))),
padding="valid",
kernel_initializer="he_normal",
kernel_regularizer=l1_l2(0.01, 0.0001))(left)
x_l_1 = add([x_l, right])
return x_l_1
def basic_block(self, filters, strides=(1, 1), is_first_block=False):
"""34层以内的残差网络使用的block,2层一跨"""
def inner_func(input):
# 恒等映射
if not is_first_block:
conv1 = self.bn_relu_weight(filters=filters,
kernel_size=(3, 3),
strides=strides)(input)
else:
conv1 = Conv2D(filters=filters, kernel_size=(3, 3),
strides=strides,
padding="same",
kernel_initializer="he_normal",
kernel_regularizer=l1_l2(0.01, 0.0001))(input)
# 残差网络
residual = self.bn_relu_weight(filters=filters,
kernel_size=(3, 3), strides=(1, 1))(conv1)
# 构建一个两层的残差block
return self.shortcut(input, residual)
return inner_func
def residual_block(self, block_func, filters, repeat_times, is_first_block):
'''构建多层残差block'''
def inner_func(input):
for i in range(repeat_times):
# 第一个block的第一层,其输入为pooling层
if is_first_block:
strides = (1, 1)
else:
if i == 0: # 每个残差block的第一层
strides = (2, 2)
else: # 每个残差block的非第一层
strides = (1, 1)
flag = i == 0 and is_first_block
input = block_func(filters=filters,
strides=strides,
is_first_block=flag)(input)
return input
return inner_func
def residual_builder(self, input_shape, softmax_num, func_type, repeat_times):
'''指定输入、输出、残差block的类型、网络深度并构建残差网络'''
input = Input(shape=input_shape)
# 第一层为卷积层
conv1 = self.weight_bn_relu(filters=64, kernel_size=(7, 7), strides=(2, 2))(input)
# 第二层为max pooling层
pool1 = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), padding="same")(conv1)
residual_block = pool1
filters = 64
# 接着16个残差block
for i, r in enumerate(repeat_times):
if i == 0:
residual_block = self.residual_block(func_type,
filters=filters,
repeat_times=r,
is_first_block=True)(residual_block)
else:
residual_block = self.residual_block(func_type,
filters=filters,
repeat_times=r,
is_first_block=False)(residual_block)
filters *= 2
residual_block = self.bn_relu(residual_block)
shape = K.int_shape(residual_block)
# average pooling层
pool2 = AveragePooling2D(pool_size=(shape[1], shape[2]),
strides=(1, 1))(residual_block)
flatten1 = Flatten()(pool2)
# 全连接层
dense1 = Dense(units=softmax_num,
kernel_initializer="he_normal",
activation="softmax")(flatten1)
return Model(inputs=input, outputs=dense1)
resnet-cifar-10.py # -*- coding: utf-8 -*-
import numpy as np
import matplotlib
import resnet
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import os
from scipy.misc import toimage
from keras.datasets import cifar10
from keras.utils import np_utils
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ModelCheckpoint
from keras import backend as K
import tensorflow as tf
tf.python.control_flow_ops = tf
from keras.callbacks import ReduceLROnPlateau, CSVLogger, EarlyStopping
lr_reducer = ReduceLROnPlateau(monitor='val_loss', factor=np.sqrt(0.5), cooldown=0, patience=3, min_lr=1e-6)
early_stopper = EarlyStopping(monitor='val_acc', min_delta=0.0005, patience=15)
csv_logger = CSVLogger('resnet34_cifar10.csv')
def data_visualize(x, y, num):
plt.figure()
for i in range(0, num * num):
axes = plt.subplot(num, num, i + 1)
axes.set_title("label=" + str(y[i]))
axes.set_xticks([0, 10, 20, 30])
axes.set_yticks([0, 10, 20, 30])
plt.imshow(toimage(x[i]))
plt.tight_layout()
plt.savefig('sample.jpg')
if __name__ == "__main__":
from keras.utils.vis_utils import plot_model
with tf.device('/gpu:3'):
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=1, allow_growth=True)
os.environ["CUDA_VISIBLE_DEVICES"] = "3"
tf.Session(config=K.tf.ConfigProto(allow_soft_placement=True,
log_device_placement=True,
gpu_options=gpu_options))
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
data_visualize(X_train, y_train, 4)
# 定义输入数据并做归一化
dim = 32
channel = 3
class_num = 10
X_train = X_train.reshape(X_train.shape[0], dim, dim, channel).astype('float32') / 255
X_test = X_test.reshape(X_test.shape[0], dim, dim, channel).astype('float32') / 255
Y_train = np_utils.to_categorical(y_train, class_num)
Y_test = np_utils.to_categorical(y_test, class_num)
# this will do preprocessing and realtime data augmentation
datagen = ImageDataGenerator(
featurewise_center=False, # set input mean to 0 over the dataset
samplewise_center=False, # set each sample mean to 0
featurewise_std_normalization=False, # divide inputs by std of the dataset
samplewise_std_normalization=False, # divide each input by its std
zca_whitening=False, # apply ZCA whitening
rotation_range=25, # randomly rotate images in the range (degrees, 0 to 180)
width_shift_range=0.1, # randomly shift images horizontally (fraction of total width)
height_shift_range=0.1, # randomly shift images vertically (fraction of total height)
horizontal_flip=True, # randomly flip images
vertical_flip=False) # randomly flip images
datagen.fit(X_train)
s = X_train.shape[1:]
print(s)
builder = resnet.ResNet("ResNet-test")
resnet_34 = builder.residual_builder(s, class_num, builder.basic_block, [3, 4, 6, 3])
model = resnet_34
model.summary()
#import pdb
#pdb.set_trace()
plot_model(model, to_file="ResNet.jpg", show_shapes=True)
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
batch_size = 32
nb_epoch = 100
# import pdb
# pdb.set_trace()
ModelCheckpoint("weights-improvement-{epoch:02d}-{val_acc:.2f}.hdf5", monitor='val_loss', verbose=0,
save_best_only=False, save_weights_only=False, mode='auto')
model.fit_generator(datagen.flow(X_train, Y_train, batch_size=batch_size),
steps_per_epoch=X_train.shape[0],
validation_data=(X_test, Y_test),
epochs=nb_epoch,
verbose=1,
max_q_size=100,
callbacks=[lr_reducer, early_stopper, csv_logger])
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
CIFAR-10训练情况Maxout Networks
Maxout激活函数
Network in Network
NIN卷积层(MLP Convolution)
NIN抽样层(Global Average Pooling)
2.机器学习原来这么有趣!【第二章】:用机器学习制作超级马里奥的关卡
记得把公号加星标,会第一时间收到通知。
创作不易,如果觉得有点用,希望可以随手转发或者”在看“,拜谢各位老铁
赞 (0)