【连载19】GoogLeNet Inception V4/ResNet V1/V2-3.9

2020-03-11 15:17:34 浏览数 (1)

这三种结构在《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》一文中提出,论文的亮点是:提出了效果更好的GoogLeNet Inception v4网络结构;与残差网络融合,提出效果不逊于v4但训练速度更快的结构。

GoogLeNet Inception V4网络结构

GoogLeNet Inception ResNet网络结构

代码实践

GoogLeNet Inception ResNet V2

代码语言:javascript复制
# -*- coding: utf-8 -*-
import numpy as np
from keras.layers import Input, merge, Dropout, Dense, Lambda, Flatten, Activation
from keras.layers.convolutional import MaxPooling2D, Conv2D, AveragePooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.merge import concatenate, add
from keras.regularizers import l1_l2
from keras.models import Model
from keras.callbacks import CSVLogger, ReduceLROnPlateau, ModelCheckpoint, 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')
from keras.utils.vis_utils import plot_model
import os
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import np_utils
from keras.datasets import cifar10
from keras import backend as K
import tensorflow as tf
tf.python.control_flow_ops = tf
import warnings
warnings.filterwarnings('ignore')
filter_control = 8
def bn_relu(input):
    """Helper to build a BN -> relu block
    """
    norm = BatchNormalization()(input)
    return Activation("relu")(norm)
def inception_resnet_stem(input_shape, small_mode=False):
    input_layer = input_shape
    if small_mode:
        strides = (1, 1)
    else:
        strides = (2, 2)
    stem_conv1_3x3 = Conv2D(name="stem_conv1_3x3/2",
                            filters=32 // filter_control,
                            kernel_size=(3, 3),
                            strides=strides,
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(input_layer)
    stem_conv2_3x3 = Conv2D(name="stem_conv2_3x3/1",
                            filters=32 // filter_control,
                            kernel_size=(3, 3),
                            strides=(1, 1),
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_conv1_3x3)
    stem_conv3_3x3 = Conv2D(name="stem_conv3_3x3/1",
                            filters=64 // filter_control,
                            kernel_size=(3, 3),
                            strides=(1, 1),
                            padding='same',
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_conv2_3x3)
    stem_pool1_3x3 = MaxPooling2D(name="stem_pool1_3x3/2",
                                  pool_size=(3, 3),
                                  strides=strides,
                                  padding='valid')(stem_conv3_3x3)
    stem_conv4_3x3 = Conv2D(name="stem_conv4_3x3/2",
                            filters=96 // filter_control,
                            kernel_size=(3, 3),
                            strides=strides,
                            padding='valid',
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_conv3_3x3)
    stem_merge1 = concatenate([stem_pool1_3x3, stem_conv4_3x3])
    stem_conv5_1x1 = Conv2D(name="stem_conv5_1x1/1",
                            filters=64 // filter_control,
                            kernel_size=(1, 1),
                            strides=(1, 1),
                            padding='same',
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_merge1)
    stem_conv6_3x3 = Conv2D(name="stem_conv6_3x3/1",
                            filters=96 // filter_control,
                            kernel_size=(3, 3),
                            strides=(1, 1),
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_conv5_1x1)
    stem_conv7_1x1 = Conv2D(name="stem_conv7_1x1/1",
                            filters=64 // filter_control,
                            kernel_size=(1, 1),
                            strides=(1, 1),
                            padding='same',
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_merge1)
    stem_conv8_7x1 = Conv2D(name="stem_conv8_7x1/1",
                            filters=64 // filter_control,
                            kernel_size=(7, 1),
                            strides=(1, 1),
                            padding='same',
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_conv7_1x1)
    stem_conv9_1x7 = Conv2D(name="stem_conv8_1x7/1",
                            filters=64 // filter_control,
                            kernel_size=(1, 7),
                            strides=(1, 1),
                            padding='same',
                            kernel_initializer='he_normal',
                            activation='relu',
                            kernel_regularizer=l1_l2(0.0001))(stem_conv8_7x1)
    stem_conv10_3x3 = Conv2D(name="stem_conv10_3x3/1",
                             filters=96 // filter_control,
                             kernel_size=(3, 3),
                             strides=(1, 1),
                             padding='valid',
                             kernel_initializer='he_normal',
                             activation='relu',
                             kernel_regularizer=l1_l2(0.0001))(stem_conv9_1x7)
    stem_merge2 = concatenate([stem_conv6_3x3, stem_conv10_3x3])
    stem_pool2_3x3 = MaxPooling2D(name="stem_pool2_3x3/2",
                                  pool_size=(3, 3),
                                  strides=strides,
                                  padding='valid')(stem_merge2)
    stem_conv11_3x3 = Conv2D(name="stem_conv11_3x3/2",
                             filters=192 // filter_control,
                             kernel_size=(3, 3),
                             strides=strides,
                             padding='valid',
                             kernel_initializer='he_normal',
                             activation='relu',
                             kernel_regularizer=l1_l2(0.0001))(stem_merge2)
    stem_merge3 = concatenate([stem_pool2_3x3, stem_conv11_3x3])
    return bn_relu(stem_merge3)
def inception_resnet_v2_A(i, input):
    # 输入是一个ReLU激活
    init = input
    inception_A_conv1_1x1 = Conv2D(name="inception_A_conv1_1x1/1"   i,
                                   filters=32 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   kernel_initializer='he_normal',
                                   activation='relu',
                                   kernel_regularizer=l1_l2(0.0001))(input)
    inception_A_conv2_1x1 = Conv2D(name="inception_A_conv2_1x1/1"   i,
                                   filters=32 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   kernel_initializer='he_normal',
                                   activation='relu',
                                   kernel_regularizer=l1_l2(0.0001))(input)
    inception_A_conv3_3x3 = Conv2D(name="inception_A_conv3_3x3/1"   i,
                                   filters=32 // filter_control,
                                   kernel_size=(3, 3),
                                   strides=(1, 1),
                                   padding='same',
                                   kernel_initializer='he_normal',
                                   activation='relu',
                                   kernel_regularizer=l1_l2(0.0001))(inception_A_conv2_1x1)
    inception_A_conv4_1x1 = Conv2D(name="inception_A_conv4_1x1/1"   i,
                                   filters=32 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   kernel_initializer='he_normal',
                                   activation='relu',
                                   kernel_regularizer=l1_l2(0.0001))(input)
    inception_A_conv5_3x3 = Conv2D(name="inception_A_conv5_3x3/1"   i,
                                   filters=48 // filter_control,
                                   kernel_size=(3, 3),
                                   strides=(1, 1),
                                   padding='same',
                                   kernel_initializer='he_normal',
                                   activation='relu',
                                   kernel_regularizer=l1_l2(0.0001))(inception_A_conv4_1x1)
    inception_A_conv6_3x3 = Conv2D(name="inception_A_conv6_3x3/1"   i,
                                   filters=64 // filter_control,
                                   kernel_size=(3, 3),
                                   strides=(1, 1),
                                   padding='same',
                                   kernel_initializer='he_normal',
                                   activation='relu',
                                   kernel_regularizer=l1_l2(0.0001))(inception_A_conv5_3x3)
    inception_merge1 = concatenate([inception_A_conv1_1x1, inception_A_conv3_3x3, inception_A_conv6_3x3])
    inception_A_conv7_1x1 = Conv2D(name="inception_A_conv7_1x1/1"   i,
                                   filters=384 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='linear')(inception_merge1)
    out = add([input, inception_A_conv7_1x1])
    return bn_relu(out)
def inception_resnet_v2_B(i, input):
    # 输入是一个ReLU激活
    init = input
    inception_B_conv1_1x1 = Conv2D(name="inception_B_conv1_1x1/1"   i,
                                   filters=192 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    inception_B_conv2_1x1 = Conv2D(name="inception_B_conv2_1x1/1"   i,
                                   filters=128 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    inception_B_conv3_1x7 = Conv2D(name="inception_B_conv3_1x7/1"   i,
                                   filters=160 // filter_control,
                                   kernel_size=(1, 7),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(inception_B_conv2_1x1)
    inception_B_conv4_7x1 = Conv2D(name="inception_B_conv4_7x1/1"   i,
                                   filters=192 // filter_control,
                                   kernel_size=(7, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(inception_B_conv3_1x7)
    inception_B_merge = concatenate([inception_B_conv1_1x1, inception_B_conv4_7x1])
    inception_B_conv7_1x1 = Conv2D(name="inception_B_conv7_1x1/1"   i,
                                   filters=1154 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='linear')(inception_B_merge)
    out = add([input, inception_B_conv7_1x1])
    return bn_relu(out)
def inception_resnet_v2_C(i, input):
    # 输入是一个ReLU激活
    inception_C_conv1_1x1 = Conv2D(name="inception_C_conv1_1x1/1"   i,
                                   filters=192 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    inception_C_conv2_1x1 = Conv2D(name="inception_C_conv2_1x1/1"   i,
                                   filters=192 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    inception_C_conv3_1x3 = Conv2D(name="inception_C_conv3_1x3/1"   i,
                                   filters=224 // filter_control,
                                   kernel_size=(1, 3),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(inception_C_conv2_1x1)
    inception_C_conv3_3x1 = Conv2D(name="inception_C_conv3_3x1/1"   i,
                                   filters=256 // filter_control,
                                   kernel_size=(3, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(inception_C_conv3_1x3)
    ir_merge = concatenate([inception_C_conv1_1x1, inception_C_conv3_3x1])
    inception_C_conv4_1x1 = Conv2D(name="inception_C_conv4_1x1/1"   i,
                                   filters=2048 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='linear')(ir_merge)
    out = add([input, inception_C_conv4_1x1])
    return bn_relu(out)
def reduction_A(input, k=192, l=224, m=256, n=384):
    pool_size = (3, 3)
    strides = (2, 2)
    reduction_A_pool1 = MaxPooling2D(name="reduction_A_pool1/2",
                                     pool_size=pool_size,
                                     strides=strides,
                                     padding='valid')(input)
    reduction_A_conv1_3x3 = Conv2D(name="reduction_A_conv1_3x3/1",
                                   filters=n // filter_control,
                                   kernel_size=pool_size,
                                   strides=strides,
                                   activation='relu')(input)
    reduction_A_conv2_1x1 = Conv2D(name="reduction_A_conv2_1x1/1",
                                   filters=k // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    reduction_A_conv2_3x3 = Conv2D(name="reduction_A_conv2_3x3/1",
                                   filters=l // filter_control,
                                   kernel_size=(3, 3),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(reduction_A_conv2_1x1)
    reduction_A_conv3_3x3 = Conv2D(name="reduction_A_conv3_3x3/1",
                                   filters=m // filter_control,
                                   kernel_size=pool_size,
                                   strides=strides,
                                   activation='relu')(reduction_A_conv2_3x3)
    reduction_A_merge = concatenate([reduction_A_pool1, reduction_A_conv1_3x3, reduction_A_conv3_3x3])
    return reduction_A_merge
def reduction_B(input):
    pool_size = (3, 3)
    strides = (2, 2)
    reduction_B_pool1 = MaxPooling2D(name="reduction_B_pool1/2",
                                     pool_size=pool_size,
                                     strides=strides,
                                     padding='valid')(input)
    reduction_B_conv1_1x1 = Conv2D(name="reduction_B_conv3_3x3/1",
                                   filters=256 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    reduction_B_conv2_3x3 = Conv2D(name="reduction_B_conv2_3x3/1",
                                   filters=288 // filter_control,
                                   kernel_size=pool_size,
                                   strides=strides,
                                   activation='relu')(reduction_B_conv1_1x1)
    reduction_B_conv3_1x1 = Conv2D(name="reduction_B_conv3_1x1/1",
                                   filters=256 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    reduction_B_conv4_3x3 = Conv2D(name="reduction_B_conv4_3x3/1",
                                   filters=288 // filter_control,
                                   kernel_size=pool_size,
                                   strides=strides,
                                   activation='relu')(reduction_B_conv3_1x1)
    reduction_B_conv5_1x1 = Conv2D(name="reduction_B_conv5_1x1/1",
                                   filters=256 // filter_control,
                                   kernel_size=(1, 1),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(input)
    reduction_B_conv5_3x3 = Conv2D(name="reduction_B_conv5_3x3/1",
                                   filters=288 // filter_control,
                                   kernel_size=(3, 3),
                                   strides=(1, 1),
                                   padding='same',
                                   activation='relu')(reduction_B_conv5_1x1)
    reduction_B_conv6_3x3 = Conv2D(name="reduction_B_conv6_3x3/1",
                                   filters=320 // filter_control,
                                   kernel_size=pool_size,
                                   strides=strides,
                                   activation='relu')(reduction_B_conv5_3x3)
    reduction_B_merge = concatenate(
        [reduction_B_pool1, reduction_B_conv2_3x3, reduction_B_conv4_3x3, reduction_B_conv6_3x3])
    return reduction_B_merge
def create_inception_resnet_v2(input_shape, nb_classes=10, small_mode=False):
    input_layer = Input(input_shape)
    x = inception_resnet_stem(input_layer, small_mode)
    # 10 x Inception Resnet A
    for i in range(10):
        x = inception_resnet_v2_A(str(i), x)
    # Reduction A
    x = reduction_A(x, k=256, l=256, m=384, n=384)
    # 20 x Inception Resnet B
    for i in range(20):
        x = inception_resnet_v2_B(str(i), x)
    # 对32*32*3的数据可以更改pooling层
    aout = AveragePooling2D((5, 5), strides=(3, 3))(x)
    aout = Conv2D(name="conv1_1x1/1",
                  filters=128,
                  kernel_size=(1, 1),
                  strides=(1, 1),
                  padding='same',
                  activation='relu')(aout)
    aout = Conv2D(name="conv1_5x5/1",
                  filters=768,
                  kernel_size=(5, 5),
                  strides=(1, 1),
                  padding='same',
                  activation='relu')(aout)
    aout = Flatten()(aout)
    aout = Dense(nb_classes, activation='softmax')(aout)
    # Reduction Resnet B
    x = reduction_B(x)
    # 10 x Inception Resnet C
    for i in range(10):
        x = inception_resnet_v2_C(str(i), x)
    # 需要视情况更改
    x = AveragePooling2D((4, 4), strides=(1, 1))(x)
    # Dropout
    x = Dropout(0.8)(x)
    x = Flatten()(x)
    # Output
    out = Dense(output_dim=nb_classes, activation='softmax')(x)
    # 简单起见去掉附加目标函数
    # model = Model(input_layer, output=[out, aout], name='Inception-Resnet-v2')
    model = Model(input_layer, output=out, name='Inception-Resnet-v2')
    return model
if __name__ == "__main__":
    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()
        # reorder dimensions for tensorflow
        x_train = np.transpose(x_train.astype('float32') / 255., (0, 1, 2, 3))
        x_test = np.transpose(x_test.astype('float32') / 255., (0, 1, 2, 3))
        print('x_train shape:', x_train.shape)
        print(x_train.shape[0], 'train samples')
        print(x_test.shape[0], 'test samples')
        # convert class vectors to binary class matrices
        y_train = np_utils.to_categorical(y_train)
        y_test = np_utils.to_categorical(y_test)
        s = x_train.shape[1:]
        batch_size = 128
        nb_epoch = 10
        nb_classes = 10
        model = create_inception_resnet_v2(s, nb_classes, False, True)
        model.summary()
        plot_model(model, to_file="GoogLeNet-Inception-Resnet-V2.jpg", show_shapes=True)
        model.compile(optimizer='adadelta',
                      loss='categorical_crossentropy',
                      metrics=['accuracy'])
        # Model saving callback
        checkpointer = ModelCheckpoint("weights-improvement-{epoch:02d}-{val_acc:.2f}.hdf5", monitor='val_loss',
                                       verbose=0,
                                       save_best_only=False, save_weights_only=False, mode='auto')
        print('Using real-time data augmentation.')
        datagen_train = ImageDataGenerator(
            featurewise_center=False,
            samplewise_center=False,
            featurewise_std_normalization=False,
            samplewise_std_normalization=False,
            zca_whitening=False,
            rotation_range=0,
            width_shift_range=0.125,
            height_shift_range=0.125,
            horizontal_flip=True,
            vertical_flip=False)
        datagen_train.fit(x_train)
        history = model.fit_generator(datagen_train.flow(x_train, y_train, batch_size=batch_size, shuffle=True),
                                      samples_per_epoch=x_train.shape[0],
                                      nb_epoch=nb_epoch, verbose=1,
                                      validation_data=(x_test, y_test),
                                      callbacks=[lr_reducer, early_stopper, csv_logger, checkpointer])

‍‍‍‍‍‍

0 人点赞