Zephyrnet logo

ConvNetsin ylisovituksen ymmärtäminen

Treffi:

esittely

Ylisovitus ConvNetsissä on haaste syväoppimisessa ja hermoverkoissa, joissa malli oppii liikaa koulutustiedoista, mikä johtaa huonoon suorituskykyyn uudessa datassa. Tämä ilmiö on erityisen yleistä monimutkaisissa hermoarkkitehtuureissa, jotka voivat mallintaa monimutkaisia ​​suhteita. Convnet-verkon ylisovituksen käsitteleminen on ratkaisevan tärkeää luotettavien hermoverkkomallien rakentamisessa. Tämä artikkeli tarjoaa oppaan ylisovituksen ymmärtämiseen ja lieventämiseen sekä perimmäisten syiden, kuten mallin monimutkaisuuden, rajallisten harjoitustietojen ja meluisten ominaisuuksien tutkimiseen. Se käsittelee myös tekniikoita ylisovituksen estämiseksi, kuten tiedon lisäysstrategioita ja regularisointimenetelmiä.

Suosittelen lukemaan nämä artikkelit perusymmärryksen saamiseksi ylisovitus, alasovitus ja bias varianssin kompromissi.

Opi tavoitteet

  • Ymmärrä yliasennusten syyt, seuraukset ja skenaariot ConvNets.
  • Tulkitse oppimiskäyrät yli- ja alisovituksen havaitsemiseksi hermoverkkomalleissa.
  • Opi erilaisia ​​tekniikoita ylisovituksen lieventämiseksi, kuten varhainen pysäytys, keskeyttäminen, erän normalisointi, laillistaminen ja tietojen lisääminen.
  • Käytä näitä tekniikoita käyttämällä TensorFlow ja Keras kouluttamaan ConvNets-verkkoja CIFAR-10-tietojoukossa.
  • Analysoi eri tekniikoiden vaikutusta mallin suorituskykyyn ja yleistykseen.

Sisällysluettelo

Yleisiä yliasennusskenaarioita ConvNetissä

Katsotaanpa joitain yleisiä yliasennusskenaarioita ConvNetissä:

Skenaario 1: Erittäin monimutkainen malli, jossa ei ole riittävästi tietoja

Hyvin monimutkaisen mallin, kuten syvän hermoverkon, käyttö pienessä tietojoukossa voi johtaa ylisovitukseen. Malli saattaa muistaa koulutusesimerkit yleisen mallin oppimisen sijaan. Esimerkiksi syvän neuroverkon, jossa on vain muutama sata kuvaa, kouluttaminen monimutkaiseen tehtävään, kuten kuvantunnistukseen, voi johtaa ylisovitukseen.

Seuraus

Malli voi toimia erittäin hyvin harjoitustiedoissa, mutta se ei voi yleistää uuteen, näkymättömään dataan, mikä johtaa huonoon suorituskykyyn todellisissa sovelluksissa.

Kuinka ratkaista tämä ongelma?

Hanki lisää harjoitustietoja, tee kuvan lisäys yleistääksesi tietojoukkomme. Aloita vähemmän monimutkaisesta mallista ja jos kapasiteetti on pienempi, lisää monimutkaisuutta. 

Skenaario 2: Liiallinen harjoittelu

Mallin jatkuva harjoittelu liian monelle aikakaudelle voi johtaa ylisovitukseen. Kun malli näkee harjoitustiedot toistuvasti, se voi alkaa muistaa niitä mieluummin kuin oppia taustalla olevia malleja.

Seuraus

Mallin suorituskyky saattaa tasaantua tai jopa heiketä näkymättömissä tiedoissa, kun se erikoistuu yhä enemmän harjoitussarjaan.

Kuinka ratkaista tämä ongelma?

Käytä aikaista pysäytystä välttääksesi mallin liiallisen istuvuuden ja säästääksesi parhaan mallin. 

Skenaario 3: Regularoinnin huomiotta jättäminen

Regularisointitekniikoita, kuten L1- tai L2-regulointia, käytetään estämään ylisovitus rankaisemalla monimutkaisia ​​malleja. Regularointiparametrien huomiotta jättäminen tai virheellinen viritys voi johtaa ylisovitukseen.

Seuraus

Mallista voi tulla liian monimutkainen eikä se voi yleistää hyvin uuteen dataan, mikä johtaa huonoon suorituskykyyn harjoitussarjan ulkopuolella.

Kuinka ratkaista tämä ongelma?

Toteuta regularisointi, ristiinvalidointi, hyperparametrien viritys. 

Mikä on mallin kapasiteetti?

Mallin kapasiteetti viittaa niiden kuvioiden kokoon ja monimutkaisuuteen, jotka se pystyy oppimaan. Hermoverkkojen osalta tämä määräytyy suurelta osin sen mukaan, kuinka monta neuronia siinä on ja kuinka ne ovat yhteydessä toisiinsa. Jos näyttää siltä, ​​että verkkosi ei sovi dataan, yritä lisätä sen kapasiteettia.

Voit lisätä verkon kapasiteettia joko laajentamalla sitä (enemmän yksiköitä olemassa oleviin tasoihin) tai tekemällä sitä syvemmäksi (lisäämällä tasoja). Laajemmilla verkoilla on helpompi oppia lineaarisempia suhteita, kun taas syvemmät verkot pitävät enemmän epälineaarisista suhteista. Kumpi on parempi, riippuu vain tietojoukosta.

Oppimiskäyrien tulkinta

Keras tarjoaa mahdollisuuden rekisteröidä takaisinsoittoja harjoittelun aikana syväoppimismalli. Yksi kaikkien syväoppimismallien koulutuksen aikana rekisteröidyistä oletussoitoista on historian takaisinsoitto. Se tallentaa kunkin aikakauden harjoitusmittarit. Tämä sisältää menetyksen ja tarkkuuden (luokitteluongelmia varten) sekä validointitietojoukon menetyksen ja tarkkuuden, jos sellainen on asetettu.

Historiaobjekti palautetaan kutsuista fit()-funktioon, jota käytetään mallin harjoittamiseen. Mittarit tallennetaan sanakirjaan palautetun objektin historiajäseneen.

Voit esimerkiksi luetella historiaobjektiin kerätyt tiedot käyttämällä seuraavaa koodinpätkää mallin koulutuksen jälkeen:

# list all data in history
print(history.history.keys())

lähtö:

['tarkkuus', 'tappio', 'val_accuracy', 'val_loss']

Tietotyyppi

Voit ajatella, että harjoitustiedoissa olevat tiedot ovat kahdenlaisia:

  • signaali: Signaali on se osa, joka yleistää, osa, joka voi auttaa malliamme tekemään ennusteita uudesta tiedosta.
  • Noise: Melu on se osa, joka koskee vain harjoitustietoja; kohina on kaikkea satunnaista vaihtelua, joka tulee todellisen maailman tiedoista tai kaikista satunnaisista, ei-informatiivisista kuvioista, jotka eivät itse asiassa voi auttaa mallia tekemään ennusteita. Melu on osa, joka saattaa näyttää hyödylliseltä, mutta ei todellakaan ole sitä.

Kun harjoittelemme mallia, olemme piirtäneet tappiota harjoitussarjalle aikakausi kerrallaan. Tähän lisäämme myös validointitiedon käyrän. Näitä kaavioita kutsumme oppimiskäyriksi. Jotta syväoppimismalleja voidaan kouluttaa tehokkaasti, meidän on kyettävä tulkitsemaan niitä.

Oppimiskäyrät

Yllä olevasta kuvasta nähdään, että harjoitushäviö pienenee aikakausien kasvaessa, mutta validointihäviö pienenee aluksi ja kasvaa, kun malli alkaa siepata tietojoukossa olevaa kohinaa. Nyt aiomme nähdä, kuinka välttää ylisovitus ConvNetsissä eri tekniikoiden avulla. 

Menetelmät liiallisen sovituksen välttämiseksi

Nyt kun olemme nähneet joitain skenaarioita ja kuinka tulkita oppimiskäyriä ylisovituksen havaitsemiseksi. Tarkastellaan joitain menetelmiä, joilla vältetään ylisovitus hermoverkossa:

Tapa 1: Käytä enemmän tietoja

Tietojoukon koon kasvattaminen voi auttaa mallia yleistymään paremmin, koska siinä on monipuolisempia esimerkkejä, joista oppia. Malli löytää tärkeitä tietojoukossa olevia kuvioita ja jättää huomiotta kohinan, koska malli tajuaa, että nämä tietyt kuviot (kohina) eivät ole läsnä kaikissa tietojoukossa.

Tapa 2: Varhainen lopetus

Varhainen pysäytys on tekniikka, jota käytetään estämään yliasennusta seuraamalla mallin suorituskykyä validointisarjassa harjoituksen aikana. Harjoittelu keskeytyy, kun validointisarjan suorituskyky alkaa heikentyä, mikä osoittaa, että malli alkaa ylisovittua. Tyypillisesti suorituskyvyn seurantaan käytetään erillistä vahvistussarjaa, ja harjoitus lopetetaan, kun suorituskyky ei ole parantunut tietyn ajanjakson aikana.

Ali- ja ylisovitus

Tapa 3: Keskeyttäminen

Tiedämme, että ylisovitus johtuu siitä, että verkko oppii harhaanjohtavia kuvioita (kohinaa) harjoitusdatassa. Tunnistaakseen nämä harhaanjohtavat kuviot verkosto luottaa usein hyvin erityisiin painoyhdistelmiin, eräänlaiseen painojen "salaliittoon". Koska ne ovat niin tarkkoja, ne ovat yleensä hauraita: poista yksi ja salaliitto hajoaa.

Tämä on keskeyttämisen taustalla oleva idea. Purkaaksemme nämä salaliitot, pudotamme satunnaisesti pois osan tason syöttöyksiköistä jokaisessa harjoitusvaiheessa, mikä vaikeuttaa verkon oppimista harjoitusdatassa olevista harhaanjohtavista kuvioista. Sen sijaan sen on etsittävä laajoja, yleisiä kuvioita, joiden painokuviot ovat yleensä vankempia. 

Keskeyttämistä voisi ajatella myös eräänlaisena verkostokokonaisuuden luomisena. Ennusteita ei enää tee yksi iso verkosto, vaan pienempien verkostojen komitea. Valiokuntaan kuuluvilla henkilöillä on taipumus tehdä erilaisia ​​virheitä, mutta olla samalla oikeassa, mikä tekee komiteasta kokonaisuutena paremman kuin kukaan muu. (Jos tunnet satunnaiset metsät päätöspuiden kokonaisuutena, se on sama idea.)

Yliasennus ConvNetsissä

Tapa 4: Erän normalisointi

Seuraava erikoismenetelmä, jota tarkastelemme, suorittaa "eränormalisoinnin" (tai "batchnorm"), joka voi auttaa korjaamaan hidasta tai epävakaa harjoittelua.

Neuroverkkojen kanssa on yleensä hyvä idea laittaa kaikki tietosi yhteiseen mittakaavaan, esimerkiksi scikit-learnin StandardScalerin tai MinMaxScalerin avulla. Syynä on se, että SGD siirtää verkon painotuksia suhteessa siihen, kuinka suuren aktivoinnin data tuottaa. Ominaisuudet, jotka yleensä tuottavat hyvin erikokoisia aktivaatioita, voivat aiheuttaa epävakaa harjoittelukäyttäytymistä.

Jos nyt on hyvä normalisoida tiedot ennen kuin ne menee verkkoon, ehkä myös verkon sisällä normalisointi olisi parempi! Itse asiassa meillä on erityinen kerros, joka voi tehdä tämän, eränormalisointikerros. Erän normalisointikerros tarkastelee jokaista erää sen saapuessa, normalisoi ensin erän omalla keskiarvollaan ja standardipoikkeamallaan ja asettaa sitten tiedot uudelle mittakaavalle kahdella koulutettavalla uudelleenskaalausparametrilla. Batchnorm itse asiassa suorittaa eräänlaisen tulojensa koordinoidun uudelleenskaalauksen.

Useimmiten batchnorm lisätään optimointiprosessin apuvälineeksi (vaikka se voi joskus myös auttaa ennustamaan suorituskykyä). Batchnorm-mallit tarvitsevat yleensä vähemmän aikakausia koulutuksen suorittamiseen. Lisäksi batchnorm voi myös korjata erilaisia ​​​​ongelmia, jotka voivat aiheuttaa koulutuksen "jumittumista". Harkitse eränormalisoinnin lisäämistä malleihisi, varsinkin jos sinulla on ongelmia harjoituksen aikana.

Menetelmä 5: L1- ja L2-regulointi

L1- ja L2-regulointi ovat tekniikoita, joita käytetään estämään ylisovitus rankaisemalla suuria painoja hermoverkossa. L1-regulointi lisää tappiofunktioon painojen itseisarvoon verrannollisen sakkotermin. Se kannustaa painojen harvaan ja voi johtaa ominaisuuksien valintaan. L2-regulaatio, joka tunnetaan myös nimellä painon väheneminen, lisää painojen neliöön verrannollisen sakkotermin tappiofunktioon. Se estää painojen muodostumisen liian suuriksi ja edistää painojen jakautumista tasaisemmin.

Valinta L1- ja L2-regulaation välillä riippuu usein tietystä ongelmasta ja mallin halutuista ominaisuuksista.

Suuret arvot L1/L2-reguloinnille saa aikaan sen, että malli ei opi nopeasti ja saavuttaa oppimisen tasanne, mikä aiheuttaa mallin alisopivuuden. 

Menetelmä 6: Tietojen lisäys

Paras tapa parantaa koneoppimismallin suorituskykyä on kouluttaa sitä lisäämään dataa. Mitä useammista esimerkeistä mallin on opittava, sitä paremmin se pystyy tunnistamaan, mitkä kuvien erot ovat tärkeitä ja mitkä eivät. Lisää tietoa auttaa mallia yleistämään paremmin.

Yksi helppo tapa saada lisää tietoa on käyttää jo olemassa olevia tietoja. Jos pystymme muuttamaan tietojoukossamme olevat kuvat tavalla, joka säilyttää luokan (esimerkki: MNIST-numeroluokitus, jos yritämme lisätä 6:ta, on vaikea erottaa 6 ja 9), voimme opettaa luokittelijamme jättämään huomiotta tällaiset muunnokset. Esimerkiksi se, onko auto kuvassa vasemmalle tai oikealle, ei muuta sitä tosiasiaa, että se on henkilöauto eikä kuorma-auto. Joten jos täydennämme harjoitustietojamme käännetyillä kuvilla, luokittelijamme oppii, että "vasen tai oikea" on ero, jonka sen pitäisi jättää huomiotta.

Ja se on koko idea tietojen lisäämisen takana: lisää ylimääräisiä väärennettyjä tietoja, jotka näyttävät kohtuullisesti todellisilta tiedoilta, ja luokittimesi paranee. 

Muista, että avain liiallisen sovituksen välttämiseen on varmistaa, että mallisi yleistyy hyvin. Tarkista aina mallisi suorituskyky validointisarjasta, ei vain harjoitussarjasta.

Yllä olevien menetelmien käyttöönotto datalla

Tutkitaan yllä olevien menetelmien toteutusvaiheita:

Vaihe 1: Lataa tarvittavat kirjastot

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.callbacks import ModelCheckpoint
import keras
from keras.preprocessing import image
from keras import models, layers, regularizers
from tqdm import tqdm
import warnings
warnings.filterwarnings(action='ignore')

Vaihe 2: Tietojoukon lataaminen ja esikäsittely

#Here all the images are in the form of a numpy array
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.0
x_test = x_test / 255.0

Vaihe 3: Tietojoukon oppiminen

x_train.shape, y_train.shape, x_test.shape, y_test.shape 

lähtö:

ulostulo
np.unique(y_train)

lähtö:

ulostulo
#These labels are in the order and taken from the documentaion
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']

Vaihe 4: Kuvan visualisointi tietojoukosta

def show_image(IMG_INDEX):
    plt.imshow(x_train[20] ,cmap=plt.cm.binary)
    plt.xlabel(class_names[y_train[IMG_INDEX][0]])
    plt.show()
show_image(20)
Yliasennus ConvNetsissä
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

Alustetaan nyt hyperparametrit ja käännösmalli optimoijalla, häviöfunktiolla ja arviointimetriikalla.


train_hyperparameters_config={'optim':keras.optimizers.Adam(learning_rate=0.001),
                             'epochs':20,
                              'batch_size':16
                             }
model.compile(optimizer=train_hyperparameters_config['optim'],
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

Vaihe 6: Koulutusmalli

history = model.fit(x_train, y_train, 
                        epochs=train_hyperparameters_config['epochs'], 
                        batch_size=train_hyperparameters_config['batch_size'], 
                        verbose=1,
                        validation_data=(x_test, y_test))

Vaihe 7: Arvioi malli

Nämä kertovat meille historiaobjektin sisältämät tiedot ja luomme niiden avulla tietokäyrimme.

print(history.history.keys()) 
def learning_curves(history):
# Plotting Accuracy
    plt.figure(figsize=(14, 5))  # Adjust the figure size as needed
    plt.subplot(1, 2, 1)  # Subplot with 1 row, 2 columns, and index 1
    plt.plot(history.history['accuracy'], label='train_accuracy', marker='s', markersize=4)
    plt.plot(history.history['val_accuracy'], label='val_accuracy', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')

    # Plotting Loss
    plt.subplot(1, 2, 2)  # Subplot with 1 row, 2 columns, and index 2
    plt.plot(history.history['loss'], label='train_loss', marker='s', markersize=4)
    plt.plot(history.history['val_loss'], label='val_loss', marker='*', markersize=4)
    plt.xlabel('Epoch')
    plt.ylabel('Loss')
    plt.legend(loc='lower right')

    plt.show()
learning_curves(history)
Yliasennus ConvNetsissä

Käyristä nähdään, että validointitarkkuus saavuttaa tasannen 4. aikakauden jälkeen ja malli alkaa siepata kohinaa. Tästä syystä otamme käyttöön varhaisen pysäytyksen välttääksemme mallin yliasennusta ja palauttamme parhaat painot val_loss-arvon perusteella. Käytämme val_lossia valvomaan varhaista pysähtymistä, kun hermoverkkomme yrittää vähentää häviötä optimoijien avulla. Tarkkuus ja validointitarkkuus riippuvat kynnysarvosta (todennäköisyys erottaa luokkia – yleensä 0.5 binääriluokituksessa), joten jos tietojoukkomme on epätasapainossa, se olisi menetys, josta meidän pitäisi useimmissa tapauksissa huolehtia. 

Vaihe 8: Varhaisen pysäyttämisen käyttöönotto

Koska emme ole huolissamme mallimme liian istumisesta, varhainen pysähtyminen estää mallimme toteutumisen. On hyvä valinta valita suurempi määrä aikakausia ja sopiva kärsivällisyys. Nyt käytämme samaa malliarkkitehtuuria ja harjoittelemme varhaisessa pysäyttämisessä. 

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.AveragePooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))
model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

def model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config):
    model.compile(optimizer=train_hyperparameters_config['optim'],
                      loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                      metrics=['accuracy'])
    ht = model.fit(x_train, y_train, 
                            epochs=train_hyperparameters_config['epochs'], 
                            batch_size=train_hyperparameters_config['batch_size'],
                            callbacks=[callback],
                            verbose=1,
                            validation_data=(x_test, y_test))
    return ht

ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Yliasennus ConvNetsissä

Tietääksemme mallin parhaat painomme. 

print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Vaihe 9: Mallin monimutkaisuuden lisääminen

Koska mallimme ei toimi hyvin ja ei sovi, koska se ei pysty kaappaamaan tarpeeksi tietoa. Meidän pitäisi lisätä mallimme monimutkaisuutta ja arvioida. 

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
model.summary()
ulostulo

Näemme, että kokonaisparametrit ovat lisääntyneet. Tämä auttaisi löytämään monimutkaisempia suhteita mallissamme. Huomautus: Tietojoukossamme on 32 x 32 kuvia; nämä ovat suhteellisen pieniä kuvia. Siksi monimutkaisempien mallien käyttäminen alussa varmasti ylisopii mallia, joten meillä on tapana lisätä mallimme monimutkaisuutta hitaasti.

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)

learning_curves(ht)
Yliasennus ConvNetsissä
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Yllä olevista kaavioista voimme selvästi sanoa, että malli on ylisovitettu, joten käytämme toista menetelmää nimeltä Drop out normalization ja Batch normalisointi.

Vaihe 10: Dropout-tasojen ja eränormalisointikerrosten käyttäminen

model = models.Sequential()

model.add(layers.Conv2D(128, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(256, (3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPooling2D((2, 2)))

model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.3))

model.add(layers.Dense(10, activation='softmax'))
model.summary()
ulostulo
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Yliasennus ConvNetsissä
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Oppimiskaavioista voidaan nähdä, että malli on ylisovitettu jopa eränormalisointi- ja dropout-kerroksilla. Siten sen sijaan, että lisäisit monimutkaisuutta, vaan lisäisit suodattimien määrää. Lisäisimme lisää konvoluutiokerroksia saadaksemme enemmän ominaisuuksia.

Vaihe 11: Konvoluutiokerrosten lisääminen

Pienennä koulutettavaa parametria, mutta lisää konvoluutiokerroksia saadaksesi lisää ominaisuuksia.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 5,
    'epochs': 50,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
ulostulo
learning_curves(ht)
Yliasennus ConvNetsissä
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Yllä olevasta tuotos- ja oppimiskäyrästä voimme päätellä, että malli on toiminut erittäin hyvin ja on välttynyt ylisovittamiselta. Koulutuksen tarkkuus ja validointitarkkuus ovat hyvin lähellä. Tässä skenaariossa emme tarvitse lisää menetelmiä yliasennuksen vähentämiseksi. Silti tutkimme L1/L2-regulaatiota. 

Vaihe 12: L1/L2-reguloinnin käyttäminen

from tensorflow.keras import regularizers

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l2(0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l1_l2(0.0005, 0.0005)))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(10, activation='softmax'))

model.summary()
# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 7,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)
ht=model_train(model, x_train, y_train, x_test, y_test, train_hyperparameters_config)
learning_curves(ht)
Yliasennus ConvNetsissä
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Nyt voimme nähdä, että L1/L2-regulaatio jopa alhaisen 0.0001:n rangaistuspisteen käytön jälkeen teki mallistamme 4 % alituntuman. Siksi on suositeltavaa käyttää kaikkia menetelmiä varovasti yhdessä. Koska Eränormalisointi ja Regularisointi vaikuttavat malliin samalla tavalla, emme tarvitsisi L1/L2-regulointia. 

Vaihe 13: Tietojen lisäys

Käytämme ImageDataGeneratoria tensorflow kerasista.

# creates a data generator object that transforms images
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')

# pick an image to transform
test_img = x_train[20]
img = image.img_to_array(test_img)  # convert image to numpy arry
img = img.reshape((1,) + img.shape)  # reshape image

i = 0

for batch in datagen.flow(img, save_prefix='test', save_format='jpeg'):  # this loops runs forever until we break, saving images to current directory with specified prefix
    plt.figure(i)
    plot = plt.imshow(image.img_to_array(batch[0]))
    i += 1
    if i > 4:  # show 4 images
        break

plt.show()
Yliasennus ConvNetsissä

Nämä ovat neljä lisättyä kuvaa ja yksi alkuperäinen kuva.

# Create an instance of the ImageDataGenerator
datagen = ImageDataGenerator(
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True,
    fill_mode='nearest'
)

# Create an iterator for the data generator
data_generator = datagen.flow(x_train, y_train, batch_size=32)

# Create empty lists to store the augmented images and labels
augmented_images = []
augmented_labels = []

# Loop over the data generator and append the augmented data to the lists
num_batches = len(x_train) // 32
progress_bar = tqdm(total=num_batches, desc="Augmenting data", unit="batch")

for i in range(num_batches):
    batch_images, batch_labels = next(data_generator)
    augmented_images.append(batch_images)
    augmented_labels.append(batch_labels)
    progress_bar.update(1)

progress_bar.close()

# Convert the lists to NumPy arrays
augmented_images = np.concatenate(augmented_images, axis=0)
augmented_labels = np.concatenate(augmented_labels, axis=0)

# Combine the original and augmented data
x_train_augmented = np.concatenate((x_train, augmented_images), axis=0)
y_train_augmented = np.concatenate((y_train, augmented_labels), axis=0)
ulostulo

Olemme käyttäneet tqdm-kirjastoa tietääksemme lisäyksen edistymisen.

x_train_augmented.shape, y_train_augmented.shape
ulostulo

Tämä on tietojoukkomme lisäyksen jälkeen. Nyt käytetään tätä tietojoukkoa ja koulutetaan malliamme.

model = models.Sequential()

model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(32, 32, 3)))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(32, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.2))

model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(64, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.3))

model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(layers.BatchNormalization())
model.add(layers.MaxPool2D((2, 2)))
model.add(layers.Dropout(0.4))

model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.BatchNormalization())
model.add(layers.Dropout(0.5))

model.add(layers.Dense(10, activation='softmax'))

model.summary()

# Here we have used more epochs than needed since we use patience parameter which we stop the model from overfitting
train_hyperparameters_config = {
    'optim': keras.optimizers.Adam(learning_rate=0.001),
    'patience': 10,
    'epochs': 70,
    'batch_size': 32, 
}
print('Setting the callback and early stopping configurations...')
callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', 
    min_delta=0.001, # minimium amount of change to count as an improvement
    patience=train_hyperparameters_config['patience'], 
    restore_best_weights=True)

ht=model_train(model, x_train_augmented, y_train_augmented, x_test, y_test, train_hyperparameters_config)


learning_curves(ht)
Yliasennus ConvNetsissä
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test,  y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)

Näemme mallin yleistyvän ja tappion pienenevän. Meillä on myös parempi validointitarkkuus. Tästä syystä tietojen lisäys on lisännyt mallimme tarkkuutta. 

Yhteenveto

Ylisovitus on yleinen ongelma syväoppimisessa, erityisesti monimutkaisissa hermoverkkoarkkitehtuureissa, kuten ConvNets. Ammatinharjoittajat voivat estää ylisovituksen ConvNetsissä ymmärtämällä sen perimmäiset syyt ja tunnistamalla skenaariot, joissa sitä esiintyy. Tekniikat, kuten varhainen lopettaminen, keskeyttäminen, eränormalisointi, laillistaminen ja tietojen lisääminen, voivat auttaa lieventämään tätä ongelmaa. Näiden tekniikoiden käyttöönotto CIFAR-10-tietojoukossa osoitti merkittäviä parannuksia mallin yleistämisessä ja suorituskyvyssä. Näiden tekniikoiden hallitseminen ja niiden periaatteiden ymmärtäminen voi johtaa vankoihin ja luotettaviin hermoverkkomalleihin.

Usein kysytyt kysymykset

Q1. Mitä ylisovitus on, ja miksi se on ongelma syvässä oppimisessa? 

V. Ylisovitus tapahtuu, kun malli oppii liian hyvin harjoitustiedot, mukaan lukien sen kohinan ja epäolennaiset kuviot, mikä johtaa huonoon suorituskykyyn uudella, näkemättömällä tiedolla. Se on ongelma, koska ylisovitetut mallit eivät pysty yleistämään tehokkaasti, mikä rajoittaa niiden käytännön käyttökelpoisuutta.

Q2. Kuinka voin havaita ylisovituksen hermoverkkomallissani?

V. Voit havaita ylisovituksen ConvNetsissä tulkitsemalla oppimiskäyriä, jotka kuvaavat koulutus- ja validointimetriikkaa (esim. menetys, tarkkuus) eri aikakausille. Jos validointimittarit lakkaavat parantumasta tai alkavat heikentyä harjoittelutietojen parantuessa edelleen, se on merkki ylisovituksesta.

Q3. Mitä on varhainen pysähtyminen ja miten se auttaa estämään liiallista istuvuutta?

V. Varhainen pysäytys on tekniikka, joka tarkkailee mallin suorituskykyä validointisarjassa harjoituksen aikana ja pysäyttää harjoitusprosessin, kun validointisarjan suorituskyky alkaa heikentyä, mikä osoittaa ylisovitusta. Se auttaa estämään mallin liiallista istuvuutta lopettamalla harjoittelun oikeaan aikaan.

Q4. Kuinka tiedon lisääminen auttaa vähentämään ylisovitusta? 

V. Datan lisäys on prosessi, jossa luodaan uutta synteettistä harjoitusdataa soveltamalla muunnoksia (esim. kääntämällä, kiertämällä, skaalauttamalla) olemassa olevaan dataan. Se auttaa mallia yleistymään paremmin paljastamalla sen monipuolisemmille esimerkeille, mikä vähentää riskiä, ​​että ConvNets ylisovitetaan rajoitetulle harjoitusdatalle.

spot_img

Uusin älykkyys

spot_img