logo

Reziduálne siete (ResNet) – Hlboké učenie

Po prvej architektúre založenej na CNN (AlexNet), ktorá vyhrala súťaž ImageNet 2012, každá ďalšia víťazná architektúra využíva viac vrstiev v hlbokej neurónovej sieti na zníženie chybovosti. Funguje to pri menšom počte vrstiev, ale keď počet vrstiev zväčšíme, v hlbokom učení sa vyskytuje bežný problém, ktorý súvisí s tým, ktoré sa nazýva gradient miznúci/vybuchujúci. To spôsobí, že gradient bude 0 alebo príliš veľký. Keď teda zvýšime počet vrstiev, zvýši sa aj chybovosť trénovania a testovania.

Porovnanie 20-vrstvovej vs 56-vrstvovej architektúry



Vo vyššie uvedenom grafe môžeme pozorovať, že 56-vrstvová CNN poskytuje väčšiu chybovosť na tréningovom aj testovacom súbore údajov ako 20-vrstvová architektúra CNN. Po podrobnejšej analýze chybovosti boli autori schopní dospieť k záveru, že je to spôsobené miznúcim/explodujúcim gradientom.
ResNet, ktorý v roku 2015 navrhli výskumníci z Microsoft Research, predstavil novú architektúru s názvom Residual Network.

Zvyšná sieť: Aby sa vyriešil problém miznúceho/explodujúceho gradientu, zaviedla táto architektúra koncept nazývaný zvyškové bloky. V tejto sieti používame techniku ​​tzv preskočiť spojenia . Preskakovanie spája aktivácie vrstvy s ďalšími vrstvami preskočením niektorých vrstiev medzi nimi. Toto tvorí zvyškový blok. Resnety sa vyrábajú stohovaním týchto zvyškových blokov dohromady.
Prístup za touto sieťou je namiesto toho, aby sa vrstvy učili základné mapovanie, umožňujeme sieti prispôsobiť sa zvyškovému mapovaniu. Takže namiesto povedzme H(x) počiatočné mapovanie , nech sa sieť zmestí,

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

Preskočiť (skratka) pripojenie



Výhodou pridania tohto typu preskakovacieho pripojenia je, že ak ktorákoľvek vrstva poškodí výkon architektúry, bude preskočená regularizáciou. Výsledkom je trénovanie veľmi hlbokej neurónovej siete bez problémov spôsobených miznúcim/explodujúcim gradientom. Autori článku experimentovali na 100-1000 vrstvách súboru údajov CIFAR-10.
Existuje podobný prístup nazývaný diaľničné siete, tieto siete tiež využívajú preskakovacie pripojenie. Podobne ako LSTM, aj tieto preskokové spojenia používajú parametrické brány. Tieto brány určujú, koľko informácií prejde cez preskočené spojenie. Táto architektúra však neposkytuje lepšiu presnosť ako architektúra ResNet.

Architektúra siete: Táto sieť využíva 34-vrstvovú jednoduchú sieťovú architektúru inšpirovanú VGG-19, do ktorej je potom pridané skratkové pripojenie. Tieto skratky potom konvertujú architektúru na zvyškovú sieť.

Architektúra ResNet -34



Implementácia: Pomocou Tensorflow a Keras API môžeme navrhnúť architektúru ResNet (vrátane zvyškových blokov) od začiatku. Nižšie je uvedená implementácia rôznych architektúr ResNet. Na túto implementáciu používame súbor údajov CIFAR-10. Tento súbor údajov obsahuje 60 000 farebných obrázkov 32×32 v 10 rôznych triedach (lietadlá, autá, vtáky, mačky, jelene, psy, žaby, kone, lode a nákladné autá) atď. Tento súbor údajov možno posúdiť od k éry.súbory údajov Funkcia API.

Krok 1: Najprv importujeme modul keras a jeho API. Tieto rozhrania API pomáhajú pri budovaní architektúry modelu ResNet.

kód: Importovanie knižníc

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

Krok 2: Teraz nastavíme rôzne hyper parametre, ktoré sú potrebné pre architektúru ResNet. Urobili sme tiež predbežné spracovanie nášho súboru údajov, aby sme ho pripravili na školenie.

kód: Nastavenie tréningových hyperparametrov

python3


ako odstrániť prvý znak v programe excel



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

>

>

Krok 3: V tomto kroku nastavíme rýchlosť učenia podľa počtu epoch. Vzhľadom na počet epoch sa musí rýchlosť učenia znížiť, aby sa zabezpečilo lepšie učenie.

kód: Nastavenie LR pre rôzne počty epoch

python3




mysql odišiel pripojiť
# 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>

>

>

Krok 4: Definujte základný stavebný blok ResNet, ktorý možno použiť na definovanie architektúry ResNet V1 a V2.

kód: Základný stavebný blok 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>

>

>

Krok 5: Definujte architektúru ResNet V1, ktorá je založená na stavebnom bloku ResNet, ktorý sme definovali vyššie:

kód: Architektúra 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>

>

>

Krok 6: Definujte architektúru ResNet V2, ktorá je založená na stavebnom bloku ResNet, ktorý sme definovali vyššie:

kód: Architektúra ResNet V2

ako zistiť veľkosť monitora

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>

>

>

Krok 7: Nižšie uvedený kód sa používa na trénovanie a testovanie architektúry ResNet v1 a v2, ktorú sme definovali vyššie:

Kód: Hlavná funkcia

python3

arraylist v java sort




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

>

>

Výsledky a záver:
Na súbore údajov ImageNet autori používajú 152-vrstvový ResNet, ktorý je 8-krát hlbší ako VGG19, ale stále má menej parametrov. Súbor týchto ResNet vygeneroval chybu iba 3,7% na testovacej sade ImageNet, výsledok vyhral súťaž ILSVRC 2015. Na súbore údajov detekcie objektov COCO tiež generuje 28% relatívne zlepšenie vďaka veľmi hlbokému zastúpeniu.

Chybovosť v architektúre ResNet

  • Vyššie uvedený výsledok ukazuje, že skratkové pripojenia by dokázali vyriešiť problém spôsobený zväčšením vrstiev, pretože keď zväčšujeme vrstvy z 18 na 34, chybovosť na ImageNet Validation Set tiež klesá na rozdiel od obyčajnej siete.

chybovosť top-1 a top-5 na ImageNet Validation Set.

  • Nižšie sú uvedené výsledky testovacej sady ImageNet. The 3,57 % chybovosť ResNet v top 5 bola najnižšia, a preto bola architektúra ResNet na prvom mieste v klasifikačnej výzve ImageNet v roku 2015.