Bildedataforsterkning for dyp læring

Forstå hva som er bildedataforstørrelse og hvordan du bruker det ved å bruke Keras for dyplæringsprosjektene dine

Photo by Chris Lawton on Unsplash

Hvis du noen gang har prøvd å utføre bildegjenkjenning ved hjelp av dyp læring, vet du viktigheten av et godt datasett for trening. Det er imidlertid ikke alltid lett å finne nok bilder for trening, og nøyaktigheten til modellen din er direkte avhengig av kvaliteten på treningsdataene.

Heldigvis finnes det teknikker du kan bruke for å supplere bildedatasettet som de bruker til trening. En av teknikkene kalles bildedataforstørrelse. I denne artikkelen vil jeg diskutere hva som er bildedataforstørrelse, hvordan det fungerer, hvorfor er det nyttig i dyp læring, og til slutt hvordan man utfører bildedataforstørrelse ved hjelp av Keras-biblioteket.

Bildedataforstørrelse er en teknikk som lager nye bilder fra eksisterende. For å gjøre det, gjør du noen små endringer i dem, for eksempel å justere lysstyrken på bildet, eller rotere bildet, eller forskyve motivet i bildet horisontalt eller vertikalt.

Bildeforstørrelsesteknikker lar deg kunstig øke størrelsen på treningssettet ditt, og dermed gi mye mer data til modellen din for trening. Dette lar deg forbedre nøyaktigheten til modellen din ved å forbedre modellens evne til å gjenkjenne nye varianter av treningsdataene dine.

Typer bildedataforsterkning

Bildeforstørrelse kommer i mange former, her er noen av de vanlige - Vertikal skift, Horisontal skift, Vertikal vending, Horisontal vending, Rotasjon, Justering av lysstyrke og Zoom inn/ut.

Jeg vil først demonstrere de ulike bildeforstørrelsesteknikkene ved hjelp av Python og Keras. Hvis du vil prøve med, sørg for at du har følgende programvare og pakker installert:

Når Anaconda og TensorFlow er installert, lag en ny Jupyter Notebook.

Vertikal forskyvning

Den første bildeforstørrelsesteknikken jeg vil vise er vertikal forskyvning. De vertikal forskyvning flytter bildet tilfeldig vertikalt opp eller ned. For dette eksemplet skal jeg bruke et bilde som heter 747.jpg, som ligger i samme mappe som Jupyter Notebook.

Bildekilde: https://commons.wikimedia.org/wiki/File:Qantas_Boeing_747-438ER_VH-OEI_at_LAX.jpg. Denne filen er lisensiert under Creative Commons Attribution-Share Alike 2.0 Generisk lisens.

Følgende kodebit bruker ImageDataGenerator klasse i Keras for å flytte bildet vertikalt.

De ImageDataGenerator klasse fra Keras genererer grupper med bildedata med sanntidsdataforsterkning.

#---importer modulene---
importer nummen som np
importer matplotlib.pyplot som plt
fra tensorflow.keras.preprocessing.image import load_img
fra tensorflow.keras.preprocessing.image import img_to_array
fra tensorflow.keras.preprocessing.image import ImageDataGenerator
#---last inn bildet---
image_filename = '747.jpg'
img = load_img(bildefilnavn)
#---konverter bildet til 3D-array---
bildedata = img_to_array(img)
#---konvertere til en 4-D matrise med 1 element av 3D matrise som representerer
# bildet---
images_data = np.expand_dims(image_data, axis=0)
#---lag generator for bildedataforstørrelse---
datagen = ImageDataGenerator(width_shift_range=0.2)
#---forbered iteratoren; flow() tar inn en 4D-matrise og returnerer
# en iterator som inneholder en gruppe bilder---
train_generator = datagen.flow(images_data, batch_size=1)
rader = 5
kolonner = 4
#---plott 5 rader og 4 kolonner---
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
#---hent det neste bildet i batchen (ett bilde siden batch
# størrelse er 1)---
image_batch = train_generator.next()

#---konverter til usignerte heltall for visning---
image = image_batch[0].astype('uint8')

#---vis bildet---
akser[r,c].imshow(bilde)
#---sett størrelsen på figuren---
fig.set_size_inches(15,10)

Kodebiten ovenfor produserer følgende utdata:

Som du kan se fra utgangen ovenfor, hver gang du ringer next() metoden fra train_generator objekt, får du et bilde som er litt endret. I kodebiten ovenfor returneres et nytt bilde som er forskjøvet med 20 % basert på den opprinnelige bildehøyden hver gang du ringer next() metode:

datagen = ImageDataGenerator(width_shift_range=0.2)

Interessant nok for denne versjonen av ImageDataGenerator (tensorflow.keras.preprocessing.image) klasse, som spesifiserer width_shift_range parameter forskyver bildet vertikalt, i stedet for horisontalt (som er oppførselen til den eldreImageDataGeneratorfra keras.preprocessing.image modul). På samme måte, hvis du vil at bildet skal forskyves horisontalt, må du bruke height_shift_range parameter (se neste avsnitt).

Legg merke til at next() metoden vil returnere et utvidet bilde så mange ganger du vil. I kodebiten ovenfor kalte vi den 20 ganger (5 rader ganger 4 kolonner).

Horisontal forskyvning

Du kan nå prøve å flytte bildet horisontalt ved å bruke height_shift_range parameter:

datagen = ImageDataGenerator(height_shift_range=0.2)
train_generator = datagen.flow(images_data, batch_size=1)
rader = 5
kolonner = 4
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

Kodebiten ovenfor produserer følgende utdata:

Horisontal flip

Noen ganger er det fornuftig å snu bildet horisontalt. Når det gjelder et fly, kan fronten av flyet vende mot venstre eller høyre:

datagen = ImageDataGenerator(horizontal_flip=Sant)
train_generator = datagen.flow(images_data, batch_size=1)
rader = 2
kolonner = 2
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

For kodebiten ovenfor er det godt nok å generere fire bilder, da fronten av flyet enten kan være vendt mot venstre eller høyre:

Husk at vendingen er tilfeldig (noen ganger får du alle de fire originalbildene, og noen ganger får du bilder som vendes horisontalt). Det er sannsynlig at fire bilder ovenfor kan alle være like. Hvis det skjer, bare kjør den kodeblokken på nytt.

Vertikal vipp

Akkurat som horisontal vending, kan du også utføre vertikal vending:

datagen = ImageDataGenerator(vertical_flip=Sant)
train_generator = datagen.flow(images_data, batch_size=1)
rader = 2
kolonner = 2
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

Når det gjelder fly, er det kanskje ikke særlig fornuftig å snu flyet vårt opp ned! Hvis du prøver å utføre bildegjenkjenning, er sjansen stor for at bildene dine av fly står oppreist, og derfor er det kanskje ikke så vanlig å trene modellen din til å gjenkjenne opp-ned-plan. For andre tilfeller gir vertikal flipping mye mening.

Rotasjon

Rotasjon, som navnet tilsier, roterer bildet ditt. Dette ville være veldig nyttig for flybildet vårt. Følgende kodebiter roterer bildet tilfeldig opptil 50 grader:

datagen = ImageDataGenerator(rotasjonsområde=50)
train_generator = datagen.flow(images_data)
rader = 5
kolonner = 4
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

Med rotasjon viser utgangen flyene i de forskjellige posisjonene - simulerer start- og landingsposisjonene:

Lysstyrke

En annen forstørrelsesteknikk er å justere lysstyrken på bildet. Følgende kodebit angir en rekke lysstyrkeskiftverdier:

datagen = ImageDataGenerator(lysstyrkeområde=[0.15,2.0])
train_generator = datagen.flow(images_data, batch_size=1)
rader = 5
kolonner = 4
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

Utgangen inneholder en serie bilder med varierende lysstyrke:

zooming

Du kan også zoome inn eller ut på bildene:

datagen = ImageDataGenerator(zoom_range=[5,0.5])
train_generator = datagen.flow(images_data, batch_size=1)
rader = 5
kolonner = 4
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

Utgangen viser bildet i de forskjellige zoomforholdene:

Legg merke til at zooming av bildene vil endre sideforholdet til bildene.

Kombinere alle utvidelsene

Selvfølgelig kan alle de forskjellige forstørrelsesteknikkene som jeg har diskutert så langt kombineres:

datagen = ImageDataGenerator(width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=Sant,
rotasjonsområde=50,
lysstyrkeområde=[0.15,2.0],
zoom_range=[5,0.5]
)
train_generator = datagen.flow(images_data, batch_size=1)rader = 8
kolonner = 8
fig, akser = plt.subplots(rows,columns)
for r i område(rader):
for c i området (kolonner):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akser[r,c].imshow(bilde)
fig.set_size_inches(15,10)

Legg merke til at jeg har utelatt vertikal flip da det ikke gir mening for vårt eksempel.

Utgangen viser nå bildet med de forskjellige utvidelsene som er brukt:

De forrige delene viste det grunnleggende om bildedataforstørrelse og hvordan det kan brukes på et enkelt bilde. I dyp læring har vi ofte å gjøre med et sett med bilder. Så la oss nå se hvordan bildeforstørrelse kan brukes på et sett med bilder. For illustrasjoner vil jeg anta at i mappen som inneholder Jupyter Notebook, har du en Frukt mappe og følgende undermapper:

Frukt
|__banan
|__banana1.jpg
|__banana2.jpg
|__banana3.jpg
|__ ...
|__durian
|__durian1.jpg
|__durian2.jpg
|__durian3.jpg
|__ ...
|__oransje
|__oransje1.jpg
|__oransje2.jpg
|__oransje3.jpg
|__ ...
|__jordbær
|__jordbær1.jpg
|__jordbær2.jpg
|__jordbær3.jpg
|__ ...

Hver undermappe inneholder et sett med bilder. For eksempel banan mappen inneholder et antall navngitte bilder banan1.jpg, banan2.jpg, og så videre. Navnet på undermappene vil tjene som etiketter for de forskjellige bildene. Dette betyr at alle filene under banan mappen inneholder bilder av banan, og så videre.

For å laste en serie bilder fra disk, kaller du nå flow_from_directory() metode av ImageDataGenerator instans i stedet for flow() metode (for å laste bilder fra minnet):

train_datagen = ImageDataGenerator(
horizontal_flip=Sant,
vertical_flip=Sant,
rotasjonsområde=50,
)
batch_size = 8toggenerator = train_datagen.flow_from_directory(
'./Frukt',
target_size=(224,224),
color_mode='rgb',
batch_size=batch_size,
class_mode='categorical',
shuffle=True)

Legg merke til at jeg nå stiller inn batch_size til 8. Du vil se bruken av batchstørrelsen snart.

Ved å bruke iteratoren som returneres, kan jeg finne etikettene for de forskjellige fruktene (banan, durian, appelsin og jordbær):

klasse_ordbok = tog_generator.klasse_indekser#---lag en ordbok med etiketter---
class_dictionary = { verdi:nøkkel for nøkkel, verdi i
class_dictionary.items()}
#---konverter ordboken til en liste---
class_list = [verdi for _,verdi i class_dictionary.items()]
print(klasse_liste)

Du vil se følgende utdata:

Fant 54 bilder som tilhører 4 klasser.
['banan', 'durian', 'oransje', 'jordbær']

I alt er det totalt 54 bilder i 4 mapper. Også class_list variabelen inneholder listen over frukter.

Jeg skal nå skrive ut settet med utvidede bilder som er laget av ImageDataGenerator klasse. Jeg vil vilkårlig sette radene til 10, og for hver rad vil jeg skrive ut partiet med bilder som er returnert (som er 8 i dette eksemplet):

rader = 10fig, akser = plt.subplots(rows, batch_size)for r i område(rader):    
#---hent partiet med utvidede bilder---
image_batch = train_generator.next()
#---få antall bilder returnert---
images_count = image_batch[0].shape[0]

for c i området(images_count):
#---konverter til usignerte heltall for visning---
image = image_batch[0][c].astype('uint8')

#---vis bildet---
akser[r,c].imshow(bilde)

#---vis etiketten til bildet---
akser[r,c].tittel.sett_tekst(
klasseliste[np.argmax(bildebatch[1][c])])
#---skjuler x og y-merker---
akser[r,c].set_xticks([])
akser[r,c].set_yticks([])
fig.set_size_inches(15,18)

Siden batch_size er nå satt til 8 (og ikke lenger 1), den train_generator.next() metoden vil returnere deg en batch med åtte utvidede bilder hver gang du ringer det. Antall bilder som returneres er basert på batch_size som du satte tidligere i flow_from_directory() metode:

train_generator = train_datagen.flow_from_directory(
'./Frukt',
target_size=(224,224),
color_mode='rgb',
batch_size=batch_size, # batch_size = 8
class_mode='categorical',
shuffle=True)

Verdien av image_batch variabel (returnert av next() metode) er en tuppel av to elementer:

  • Det første elementet (image_batch[0]) er en rekke Partistørrelse, Gruppestørrelse bilder (4D-array)
  • Det andre elementet (image_batch[1]) inneholder etikettene for bildene

Kodebiten ovenfor produserer følgende utdata:

Legg merke til at på den syvende raden er det to tomme diagrammer uten bilder. Husk at det er totalt 54 bilder i bildesettet, og siden hver batch returnerer 8 bilder (per rad), vil de første syv radene vise totalt 54 bilder (8×6 + 6). Følgende figur gjør det klart:

Merk at du kan stille inn rows til et hvilket som helst nummer og ImageDataGenerator klasse vil fortsette å generere nye utvidede bilder for deg.

Bygge en modell ved hjelp av overføringslæring

Du vet nå hvordan du bruker ImageDataGenerator for å laste inn sett med bilder fra disk for utvidelse. Men hvordan bruker du den til trening? Følgende kodebit viser hvordan du bygger en dyp læringsmodell ved hjelp av overføre læring.

Overføringslæring er en maskinlæringsmetode der en modell utviklet for en oppgave gjenbrukes som utgangspunkt for en modell på en andre oppgave. Overføringslæring reduserer tiden du trenger å bruke på trening.

fra tensorflow.keras.models import Modell
fra tensorflow.keras.applications import VGG16
fra tensorflow.keras.layers importer Dense, GlobalAveragePooling2D
#---antall frukt---
NO_CLASSES = max(train_generator.class_indices.values()) + 1
#---last inn VGG16-modellen som basismodell for trening---
base_model = VGG16(include_top=False, input_shape=(224, 224, 3))
#---legg til våre egne lag---
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024,activation='relu')(x) # legg til tette lag så
# at modellen kan
# lære mer komplekst
# funksjoner og
# klassifisere for bedre
# resultater.
x = Tett(1024,aktivering='relu')(x) # tett lag 2
x = Tett(512,aktivering='relu')(x) # tett lag 3
preds = Tett(NO_CLASSES,
activation='softmax')(x) # siste lag med
# softmax-aktivering
#---lag en ny modell med basismodellens original
# input og den nye modellens utgang ---
modell = Modell(innganger = base_model.input, utganger = preds)
#---ikke tren de første 19 lagene - 0..18---
for lag i model.layers[:19]:
layer.trainable=False
#---trene resten av lagene - 19 og utover---
for lag i model.layers[19:]:
layer.trainable=Sant

#---kompiler modellen---
model.compile(optimizer='Adam',
loss='categorical_crossentropy',
metrics=['nøyaktighet'])

Å forklare hvordan overføringslæring fungerer er utenfor denne artikkelens omfang. Jeg lar det ligge til en annen artikkel.

Bruke de genererte bildene til trening

For å bruke de utvidede bildene til trening, bestå train_generator inn fit() metode for modellen:

#---trene modellen---
step_size_train = train_generator.n // train_generator.batch_size
model.fit(toggenerator,
steps_per_epoch=step_size_train,
epoker=15)

De steps_per_epoch parameter betyr i utgangspunktet hvor mange trinn som er det i en epoke - det er avhengig av antall bilder du har og batchstørrelsen definert tidligere. Hvis du setter dette til et høyt tall, gjør du repeterende trening. Du bør angi den basert på denne formelen:

antall bilder / batchstørrelse

I vårt eksempel har vi totalt 54 bilder. Og så i hver epoke ImageDataGenerator klasse vil forvandle alle de 54 bildene for trening. I hver epoke vil modellen få forskjellige varianter av bildene. Hvis du har 15 epoker, vil totalt 15×54 variasjoner av bildene bli generert og matet inn i treningsmodellen.

De ImageDataGenerator klasse lar modellen din motta nye varianter av bildene i hver epoke. Men husk at det bare returnerer de transformerte bildene og ikke legger det til settet med bilder du har.

Jeg håper denne artikkelen har gitt deg en god idé om hva bildedataforstørrelse handler om og hvorfor du trenger dem i opplæringen av dyplæringsmodellene dine. Spesielt har jeg demonstrert det ved å bruke Keras-modulen i TensorFlow-biblioteket.

Bildedataforsterkning for dyp læring publisert på nytt fra kilde https://towardsdatascience.com/image-data-augmentation-for-deep-learning-77a87fabd2bf?source=rss—-7f60cf5620c9—4 via https://towardsdatascience.com/feed

<!–

->

Tidstempel:

Mer fra Blockchain-konsulenter