logo

Ostala omrežja (ResNet) – globoko učenje

Po prvi arhitekturi, ki temelji na CNN (AlexNet), ki je zmagala na tekmovanju ImageNet 2012, vsaka naslednja zmagovalna arhitektura uporablja več plasti v globoki nevronski mreži za zmanjšanje stopnje napak. To deluje pri manjšem številu slojev, ko pa povečamo število slojev, pride do pogoste težave pri globokem učenju, ki je povezana s tistim, ki se imenuje izginjajoči/eksplodirajući gradient. To povzroči, da gradient postane 0 ali prevelik. Ko torej povečamo število plasti, se poveča tudi stopnja napak pri usposabljanju in testu.

Primerjava 20-slojne in 56-slojne arhitekture



Na zgornjem grafu lahko opazimo, da 56-slojni CNN daje višjo stopnjo napak pri naboru podatkov za usposabljanje in testiranje kot 20-slojna arhitektura CNN. Po podrobnejši analizi stopnje napak so avtorji lahko prišli do zaključka, da jo povzroča izginjajoči/eksplozivni gradient.
ResNet, ki so ga leta 2015 predlagali raziskovalci pri Microsoft Research, je predstavil novo arhitekturo, imenovano Residual Network.

jpa proti hibernaciji

Preostalo omrežje: Da bi rešili problem izginjajočega/eksplozivnega gradienta, je ta arhitektura uvedla koncept, imenovan Residual Blocks. V tem omrežju uporabljamo tehniko, imenovano preskočite povezave . Preskočna povezava povezuje aktivacije sloja z nadaljnjimi sloji tako, da preskoči nekatere vmesne sloje. To tvori preostali blok. Resneti so narejeni z zlaganjem teh preostalih blokov skupaj.
Pristop v ozadju tega omrežja je, da namesto slojev, ki se učijo osnovnega preslikave, omogočimo omrežju, da se prilagodi preostalemu preslikavi. Torej, namesto recimo H(x), začetno preslikavo , naj se mreža prilega,

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

Preskoči (bližnjico) povezavo



Prednost dodajanja te vrste preskočne povezave je v tem, da če katera koli plast škoduje zmogljivosti arhitekture, jo bo regularizacija preskočila. Posledica tega je usposabljanje zelo globoke nevronske mreže brez težav, ki jih povzroča izginjajoči/eksplozivni gradient. Avtorji prispevka so eksperimentirali na 100–1000 slojih nabora podatkov CIFAR-10.
Obstaja podoben pristop, imenovan avtocestna omrežja, ta omrežja uporabljajo tudi preskočno povezavo. Podobno kot LSTM tudi te preskočne povezave uporabljajo parametrična vrata. Ta vrata določajo, koliko informacij gre skozi preskočno povezavo. Vendar pa ta arhitektura ni zagotovila boljše natančnosti kot arhitektura ResNet.

Arhitektura omrežja: To omrežje uporablja 34-slojno navadno omrežno arhitekturo po navdihu VGG-19, v katero je nato dodana povezava z bližnjico. Te bližnjične povezave nato pretvorijo arhitekturo v preostalo omrežje.

Arhitektura ResNet -34



Izvedba: Z uporabo Tensorflow in Keras API lahko oblikujemo arhitekturo ResNet (vključno s preostalimi bloki) iz nič. Spodaj je implementacija različnih arhitektur ResNet. Za to izvedbo uporabljamo nabor podatkov CIFAR-10. Ta nabor podatkov vsebuje 60.000 barvnih slik 32 × 32 v 10 različnih razredih (letala, avtomobili, ptice, mačke, jeleni, psi, žabe, konji, ladje in tovornjaki) itd. Ta nabor podatkov je mogoče oceniti s k eras.datasets API funkcija.

Korak 1: Najprej uvozimo modul keras in njegove API-je. Ti API-ji pomagajo pri gradnji arhitekture modela ResNet.

Koda: Uvažanje knjižnic

# 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>

2. korak: Zdaj smo nastavili različne hiper parametre, ki so potrebni za arhitekturo ResNet. Izvedli smo tudi nekaj predprocesiranja našega nabora podatkov, da smo ga pripravili za usposabljanje.

Koda: Nastavitev vadbenih hiperparametrov

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)>

>

>

3. korak: V tem koraku nastavimo stopnjo učenja glede na število epoh. S številom epoh je treba hitrost učenja zmanjšati, da se zagotovi boljše učenje.

Koda: Nastavitev LR za različno število epoh

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>

>

json v primeru json
>

4. korak: Definirajte osnovni gradnik ResNet, ki se lahko uporablja za definiranje arhitekture ResNet V1 in V2.

Koda: Osnovni gradnik ResNet

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>

>

>

5. korak: Definirajte arhitekturo ResNet V1, ki temelji na gradniku ResNet, ki smo ga definirali zgoraj:

Koda: Arhitektura ResNet V1

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>

>

>

6. korak: Definirajte arhitekturo ResNet V2, ki temelji na gradniku ResNet, ki smo ga definirali zgoraj:

Koda: Arhitektura ResNet V2

python3




# 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>

>

>

7. korak: Spodnja koda se uporablja za usposabljanje in testiranje arhitekture ResNet v1 in v2, ki smo jo definirali zgoraj:

Koda: Glavna funkcija

python3

niz dolžine




# 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>])>

>

>

Rezultati in zaključek:
V naboru podatkov ImageNet avtorji uporabljajo 152-slojni ResNet, ki je 8-krat globlji od VGG19, vendar ima še vedno manj parametrov. Ansambel teh ResNetov je ustvaril samo 3,7-odstotno napako na testnem nizu ImageNet, rezultat, ki je zmagal na tekmovanju ILSVRC 2015. Na naboru podatkov o zaznavanju objektov COCO ustvari tudi 28-odstotno relativno izboljšanje zaradi svoje zelo globoke predstavitve.

Stopnja napak pri arhitekturi ResNet

  • Zgornji rezultat kaže, da bi povezave z bližnjicami lahko rešile težavo, ki jo povzroči povečanje plasti, ker se s povečanjem ravni z 18 na 34 zmanjša tudi stopnja napak v ImageNet Validation Set za razliko od navadnega omrežja.

top-1 in top-5 Stopnja napak na ImageNet Validation Set.

  • Spodaj so rezultati nabora testov ImageNet. The 3,57 % Top 5 stopnja napak ResNet je bila najnižja in tako je bila arhitektura ResNet prva v izzivu klasifikacije ImageNet leta 2015.