Residual net概念
概念:
Residual net(殘差網絡):將靠前若干層的某一層數據輸出直接跳過多層引入到后面數據層的輸入 部分。
殘差神經單元:假定某段神經網絡的輸入是x,期望輸出是H(x),如果我們直接將輸入x傳到輸出作 為初始結果,那么我們需要學習的目標就是F(x) = H(x) - x,這就是一個殘差神經單元,相當于將 學習目標改變了,不再是學習一個完整的輸出H(x),只是輸出和輸入的差別 H(x) - x ,即殘差。
細節:
? 普通的直連的卷積神經網絡和ResNet的最大區別在 于,ResNet有很多旁路的支線將輸入直接連到后面 的層,使得后面的層可以直接學習殘差,這種結構也 被稱為shortcut或skip connections。
? 傳統的卷積層或全連接層在信息傳遞時,或多或少會 存在信息丟失、損耗等問題。ResNet在某種程度上 解決了這個問題,通過直接將輸入信息繞道傳到輸出, 保護信息的完整性,整個網絡只需要學習輸入、輸出 差別的那一部分,簡化了學習目標和難度。
思路:
ResNet50有兩個基本的塊,分別名為Conv Block和Identity Block,其中Conv Block輸入和輸出的維度 是不一樣的,所以不能連續串聯,它的作用是改變網絡的維度;Identity Block輸入維度和輸出維度相 同,可以串聯,用于加深網絡的。
resent50代碼實現:
網絡主體部分:
#-------------------------------------------------------------#
# ResNet50的網絡部分
#-------------------------------------------------------------#
from __future__ import print_functionimport numpy as np
from keras import layersfrom keras.layers import Input
from keras.layers import Dense,Conv2D,MaxPooling2D,ZeroPadding2D,AveragePooling2D
from keras.layers import Activation,BatchNormalization,Flatten
from keras.models import Modelfrom keras.preprocessing import image
import keras.backend as K
from keras.utils.data_utils import get_file
from keras_applications.imagenet_utils import decode_predictions
from keras_applications.imagenet_utils import preprocess_inputdef identity_block(input_tensor, kernel_size, filters, stage, block):filters1, filters2, filters3 = filtersconv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Conv2D(filters2, kernel_size,padding='same', name=conv_name_base + '2b')(x)x = BatchNormalization(name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)x = BatchNormalization(name=bn_name_base + '2c')(x)x = layers.add([x, input_tensor])x = Activation('relu')(x)return xdef conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):filters1, filters2, filters3 = filtersconv_name_base = 'res' + str(stage) + block + '_branch'bn_name_base = 'bn' + str(stage) + block + '_branch'x = Conv2D(filters1, (1, 1), strides=strides,name=conv_name_base + '2a')(input_tensor)x = BatchNormalization(name=bn_name_base + '2a')(x)x = Activation('relu')(x)x = Conv2D(filters2, kernel_size, padding='same',name=conv_name_base + '2b')(x)x = BatchNormalization(name=bn_name_base + '2b')(x)x = Activation('relu')(x)x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)x = BatchNormalization(name=bn_name_base + '2c')(x)shortcut = Conv2D(filters3, (1, 1), strides=strides,name=conv_name_base + '1')(input_tensor)shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut)x = layers.add([x, shortcut])x = Activation('relu')(x)return xdef ResNet50(input_shape=[224,224,3],classes=1000):img_input = Input(shape=input_shape)x = ZeroPadding2D((3, 3))(img_input)x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)x = BatchNormalization(name='bn_conv1')(x)x = Activation('relu')(x)x = MaxPooling2D((3, 3), strides=(2, 2))(x)x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')x = AveragePooling2D((7, 7), name='avg_pool')(x)x = Flatten()(x)x = Dense(classes, activation='softmax', name='fc1000')(x)model = Model(img_input, x, name='resnet50')model.load_weights("resnet50_weights_tf_dim_ordering_tf_kernels.h5")return modelif __name__ == '__main__':model = ResNet50()model.summary()img_path = 'elephant.jpg'# img_path = 'bike.jpg'img = image.load_img(img_path, target_size=(224, 224))x = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)print('Input image shape:', x.shape)preds = model.predict(x)print('Predicted:', decode_predictions(preds))