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ä.
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.
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.)
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ö:
np.unique(y_train)
lähtö:
#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)
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)
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)
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()
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)
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()
# 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)
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)
learning_curves(ht)
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)
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()
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)
Olemme käyttäneet tqdm-kirjastoa tietääksemme lisäyksen edistymisen.
x_train_augmented.shape, y_train_augmented.shape
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)
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
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.
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.
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.
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.
- SEO-pohjainen sisällön ja PR-jakelu. Vahvista jo tänään.
- PlatoData.Network Vertical Generatiivinen Ai. Vahvista itseäsi. Pääsy tästä.
- PlatoAiStream. Web3 Intelligence. Tietoa laajennettu. Pääsy tästä.
- PlatoESG. hiili, CleanTech, energia, ympäristö, Aurinko, Jätehuolto. Pääsy tästä.
- PlatonHealth. Biotekniikan ja kliinisten kokeiden älykkyys. Pääsy tästä.
- Lähde: https://www.analyticsvidhya.com/blog/2024/04/understanding-overfitting-in-convnets/