Pēc pirmās uz CNN balstītās arhitektūras (AlexNet), kas uzvarēja ImageNet 2012 konkursā, katra nākamā uzvarošā arhitektūra izmanto vairāk slāņu dziļā neironu tīklā, lai samazinātu kļūdu līmeni. Tas darbojas mazākam slāņu skaitam, taču, palielinot slāņu skaitu, ir izplatīta dziļās mācīšanās problēma, kas saistīta ar gradientu, ko sauc par izzūdošo/eksplodējošu gradientu. Tādējādi gradients kļūst 0 vai pārāk liels. Tādējādi, palielinot slāņu skaitu, palielinās arī apmācības un pārbaudes kļūdu līmenis.

20 slāņu un 56 slāņu arhitektūras salīdzinājums
Iepriekš minētajā diagrammā mēs varam novērot, ka 56 slāņu CNN nodrošina lielāku kļūdu līmeni gan apmācības, gan testēšanas datu kopā nekā 20 slāņu CNN arhitektūra. Vairāk analizējot kļūdu līmeni, autori varēja nonākt pie secinājuma, ka to izraisa gradienta izzušana/eksplodēšana.
ResNet, kuru 2015. gadā ierosināja Microsoft Research pētnieki, ieviesa jaunu arhitektūru ar nosaukumu Residual Network.
Atlikušais tīkls: Lai atrisinātu izzūdošā/eksplodējošā gradienta problēmu, šī arhitektūra ieviesa jēdzienu, ko sauc par atlikušajiem blokiem. Šajā tīklā mēs izmantojam tehniku, ko sauc izlaist savienojumus . Izlaišanas savienojums savieno slāņa aktivizācijas ar citiem slāņiem, izlaižot dažus slāņus starp tiem. Tas veido atlikušo bloku. Resnets tiek izgatavots, saliekot šos atlikušos blokus kopā.
Šī tīkla pieeja ir tāda, ka tā vietā, lai slāņi apgūtu pamata kartēšanu, mēs ļaujam tīklam pielāgoties atlikušajai kartēšanai. Tātad, tā vietā, lai teiktu H(x), sākotnējā kartēšana , ļaujiet tīklam ietilpt,
F(x) := H(x) - x which gives H(x) := F(x) + x .>

Izlaist (īsceļu) savienojumu
Šāda veida izlaišanas savienojuma pievienošanas priekšrocība ir tāda, ka, ja kāds slānis pasliktinās arhitektūras veiktspēju, tas tiks izlaists, veicot regulāciju. Tādējādi tiek apmācīts ļoti dziļš neironu tīkls bez problēmām, ko rada izzūdošs/sprādziens gradients. Darba autori eksperimentēja ar 100–1000 CIFAR-10 datu kopas slāņiem.
Ir līdzīga pieeja, ko sauc par lielceļu tīkliem, šie tīkli izmanto arī izlaišanas savienojumu. Līdzīgi kā LSTM, šajos izlaišanas savienojumos tiek izmantoti arī parametriskie vārti. Šie vārti nosaka, cik daudz informācijas iziet caur izlaišanas savienojumu. Tomēr šī arhitektūra nav nodrošinājusi labāku precizitāti nekā ResNet arhitektūra.
Tīkla arhitektūra: Šajā tīklā tiek izmantota 34 slāņu vienkārša tīkla arhitektūra, ko iedvesmojis VGG-19, kurā pēc tam tiek pievienots saīsnes savienojums. Šie saīsnes savienojumi pēc tam pārvērš arhitektūru atlikušajā tīklā.

ResNet -34 arhitektūra
java pārvērš veselu skaitli par virkni
Īstenošana: Izmantojot Tensorflow un Keras API, mēs varam izstrādāt ResNet arhitektūru (ieskaitot atlikušos blokus) no nulles. Tālāk ir aprakstīta dažādu ResNet arhitektūras ieviešana. Šai ieviešanai mēs izmantojam CIFAR-10 datu kopu. Šajā datu kopā ir 60 000 32 × 32 krāsu attēlu 10 dažādās klasēs (lidmašīnas, automašīnas, putni, kaķi, brieži, suņi, vardes, zirgi, kuģi un kravas automašīnas) utt. Šo datu kopu var novērtēt no k eras.datasets API funkcija.
1. darbība: Pirmkārt, mēs importējam keras moduli un tā API. Šīs API palīdz veidot ResNet modeļa arhitektūru.
Kods: Bibliotēku importēšana
# 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. darbība: Tagad mēs iestatām dažādus hiperparametrus, kas nepieciešami ResNet arhitektūrai. Mēs arī veicām savu datu kopas priekšapstrādi, lai sagatavotu to apmācībai.
Kods: Apmācības hiperparametru iestatīšana
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. darbība: Šajā solī mēs iestatām mācīšanās ātrumu atbilstoši laikmetu skaitam. Tā kā laikmetu skaits ir jāsamazina, lai nodrošinātu labāku mācīšanos.
Kods: LR iestatīšana dažādiem laikmetu skaitļiem
python3
# Setting LR for different number of Epochs> def> lr_schedule(epoch):> >lr>=> 1e>->3> >if> epoch>>> >lr>*>=> 0.5e>->3> >elif> epoch>>> >lr>*>=> 1e>->3> >elif> epoch>>> >lr>*>=> 1e>->2> >elif> epoch>>> >lr>*>=> 1e>->1> >print>(>'Learning rate: '>, lr)> >return> lr> |
>
>
4. darbība: Definējiet pamata ResNet veidošanas bloku, ko var izmantot ResNet V1 un V2 arhitektūras definēšanai.
Kods: Pamata ResNet veidošanas bloks
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. darbība: Definējiet ResNet V1 arhitektūru, kuras pamatā ir iepriekš definētais ResNet veidošanas bloks:
Kods: ResNet V1 arhitektūra
ceturksnis biznesā
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. darbība: Definējiet ResNet V2 arhitektūru, kuras pamatā ir iepriekš definētais ResNet veidošanas bloks:
Kods: ResNet V2 arhitektūra
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. darbība: Tālāk norādītais kods tiek izmantots, lai apmācītu un pārbaudītu iepriekš definēto ResNet v1 un v2 arhitektūru:
Kods: Galvenā funkcija
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>])> |
>
>
Rezultāti un secinājumi:
ImageNet datu kopā autori izmanto 152 slāņu ResNet, kas ir 8 reizes dziļāks nekā VGG19, taču tam joprojām ir mazāk parametru. Šo ResNet komplekts ImageNet testa komplektā radīja kļūdu tikai 3,7% apmērā, kas uzvarēja ILSVRC 2015 konkursā. COCO objektu noteikšanas datu kopā tā rada arī 28% relatīvo uzlabojumu tās ļoti dziļā attēlojuma dēļ.
savienojumi java

Kļūdu līmenis ResNet arhitektūrā
- Iepriekš redzamais rezultāts parāda, ka saīsnes savienojumi varētu atrisināt problēmu, ko izraisa slāņu palielināšana, jo, palielinot slāņus no 18 uz 34, kļūdu līmenis ImageNet validācijas komplektā arī samazinās atšķirībā no vienkārša tīkla.

top-1 un top-5 kļūdu līmenis ImageNet validācijas komplektā.
- Zemāk ir ImageNet testa komplekta rezultāti. The 3,57% ResNet 5 labāko kļūdu līmenis bija viszemākais, un tādējādi ResNet arhitektūra ieņēma pirmo vietu ImageNet klasifikācijas izaicinājumā 2015. gadā.
