logo

Residual Networks (ResNet) – Deep Learning

Etter den første CNN-baserte arkitekturen (AlexNet) som vinner ImageNet 2012-konkurransen, bruker hver påfølgende vinnerarkitektur flere lag i et dypt nevralt nettverk for å redusere feilraten. Dette fungerer for mindre antall lag, men når vi øker antall lag, er det et vanlig problem i dyp læring assosiert med det som kalles Vanishing/Exploding gradient. Dette fører til at gradienten blir 0 eller for stor. Så når vi øker antall lag, øker også trenings- og testfeilfrekvensen.

Sammenligning av 20-lags vs 56-lags arkitektur



I plottet ovenfor kan vi observere at en 56-lags CNN gir mer feilrate på både trenings- og testdatasett enn en 20-lags CNN-arkitektur. Etter å ha analysert mer på feilraten, var forfatterne i stand til å konkludere med at det er forårsaket av forsvinnende/eksploderende gradient.
ResNet, som ble foreslått i 2015 av forskere ved Microsoft Research, introduserte en ny arkitektur kalt Residual Network.

Restnettverk: For å løse problemet med forsvinnende/eksploderende gradient, introduserte denne arkitekturen konseptet kalt Residual Blocks. I dette nettverket bruker vi en teknikk som heter hoppe over tilkoblinger . Hoppkoblingen kobler aktiveringer av et lag til flere lag ved å hoppe over noen lag i mellom. Dette danner en restblokk. Resnett lages ved å stable disse gjenværende blokkene sammen.
Tilnærmingen bak dette nettverket er i stedet for at lag lærer den underliggende kartleggingen, lar vi nettverket passe til gjenværende kartlegging. Så, i stedet for å si H(x), initial mapping , la nettverket passe,

 F(x) := H(x) - x  which gives H(x) := F(x) + x .>

Hopp over (snarvei) tilkobling



Fordelen med å legge til denne typen hoppforbindelse er at hvis et lag skader ytelsen til arkitekturen, vil det bli hoppet over ved regularisering. Så dette resulterer i trening av et veldig dypt nevralt nettverk uten problemene forårsaket av forsvinnende/eksploderende gradient. Forfatterne av artikkelen eksperimenterte på 100-1000 lag av CIFAR-10-datasettet.
Det er en lignende tilnærming som kalles motorveinettverk, disse nettverkene bruker også hoppforbindelse. I likhet med LSTM bruker disse hoppforbindelsene også parametriske porter. Disse portene bestemmer hvor mye informasjon som passerer gjennom hoppforbindelsen. Denne arkitekturen har imidlertid ikke gitt nøyaktighet bedre enn ResNet-arkitekturen.

Nettverksarkitektur: Dette nettverket bruker en 34-lags vanlig nettverksarkitektur inspirert av VGG-19 der snarveisforbindelsen blir lagt til. Disse snarveisforbindelsene konverterer deretter arkitekturen til et gjenværende nettverk.

ResNet -34 arkitektur



Gjennomføring: Ved å bruke Tensorflow og Keras API kan vi designe ResNet-arkitektur (inkludert Residual Blocks) fra bunnen av. Nedenfor er implementeringen av forskjellige ResNet-arkitekturer. For denne implementeringen bruker vi CIFAR-10-datasettet. Dette datasettet inneholder 60 000 32×32 fargebilder i 10 forskjellige klasser (fly, biler, fugler, katter, hjort, hunder, frosker, hester, skip og lastebiler), etc. Dette datasettet kan vurderes fra k. eras.datasett API funksjon.

Trinn 1: Først importerer vi keras-modulen og dens API-er. Disse API-ene hjelper til med å bygge arkitekturen til ResNet-modellen.

Kode: Importerer biblioteker

# Import Keras modules and its important APIs import keras from keras.layers import Dense, Conv2D, BatchNormalization, Activation from keras.layers import AveragePooling2D, Input, Flatten from keras.optimizers import Adam from keras.callbacks import ModelCheckpoint, LearningRateScheduler from keras.callbacks import ReduceLROnPlateau from keras.preprocessing.image import ImageDataGenerator from keras.regularizers import l2 from keras import backend as K from keras.models import Model from keras.datasets import cifar10 import numpy as np import os>

Steg 2: Nå setter vi forskjellige hyperparametere som kreves for ResNet-arkitektur. Vi gjorde også litt forhåndsbehandling på datasettet vårt for å forberede det til opplæring.

Kode: Angi treningshyperparametere

tilkobling java mysql

python3




# Setting Training Hyperparameters> batch_size>=> 32> # original ResNet paper uses batch_size = 128 for training> epochs>=> 200> data_augmentation>=> True> num_classes>=> 10> > # Data Preprocessing> subtract_pixel_mean>=> True> n>=> 3> > # Select ResNet Version> version>=> 1> > # Computed depth of> if> version>=>=> 1>:> >depth>=> n>*> 6> +> 2> elif> version>=>=> 2>:> >depth>=> n>*> 9> +> 2> > # Model name, depth and version> model_type>=> 'ResNet % dv % d'> %> (depth, version)> > # Load the CIFAR-10 data.> (x_train, y_train), (x_test, y_test)>=> cifar10.load_data()> > # Input image dimensions.> input_shape>=> x_train.shape[>1>:]> > # Normalize data.> x_train>=> x_train.astype(>'float32'>)>/> 255> x_test>=> x_test.astype(>'float32'>)>/> 255> > # If subtract pixel mean is enabled> if> subtract_pixel_mean:> >x_train_mean>=> np.mean(x_train, axis>=> 0>)> >x_train>->=> x_train_mean> >x_test>->=> x_train_mean> > # Print Training and Test Samples> print>(>'x_train shape:'>, x_train.shape)> print>(x_train.shape[>0>],>'train samples'>)> print>(x_test.shape[>0>],>'test samples'>)> print>(>'y_train shape:'>, y_train.shape)> > # Convert class vectors to binary class matrices.> y_train>=> keras.utils.to_categorical(y_train, num_classes)> y_test>=> keras.utils.to_categorical(y_test, num_classes)>

fineste smilet i verden
>

>

Trinn 3: I dette trinnet setter vi læringshastigheten i henhold til antall epoker. Ettersom antall epoker må læringsraten reduseres for å sikre bedre læring.

Kode: Innstilling av LR for forskjellige antall epoker

python3




# Setting LR for different number of Epochs> def> lr_schedule(epoch):> >lr>=> 1e>->3> >if> epoch>>180>:> >lr>*>=> 0.5e>->3> >elif> epoch>>160>:> >lr>*>=> 1e>->3> >elif> epoch>>120>:> >lr>*>=> 1e>->2> >elif> epoch>>80>:> >lr>*>=> 1e>->1> >print>(>'Learning rate: '>, lr)> >return> lr>

>

>

Trinn 4: Definer grunnleggende ResNet-byggeblokk som kan brukes til å definere ResNet V1- og V2-arkitekturen.

Kode: Grunnleggende ResNet byggestein

delvis avhengighet

python3




# Basic ResNet Building Block> > > def> resnet_layer(inputs,> >num_filters>=>16>,> >kernel_size>=>3>,> >strides>=>1>,> >activation>=>'relu'>,> >batch_normalization>=>True>,> >conv>=>Conv2D(num_filters,> >kernel_size>=>kernel_size,> >strides>=>strides,> >padding>=>'same'>,> >kernel_initializer>=>'he_normal'>,> >kernel_regularizer>=>l2(>1e>->4>))> > >x>=>inputs> >if> conv_first:> >x>=> conv(x)> >if> batch_normalization:> >x>=> BatchNormalization()(x)> >if> activation>is> not> None>:> >x>=> Activation(activation)(x)> >else>:> >if> batch_normalization:> >x>=> BatchNormalization()(x)> >if> activation>is> not> None>:> >x>=> Activation(activation)(x)> >x>=> conv(x)> >return> x>

>

>

Trinn 5: Definer ResNet V1-arkitektur som er basert på ResNet-byggeblokken vi definerte ovenfor:

Kode: ResNet V1-arkitektur

python3




def> resnet_v1(input_shape, depth, num_classes>=>10>):> > >if> (depth>-> 2>)>%> 6> !>=> 0>:> >raise> ValueError(>'depth should be 6n + 2 (eg 20, 32, 44 in [a])'>)> ># Start model definition.> >num_filters>=> 16> >num_res_blocks>=> int>((depth>-> 2>)>/> 6>)> > >inputs>=> Input>(shape>=>input_shape)> >x>=> resnet_layer(inputs>=>inputs)> ># Instantiate the stack of residual units> >for> stack>in> range>(>3>):> >for> res_block>in> range>(num_res_blocks):> >strides>=> 1> >if> stack & gt> >0> and> res_block>=>=> 0>:># first layer but not first stack> >strides>=> 2> # downsample> >y>=> resnet_layer(inputs>=>x,> >num_filters>=>num_filters,> >strides>=>strides)> >y>=> resnet_layer(inputs>=>y,> >num_filters>=>num_filters,> >activation>=>None>)> >if> stack & gt> >0> and> res_block>=>=> 0>:># first layer but not first stack> ># linear projection residual shortcut connection to match> ># changed dims> >x>=> resnet_layer(inputs>=>x,> >num_filters>=>num_filters,> >kernel_size>=>1>,> >strides>=>strides,> >activation>=>None>,> >batch_normalization>=>False>)> >x>=> keras.layers.add([x, y])> >x>=> Activation(>'relu'>)(x)> >num_filters>*>=> 2> > ># Add classifier on top.> ># v1 does not use BN after last shortcut connection-ReLU> >x>=> AveragePooling2D(pool_size>=>8>)(x)> >y>=> Flatten()(x)> >outputs>=> Dense(num_classes,> >activation>=>'softmax'>,> >kernel_initializer>=>'he_normal'>)(y)> > ># Instantiate model.> >model>=> Model(inputs>=>inputs, outputs>=>outputs)> >return> model>

>

>

Trinn 6: Definer ResNet V2-arkitektur som er basert på ResNet-byggesteinen vi definerte ovenfor:

Kode: ResNet V2-arkitektur

python3

innsetting sort java




# ResNet V2 architecture> def> resnet_v2(input_shape, depth, num_classes>=>10>):> >if> (depth>-> 2>)>%> 9> !>=> 0>:> >raise> ValueError(>'depth should be 9n + 2 (eg 56 or 110 in [b])'>)> ># Start model definition.> >num_filters_in>=> 16> >num_res_blocks>=> int>((depth>-> 2>)>/> 9>)> > >inputs>=> Input>(shape>=>input_shape)> ># v2 performs Conv2D with BN-ReLU on input before splitting into 2 paths> >x>=> resnet_layer(inputs>=>inputs,> >num_filters>=>num_filters_in,> >conv_first>=>True>)> > ># Instantiate the stack of residual units> >for> stage>in> range>(>3>):> >for> res_block>in> range>(num_res_blocks):> >activation>=> 'relu'> >batch_normalization>=> True> >strides>=> 1> >if> stage>=>=> 0>:> >num_filters_out>=> num_filters_in>*> 4> >if> res_block>=>=> 0>:># first layer and first stage> >activation>=> None> >batch_normalization>=> False> >else>:> >num_filters_out>=> num_filters_in>*> 2> >if> res_block>=>=> 0>:># first layer but not first stage> >strides>=> 2> # downsample> > ># bottleneck residual unit> >y>=> resnet_layer(inputs>=>x,> >num_filters>=>num_filters_in,> >kernel_size>=>1>,> >strides>=>strides,> >activation>=>activation,> >batch_normalization>=>batch_normalization,> >conv_first>=>False>)> >y>=> resnet_layer(inputs>=>y,> >num_filters>=>num_filters_in,> >conv_first>=>False>)> >y>=> resnet_layer(inputs>=>y,> >num_filters>=>num_filters_out,> >kernel_size>=>1>,> >conv_first>=>False>)> >if> res_block>=>=> 0>:> ># linear projection residual shortcut connection to match> ># changed dims> >x>=> resnet_layer(inputs>=>x,> >num_filters>=>num_filters_out,> >kernel_size>=>1>,> >strides>=>strides,> >activation>=>None>,> >batch_normalization>=>False>)> >x>=> keras.layers.add([x, y])> > >num_filters_in>=> num_filters_out> > ># Add classifier on top.> ># v2 has BN-ReLU before Pooling> >x>=> BatchNormalization()(x)> >x>=> Activation(>'relu'>)(x)> >x>=> AveragePooling2D(pool_size>=>8>)(x)> >y>=> Flatten()(x)> >outputs>=> Dense(num_classes,> >activation>=>'softmax'>,> >kernel_initializer>=>'he_normal'>)(y)> > ># Instantiate model.> >model>=> Model(inputs>=>inputs, outputs>=>outputs)> >return> model>

>

>

Trinn 7: Koden nedenfor brukes til å trene og teste ResNet v1- og v2-arkitekturen vi definerte ovenfor:

Kode: Hovedfunksjon

python3




# Main function> if> version>=>=> 2>:> >model>=> resnet_v2(input_shape>=> input_shape, depth>=> depth)> else>:> >model>=> resnet_v1(input_shape>=> input_shape, depth>=> depth)> > model.>compile>(loss>=>'categorical_crossentropy'>,> >optimizer>=> Adam(learning_rate>=> lr_schedule(>0>)),> >metrics>=>[>'accuracy'>])> model.summary()> print>(model_type)> > # Prepare model saving directory.> save_dir>=> os.path.join(os.getcwd(),>'saved_models'>)> model_name>=> 'cifar10_% s_model.{epoch:03d}.h5'> %> model_type> if> not> os.path.isdir(save_dir):> >os.makedirs(save_dir)> filepath>=> os.path.join(save_dir, model_name)> > # Prepare callbacks for model saving and for learning rate adjustment.> checkpoint>=> ModelCheckpoint(filepath>=> filepath,> >monitor>=>'val_acc'>,> >verbose>=> 1>,> >save_best_only>=> True>)> > lr_scheduler>=> LearningRateScheduler(lr_schedule)> > lr_reducer>=> ReduceLROnPlateau(factor>=> np.sqrt(>0.1>),> >cooldown>=> 0>,> >patience>=> 5>,> >min_lr>=> 0.5e>->6>)> > callbacks>=> [checkpoint, lr_reducer, lr_scheduler]> > # Run training, with or without data augmentation.> if> not> data_augmentation:> >print>(>'Not using data augmentation.'>)> >model.fit(x_train, y_train,> >batch_size>=> batch_size,> >epochs>=> epochs,> >validation_data>=>(x_test, y_test),> >shuffle>=> True>,> >callbacks>=> callbacks)> else>:> >print>(>'Using real-time data augmentation.'>)> ># This will do preprocessing and realtime data augmentation:> >datagen>=> ImageDataGenerator(> ># set input mean to 0 over the dataset> >featurewise_center>=> False>,> ># set each sample mean to 0> >samplewise_center>=> False>,> ># divide inputs by std of dataset> >featurewise_std_normalization>=> False>,> ># divide each input by its std> >samplewise_std_normalization>=> False>,> ># apply ZCA whitening> >zca_whitening>=> False>,> ># epsilon for ZCA whitening> >zca_epsilon>=> 1e>->06>,> ># randomly rotate images in the range (deg 0 to 180)> >rotation_range>=> 0>,> ># randomly shift images horizontally> >width_shift_range>=> 0.1>,> ># randomly shift images vertically> >height_shift_range>=> 0.1>,> ># set range for random shear> >shear_range>=> 0.>,> ># set range for random zoom> >zoom_range>=> 0.>,> ># set range for random channel shifts> >channel_shift_range>=> 0.>,> ># set mode for filling points outside the input boundaries> >fill_mode>=>'nearest'>,> ># value used for fill_mode = 'constant'> >cval>=> 0.>,> ># randomly flip images> >horizontal_flip>=> True>,> ># randomly flip images> >vertical_flip>=> False>,> ># set rescaling factor (applied before any other transformation)> >rescale>=> None>,> ># set function that will be applied on each input> >preprocessing_function>=> None>,> ># image data format, either 'channels_first' or 'channels_last'> >data_format>=> None>,> ># fraction of images reserved for validation (strictly between 0 and 1)> >validation_split>=> 0.0>)> > ># Compute quantities required for featurewise normalization> ># (std, mean, and principal components if ZCA whitening is applied).> >datagen.fit(x_train)> > ># Fit the model on the batches generated by datagen.flow().> >model.fit_generator(datagen.flow(x_train, y_train, batch_size>=> batch_size),> >validation_data>=>(x_test, y_test),> >epochs>=> epochs, verbose>=> 1>, workers>=> 4>,> >callbacks>=> callbacks)> > # Score trained model.> scores>=> model.evaluate(x_test, y_test, verbose>=> 1>)> print>(>'Test loss:'>, scores[>0>])> print>(>'Test accuracy:'>, scores[>1>])>

gratis ipconfig

>

>

Resultater og konklusjon:
På ImageNet-datasettet bruker forfatterne et 152-lags ResNet, som er 8 ganger dypere enn VGG19, men som fortsatt har færre parametere. Et ensemble av disse ResNets genererte en feil på bare 3,7 % på ImageNet-testsettet, resultatet som vant ILSVRC 2015-konkurransen. På COCO-objektdeteksjonsdatasettet genererer det også en relativ forbedring på 28 % på grunn av dens svært dype representasjon.

Feilfrekvens på ResNet Architecture

  • Resultatet ovenfor viser at snarveiforbindelser vil kunne løse problemet forårsaket av å øke lagene, fordi når vi øker lagene fra 18 til 34, reduseres også feilraten på ImageNet Validation Set i motsetning til det vanlige nettverket.

topp-1 og topp-5 feilrate på ImageNet Validation Set.

  • Nedenfor er resultatene på ImageNet Test Set. De 3,57 % topp-5 feilrate for ResNet var den laveste, og dermed kom ResNet-arkitekturen først i ImageNet-klassifiseringsutfordringen i 2015.