Introduksjon
Overtilpasning i ConvNets er en utfordring i dyp læring og nevrale nettverk, der en modell lærer for mye av treningsdata, noe som fører til dårlig ytelse på nye data. Dette fenomenet er spesielt utbredt i komplekse nevrale arkitekturer, som kan modellere intrikate forhold. Å adressere overtilpasning i convnet er avgjørende for å bygge pålitelige nevrale nettverksmodeller. Denne artikkelen gir en veiledning for å forstå og redusere overtilpasning, undersøke grunnleggende årsaker som modellkompleksitet, begrensede treningsdata og støyende funksjoner. Den diskuterer også teknikker for å forhindre overtilpasning, for eksempel strategier for dataforsterkning og regulariseringsmetoder.
Jeg vil anbefale å lese disse artiklene for grunnleggende forståelse av overfitting, underfitting og bias varians avveining.
Lær mål
- Forstå årsakene, konsekvensene og scenariene for overfitting ConvNets.
- Tolk læringskurver for å oppdage overtilpasning og undertilpasning i nevrale nettverksmodeller.
- Lær ulike teknikker for å redusere overtilpasning, for eksempel tidlig stopp, frafall, batchnormalisering, regularisering og dataforsterkning.
- Implementer disse teknikkene ved hjelp av tensorflow og Keras for å trene ConvNets på CIFAR-10-datasettet.
- Analyser virkningen av ulike teknikker på modellytelse og generalisering.
Innholdsfortegnelse
Vanlige scenarier for overtilpasning i ConvNet
La oss se på noen vanlige scenarier for overtilpasning i ConvNet:
Scenario 1: Svært kompleks modell med utilstrekkelig data
Å bruke en veldig kompleks modell, for eksempel et dypt nevralt nettverk, på et lite datasett kan føre til overtilpasning. Modellen kan huske treningseksemplene i stedet for å lære det generelle mønsteret. For eksempel kan trening av et dypt nevralt nettverk med bare noen få hundre bilder for en kompleks oppgave som bildegjenkjenning føre til overtilpasning.
Konsekvens
Modellen kan prestere veldig bra på treningsdataene, men klarer ikke å generalisere til nye, usynlige data, noe som resulterer i dårlig ytelse i virkelige applikasjoner.
Hvordan løse dette problemet?
Få mer treningsdata, Gjør bildeforstørrelse for å generalisere datasettet vårt. Start med en mindre kompleks modell, og hvis kapasiteten er mindre, øk kompleksiteten.
Scenario 2: Overdreven trening
Kontinuerlig opplæring av en modell for mange epoker kan føre til overfitting. Ettersom modellen ser treningsdataene gjentatte ganger, kan den begynne å huske dem i stedet for å lære de underliggende mønstrene.
Konsekvens
Modellens ytelse kan platå eller til og med forringes på usynlige data ettersom den blir stadig mer spesialisert til treningssettet.
Hvordan løse dette problemet?
Bruk tidlig stopp for å unngå at modellen overfiter og lagre den beste modellen.
Scenario 3: Ignorerer regularisering
Regulariseringsteknikker, som L1- eller L2-regularisering, brukes for å forhindre overtilpasning ved å straffe komplekse modeller. Ignorering eller feiljustering av regulariseringsparametere kan føre til overtilpasning.
Konsekvens
Modellen kan bli for kompleks og mislykkes i å generalisere godt til nye data, noe som resulterer i dårlig ytelse utenfor treningssettet.
Hvordan løse dette problemet?
Implementer regularisering, Kryssvalidering, Hyper parameter tuning.
Hva er modellens kapasitet?
En modells kapasitet refererer til størrelsen og kompleksiteten til mønstrene den er i stand til å lære. For nevrale nettverk vil dette i stor grad være bestemt av hvor mange nevroner det har og hvordan de er koblet sammen. Hvis det ser ut til at nettverket ditt undertilpasser dataene, bør du prøve å øke kapasiteten.
Du kan øke kapasiteten til et nettverk enten ved å gjøre det bredere (flere enheter til eksisterende lag) eller ved å gjøre det dypere (legge til flere lag). Bredere nettverk har lettere for å lære mer lineære relasjoner, mens dypere nettverk foretrekker mer ikke-lineære. Hva som er bedre avhenger bare av datasettet.
Tolkning av læringskurver
Keras gir muligheten til å registrere tilbakeringinger når du trener en dyp læringsmodell. En av standard tilbakeringinger som er registrert når du trener alle dyplæringsmodeller, er historietilbakekalling. Den registrerer treningsberegninger for hver epoke. Dette inkluderer tapet og nøyaktigheten (for klassifiseringsproblemer) og tapet og nøyaktigheten for valideringsdatasettet hvis et er satt.
Historieobjektet returneres fra kall til fit()-funksjonen som brukes til å trene modellen. Beregninger lagres i en ordbok i historikkmedlemmet til det returnerte objektet.
Du kan for eksempel liste opp beregningene som er samlet inn i et historieobjekt ved å bruke følgende kodebit etter at en modell er trent:
# list all data in history
print(history.history.keys())
Utgang:
['accuracy', 'loss', 'val_accuracy', 'val_loss']
Informasjonstype
Du kan tenke på at informasjonen i treningsdataene er av to typer:
- signal: Signalet er den delen som generaliserer, den delen som kan hjelpe modellen vår til å lage spådommer fra nye data.
- Støy: Støyen er den delen som bare gjelder treningsdataene; støyen er alle de tilfeldige svingningene som kommer fra data i den virkelige verden eller alle de tilfeldige, ikke-informative mønstrene som faktisk ikke kan hjelpe modellen med å lage spådommer. Støyen er at delen kan se nyttig ut, men er det egentlig ikke.
Når vi trener en modell, har vi plottet tapet på treningssettet epoke for epoke. Til dette legger vi også et plott av valideringsdataene. Disse plottene kaller vi læringskurvene. For å trene dyplæringsmodeller effektivt, må vi være i stand til å tolke dem.
I figuren ovenfor kan vi se at treningstapet avtar etter hvert som epokene øker, men valideringstapet avtar først og øker når modellen begynner å fange opp støy som er tilstede i datasettet. Nå skal vi se hvordan du unngår overtilpasning i ConvNets gjennom ulike teknikker.
Metoder for å unngå overtilpasning
Nå som vi har sett noen scenarier og hvordan tolke læringskurver for å oppdage overtilpasning. la oss sjekke noen metoder for å unngå overtilpasning i et nevralt nettverk:
Metode 1: Bruk mer data
Å øke størrelsen på datasettet ditt kan hjelpe modellen til å generalisere bedre ettersom den har flere forskjellige eksempler å lære av. Modellen vil finne viktige mønstre tilstede i datasettet og ignorere støy ettersom modellen innser at de spesifikke mønstrene (støy) ikke er tilstede i hele datasettet.
Metode 2: Tidlig stopp
Tidlig stopp er en teknikk som brukes for å forhindre overtilpasning ved å overvåke ytelsen til modellen på et valideringssett under trening. Treningen stoppes når ytelsen på valideringssettet begynner å bli dårligere, noe som indikerer at modellen begynner å overfitte. Vanligvis brukes et eget valideringssett for å overvåke ytelsen, og treningen stoppes når ytelsen ikke har forbedret seg i et spesifisert antall epoker.
Metode 3: Frafall
Vi vet at overtilpasning er forårsaket av at nettverket lærer falske mønstre (støy) i treningsdataene. For å gjenkjenne disse falske mønstrene vil et nettverk ofte stole på svært bestemte kombinasjoner av vekt, en slags "konspirasjon" av vekter. Siden de er så spesifikke, har de en tendens til å være skjøre: fjern en og konspirasjonen faller fra hverandre.
Dette er tanken bak frafall. For å bryte opp disse konspirasjonene, dropper vi tilfeldig ut en brøkdel av et lags input-enheter hvert trinn i treningen, noe som gjør det mye vanskeligere for nettverket å lære de falske mønstrene i treningsdataene. I stedet må den søke etter brede, generelle mønstre, hvis vektmønstre har en tendens til å være mer robuste.
Du kan også tenke på frafall som å skape et slags ensemble av nettverk. Spådommene vil ikke lenger gjøres av ett stort nettverk, men i stedet av en komité med mindre nettverk. Enkeltpersoner i komiteen har en tendens til å gjøre forskjellige typer feil, men ha rett på samme tid, noe som gjør komiteen som helhet bedre enn noen enkeltperson. (Hvis du er kjent med tilfeldige skoger som et ensemble av beslutningstrær, er det samme ideen.)
Metode 4: Batch-normalisering
Den neste spesielle metoden vi skal se på utfører "batch-normalisering" (eller "batchnorm"), som kan hjelpe til med å korrigere trening som er langsom eller ustabil.
Med nevrale nettverk er det generelt en god idé å sette alle dataene dine på en felles skala, kanskje med noe som scikit-learns StandardScaler eller MinMaxScaler. Årsaken er at SGD vil flytte nettverksvektene i forhold til hvor stor aktivering dataene gir. Funksjoner som har en tendens til å produsere aktiveringer av svært forskjellige størrelser kan gi ustabil treningsatferd.
Nå, hvis det er bra å normalisere dataene før de går inn i nettverket, vil kanskje også normalisering inne i nettverket være bedre! Faktisk har vi en spesiell type lag som kan gjøre dette, batch-normaliseringslaget. Et batch-normaliseringslag ser på hver batch etter hvert som den kommer inn, normaliserer først batchen med sitt eget gjennomsnitt og standardavvik, og legger deretter også dataene på en ny skala med to trenbare reskaleringsparametere. Batchnorm utfører faktisk en slags koordinert skalering av inngangene.
Oftest legges batchnorm til som en hjelp til optimaliseringsprosessen (selv om det noen ganger også kan hjelpe til med prediksjonsytelse). Modeller med batchnorm har en tendens til å trenge færre epoker for å fullføre opplæring. Dessuten kan batchnorm også fikse ulike problemer som kan føre til at treningen "blir fast". Vurder å legge til batch-normalisering til modellene dine, spesielt hvis du har problemer under trening.
Metode5: L1 og L2 Regularisering
L1- og L2-regularisering er teknikker som brukes for å forhindre overtilpasning ved å straffe store vekter i det nevrale nettverket. L1-regularisering legger til et straffeledd til tapsfunksjonen proporsjonalt med den absolutte verdien av vektene. Det oppmuntrer til sparsomhet i vektene og kan føre til funksjonsvalg. L2-regularisering, også kjent som vektnedgang, legger til et straffeledd proporsjonalt med kvadratet av vektene til tapsfunksjonen. Det forhindrer at vektene blir for store og oppmuntrer til å fordele vektene jevnere.
Valget mellom L1- og L2-regularisering avhenger ofte av det spesifikke problemet og de ønskede egenskapene til modellen.
Å ha store verdier for L1/L2-regularisering vil føre til at modellen ikke lærer fort og når et platå i læringen som fører til at modellen blir dårligere.
Metode6: Dataforsterkning
Den beste måten å forbedre ytelsen til en maskinlæringsmodell på er å trene den på mer data. Jo flere eksempler modellen har å lære av, jo bedre vil den kunne gjenkjenne hvilke forskjeller i bilder som betyr noe og hvilke som ikke gjør det. Mer data hjelper modellen til å generalisere bedre.
En enkel måte å få mer data på er å bruke dataene du allerede har. Hvis vi kan transformere bildene i datasettet vårt på måter som bevarer klassen (eksempel: MNIST-sifferklassifisering hvis vi prøver utvidelse 6 vil det være vanskelig å skille mellom 6 og 9), kan vi lære klassifikatoren vår å ignorere den typen transformasjoner. For eksempel, om en bil vender mot venstre eller høyre på et bilde, endrer ikke det faktum at det er en bil og ikke en lastebil. Så hvis vi utvider treningsdataene våre med snudde bilder, vil klassifisereren vår lære at "venstre eller høyre" er en forskjell den bør ignorere.
Og det er hele ideen bak dataforstørrelse: legg til noen ekstra falske data som ser rimelig ut som de virkelige dataene, og klassifisereren din vil forbedres.
Husk at nøkkelen til å unngå overtilpasning er å sørge for at modellen din generaliserer godt. Sjekk alltid modellens ytelse på et valideringssett, ikke bare treningssettet.
Implementering av ovennevnte metoder med data
La oss utforske implementeringstrinn for metodene ovenfor:
Trinn 1: Laster nødvendige biblioteker
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')
Trinn 2: Lasting av datasett og forhåndsbehandling
#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
Trinn 3: Lære datasett
x_train.shape, y_train.shape, x_test.shape, y_test.shape
Utgang:
np.unique(y_train)
Utgang:
#These labels are in the order and taken from the documentaion
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
'dog', 'frog', 'horse', 'ship', 'truck']
Trinn 4: Visualisere bilde fra datasett
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()
La oss nå initialisere hyperparametere og kompilere modell med optimizer, tapsfunksjon og evalueringsmetrikk.
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'])
Trinn 6: Treningsmodell
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))
Trinn 7: Evaluer modellen
Disse vil fortelle oss informasjonen i historieobjektet, og vi bruker dem til å lage informasjonskurvene våre.
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)
Fra kurvene kan vi se at valideringsnøyaktigheten når et platå etter 4. epoke og modellen begynner å fange opp støy. Derfor vil vi implementere tidlig stopp for å unngå at modellen blir overmontert og gjenopprette de beste vektene basert på val_tap. Vi vil bruke val_loss for å overvåke tidlig stopp ettersom det nevrale nettverket vårt prøver å redusere tap ved hjelp av optimerere. Nøyaktighet og valideringsnøyaktighet avhenger av terskelen (en sannsynlighet for å skille klasser – vanligvis 0.5 for binær klassifisering), så hvis datasettet vårt er ubalansert, vil det være tap vi bør bekymre oss for i de fleste tilfellene.
Trinn 8: Implementering av tidlig stopp
Siden vi ikke er bekymret for at modellen vår skal overfitte, vil tidlig stopp unngå at modellen vår skjer. Det er et godt valg å velge et høyere antall epoker og en passende tålmodighet. Nå skal vi bruke samme modellarkitektur og trene med tidlig stoppende tilbakeringing.
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)
Å kjenne våre beste vekter som modellen har tatt.
print('Testing ..................')
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print('test_loss : ', test_loss, 'test_accuracy : ', test_acc)
Trinn 9: Økende modellkompleksitet
Siden vår modell ikke gir gode resultater og undertilpasser siden den ikke er i stand til å fange nok data. Vi bør øke modellens kompleksitet og evaluere.
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()
Vi kan se at det er en økning i de totale parameterne. Dette vil bidra til å finne mer komplekse sammenhenger i modellen vår. Merk: Vårt datasett består av 32X32 bilder; dette er relativt små bilder. Derfor vil bruk av mer komplekse modeller i begynnelsen helt sikkert overpasse modellen, og derfor har vi en tendens til å øke modellens kompleksitet sakte.
# 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)
Fra grafene ovenfor kan vi tydelig si at modellen er overtilpasset, derfor vil vi bruke en annen metode som heter Drop out normalization og Batch normalization.
Trinn 10: Bruk avfallslag og batchnormaliseringslag
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)
Fra læringsgrafene kan vi se at modellen er overtilpasset selv med batchnormalisering og dropout-lag. Derfor i stedet for å øke kompleksiteten, men øke antallet filtre. Vi vil legge til flere konvolusjonslag for å trekke ut flere funksjoner.
Trinn 11: Øke konvolusjonslag
Reduser den trenerbare parameteren, men øk konvolusjonslagene for å trekke ut flere funksjoner.
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)
Fra utgangs- og læringskurven ovenfor kan vi slutte at modellen har prestert veldig bra og har unngått overtilpasning. Treningsnøyaktigheten og valideringsnøyaktigheten er veldig nær. I dette scenariet trenger vi ikke flere metoder for å redusere overtilpasning. Likevel vil vi utforske L1/L2-regularisering.
Trinn 12: Bruke L1/L2-regularisering
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)
Nå kan vi se at L1/L2-regularisering selv etter å ha brukt en lav straffescore på 0.0001, gjorde at modellen vår underfittet med 4 %. Derfor er det tilrådelig å bruke alle metodene forsiktig sammen. Ettersom batchnormalisering og -regularisering påvirker modellen på lignende måte, trenger vi ikke L1/L2-regularisering.
Trinn 13: Dataforsterkning
Vi vil bruke ImageDataGenerator fra tensorflow-keras.
# 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()
Dette er fire utvidede bilder og ett originalbilde.
# 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)
Vi har brukt tqdm-biblioteket for å vite fremdriften til utvidelsen vår.
x_train_augmented.shape, y_train_augmented.shape
Dette er datasettet vårt etter utvidelse. La oss nå bruke dette datasettet og trene modellen vår.
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)
Vi kan se at modellen er mer generalisert og en nedgang i tap. Vi har også fått bedre valideringsnøyaktighet. Derfor har dataforsterkning økt modellnøyaktigheten vår.
konklusjonen
Overtilpasning er et vanlig problem i dyp læring, spesielt med komplekse nevrale nettverksarkitekturer som ConvNets. Utøvere kan forhindre overtilpasning i ConvNets ved å forstå de grunnleggende årsakene og gjenkjenne scenarier der det oppstår. Teknikker som tidlig stopp, frafall, batchnormalisering, regularisering og dataforsterkning kan bidra til å redusere dette problemet. Implementering av disse teknikkene på CIFAR-10-datasettet viste betydelige forbedringer i modellgeneralisering og ytelse. Å mestre disse teknikkene og forstå prinsippene deres kan føre til robuste og pålitelige nevrale nettverksmodeller.
Ofte Stilte Spørsmål
A. Overtilpasning oppstår når en modell lærer treningsdataene for godt, inkludert støy og irrelevante mønstre, noe som resulterer i dårlig ytelse på nye, usynlige data. Det er et problem fordi overmonterte modeller ikke klarer å generalisere effektivt, noe som begrenser deres praktiske nytte.
A. Du kan oppdage overtilpasning i ConvNets ved å tolke læringskurvene, som plotter trenings- og valideringsberegningene (f.eks. tap, nøyaktighet) over epoker. Hvis valideringsberegningene slutter å forbedre seg eller begynner å bli nedverdigende mens treningsmålene fortsetter å forbedres, er det et tegn på overtilpasning.
A. Tidlig stopp er en teknikk som overvåker modellens ytelse på et valideringssett under trening og stopper treningsprosessen når ytelsen på valideringssettet begynner å bli dårligere, noe som indikerer overfitting. Det bidrar til å forhindre at modellen overfiter ved å stoppe treningen til rett tid.
A. Dataforsterkning er prosessen med å generere nye, syntetiske treningsdata ved å bruke transformasjoner (f.eks. bla, rotere, skalere) på eksisterende data. Det hjelper modellen med å generalisere bedre ved å eksponere den for flere forskjellige eksempler, og reduserer risikoen for overtilpasning i ConvNets til de begrensede treningsdataene.
- SEO-drevet innhold og PR-distribusjon. Bli forsterket i dag.
- PlatoData.Network Vertical Generative Ai. Styrk deg selv. Tilgang her.
- PlatoAiStream. Web3 Intelligence. Kunnskap forsterket. Tilgang her.
- PlatoESG. Karbon, CleanTech, Energi, Miljø, Solenergi, Avfallshåndtering. Tilgang her.
- PlatoHelse. Bioteknologisk og klinisk etterretning. Tilgang her.
- kilde: https://www.analyticsvidhya.com/blog/2024/04/understanding-overfitting-in-convnets/