Kuvadatan lisäys syvälliseen oppimiseen

Ymmärrä, mitä kuvadatan lisäys on ja miten sitä käytetään Kerasin avulla syväoppimisprojekteissasi

Kuva Chris Lawton on Unsplash

Jos olet joskus yrittänyt suorittaa kuvantunnistusta syväoppimisen avulla, tiedät hyvän tietojoukon tärkeyden koulutuksessa. Riittävien kuvien löytäminen harjoittelua varten ei kuitenkaan ole aina helppoa, ja mallisi tarkkuus riippuu suoraan harjoitustietojen laadusta.

Onneksi on olemassa tekniikoita, joilla voit täydentää kuvatietojoukkoa, jota he käyttävät harjoitteluun. Yksi tekniikoista on ns kuvatietojen lisäys. Tässä artikkelissa käsittelen mitä kuvadatan lisäys on, miten se toimii, miksi se on hyödyllinen syvässä oppimisessa ja lopuksi kuinka kuvadatan lisäys tehdään Keras-kirjaston avulla.

Kuvatietojen lisäys on tekniikka, joka luo uusia kuvia olemassa olevista. Voit tehdä sen tekemällä niihin pieniä muutoksia, kuten säätämällä kuvan kirkkautta, kääntämällä kuvaa tai siirtämällä kohdetta kuvassa vaaka- tai pystysuunnassa.

Kuvanlisäystekniikoiden avulla voit keinotekoisesti kasvattaa harjoitussarjasi kokoa, mikä tarjoaa paljon enemmän tietoa mallillesi harjoittelua varten. Tämän avulla voit parantaa mallisi tarkkuutta parantamalla mallisi kykyä tunnistaa harjoitustietojesi uudet muunnelmat.

Kuvatietojen lisäyksen tyypit

Kuvan lisäystä on monessa muodossa, tässä on joitain yleisimpiä muotoja - Pystysuuntainen siirto, Vaakasuora siirto, Pystysuuntainen käännös, Vaakasuora kääntö, Kierto, Kirkkauden säätö ja Zoom In/Out.

Ensin esittelen erilaisia ​​kuvanlisäystekniikoita Pythonilla ja Kerasilla. Jos haluat kokeilla, varmista, että sinulla on asennettuna seuraavat ohjelmistot ja paketit:

Kun Anaconda ja TensorFlow on asennettu, luo uusi Jupyter Notebook.

Pystysuuntainen siirto

Ensimmäinen kuvan lisäystekniikka, jonka haluan näyttää, on pystysuuntainen siirtymä. pystysuuntainen siirtymä siirtää kuvaa satunnaisesti pystysuunnassa ylös tai alas. Tässä esimerkissä aion käyttää kuvaa nimeltä 747.jpg, joka sijaitsee samassa kansiossa kuin Jupyter-muistikirja.

Kuvan lähde: https://commons.wikimedia.org/wiki/File:Qantas_Boeing_747-438ER_VH-OEI_at_LAX.jpg. Tämä tiedosto on lisensoitu Creative Commons Attribution-Share Alike 2.0 Yleinen lisenssin.

Seuraava koodinpätkä käyttää ImageDataGenerator luokka Kerasissa siirtääksesi kuvaa pystysuunnassa.

- ImageDataGenerator Keras-luokka luo kuvatietoja reaaliaikaisella lisäyksellä.

#---tuo moduulit---
Tuo numerot kuin np
Tuo matplotlib.pyplot plt
osoitteesta tensorflow.keras.preprocessing.image tuonti load_img
osoitteesta tensorflow.keras.preprocessing.image tuonti img_to_array
osoitteesta tensorflow.keras.preprocessing.image tuonti ImageDataGenerator
#---lataa kuva---
image_filename = '747.jpg'
img = load_img(kuvan_tiedostonimi)
#---muunna kuva 3D-taulukkoon---
image_data = img_to_array(img)
#---muuntaa 4-D-taulukko, jossa on 1 elementti 3D-taulukkoa edustavassa
# kuva---
images_data = np.expand_dims(image_data, axis=0)
#---luo kuvatietojen lisäysgeneraattori---
datagen = ImageDataGenerator(width_shift_range=0.2)
#---valmistele iteraattori; flow() ottaa 4D-taulukon ja palauttaa
# iteraattori, joka sisältää joukon kuvia ---
train_generator = datagen.flow(images_data, batch_size=1)
riviä = 5
sarakkeet = 4
#---piirrä 5 riviä ja 4 saraketta ---
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
#---hae erän seuraava kuva (yksi kuva erästä
# koko on 1)---
image_batch = train_generator.next()

#---muunna etumerkittömiksi kokonaisluvuiksi katselua varten---
image = image_batch[0].astype('uint8')

#---näytä kuva---
akselit[r,c].imshow(kuva)
#---asettaa kuvion koon---
fig.set_size_inches(15,10)

Yllä oleva koodinpätkä tuottaa seuraavan tulosteen:

Kuten yllä olevasta lähdöstä näet, joka kerta kun soitat next() menetelmä train_generator kohde, saat kuvan, joka on hieman muuttunut. Yllä olevassa koodinpätkässä uusi kuva, jota on siirretty 20 % sen alkuperäisen kuvan korkeuden perusteella, palautetaan aina, kun soitat next() menetelmä:

datagen = ImageDataGenerator(width_shift_range=0.2)

Mielenkiintoista, tälle versiolle ImageDataGenerator (tensorflow.keras.preprocessing.image) luokka, jossa määritellään width_shift_range parametri siirtää kuvaa pystysuunnassa vaakasuoran sijaan (mikä on vanhemman käyttäytyminenImageDataGeneratormistä keras.preprocessing.image moduuli). Samoin, jos haluat siirtää kuvaa vaakasuunnassa, sinun on käytettävä height_shift_range parametri (katso seuraava osa).

Huomaa, että next() menetelmä palauttaa lisätyn kuvan niin monta kertaa kuin haluat. Yllä olevassa koodinpätkässä kutsuimme sitä 20 kertaa (5 riviä kertaa 4 saraketta).

Vaakasiirto

Voit nyt yrittää siirtää kuvaa vaakasuunnassa käyttämällä height_shift_range parametri:

datagen = ImageDataGenerator(korkeus_siirtoväli=0.2)
train_generator = datagen.flow(images_data, batch_size=1)
riviä = 5
sarakkeet = 4
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Yllä oleva koodinpätkä tuottaa seuraavan tulosteen:

Vaakasuuntainen läppä

Joskus on järkevää kääntää kuvaa vaakasuunnassa. Jos kyseessä on lentokone, koneen etuosa voi olla vasemmalle tai oikealle:

datagen = ImageDataGenerator(horizontal_flip=Tosi)
train_generator = datagen.flow(images_data, batch_size=1)
riviä = 2
sarakkeet = 2
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Yllä olevaa koodinpätkää varten neljän kuvan luominen riittää, koska lentokoneen etuosa voi olla joko vasemmalle tai oikealle:

Muista, että kääntäminen on satunnaista (joskus saat kaikki neljä alkuperäistä kuvaa ja joskus saat kuvia, jotka käännetään vaakasuunnassa). On todennäköistä, että neljä yllä olevaa kuvaa voivat kaikki olla samoja. Jos näin tapahtuu, suorita kyseinen koodilohko uudelleen.

Pystysuuntainen läppä

Samoin kuin vaakasuuntaisen käännön, voit myös kääntää pystysuunnassa:

datagen = ImageDataGenerator(vertical_flip=Tosi)
train_generator = datagen.flow(images_data, batch_size=1)
riviä = 2
sarakkeet = 2
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Lentokoneiden tapauksessa ei ehkä ole kovin järkevää kääntää lentokonetta ylösalaisin! Jos yrität suorittaa kuvantunnistusta, on todennäköistä, että kuvasi tasoista ovat pystyssä, joten mallin kouluttaminen tunnistamaan ylösalaisin olevia tasoja ei välttämättä ole liian yleistä. Muissa tapauksissa pystysuuntaisella kääntämisellä on paljon järkeä.

Kierto

Rotation, kuten nimestä voi päätellä, kääntää kuvaasi. Tämä olisi erittäin hyödyllinen lentokonekuvamme kannalta. Seuraavat koodinpätkät kääntävät kuvaa satunnaisesti jopa 50 astetta:

datagen = ImageDataGenerator(rotation_range=50)
train_generator = datagen.flow(images_data)
riviä = 5
sarakkeet = 4
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Kääntyessä tulos näyttää lentokoneet eri asennoissa – simuloiden nousu- ja laskuasentoa:

Kirkkaus

Toinen lisäystekniikka on kuvan kirkkauden säätäminen. Seuraava koodinpätkä asettaa joukon kirkkauden muutosarvoja:

datagen = ImageDataGenerator(brightness_range=[0.15,2.0])
train_generator = datagen.flow(images_data, batch_size=1)
riviä = 5
sarakkeet = 4
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Tulos sisältää sarjan kuvia, joiden kirkkaus vaihtelee:

zoomaus

Voit myös lähentää tai loitontaa kuvia:

datagen = ImageDataGenerator(zoom_range=[5,0.5])
train_generator = datagen.flow(images_data, batch_size=1)
riviä = 5
sarakkeet = 4
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Tulos näyttää kuvan eri zoomaussuhteissa:

Huomaa, että kuvien zoomaus muuttaa kuvien kuvasuhteita.

Yhdistämällä kaikki lisäykset

Tietenkin kaikki erilaiset lisäystekniikat, joista olen tähän mennessä keskustellut, voidaan yhdistää:

datagen = ImageDataGenerator(width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip = Totta,
rotation_range=50,
brightness_range=[0.15,2.0],
zoom_range=[5,0.5]
)
train_generator = datagen.flow(images_data, batch_size=1)riviä = 8
sarakkeet = 8
kuva, akselit = plt.subplots (rivit, sarakkeet)
r:lle alueella (rivit):
c:lle alueella (sarakkeet):
image_batch = train_generator.next()
image = image_batch[0].astype('uint8')
akselit[r,c].imshow(kuva)
fig.set_size_inches(15,10)

Huomaa, että olen jättänyt pystysuoran käännön pois, koska se ei ole järkevää esimerkissämme.

Tulos näyttää nyt kuvan erilaisilla lisäyksillä:

Edellisissä osissa esiteltiin kuvatietojen lisäämisen perusteet ja kuinka sitä voidaan soveltaa yhteen kuvaan. Syväoppimisessa käsittelemme usein joukkoa kuvia. Katsotaanpa nyt, kuinka kuvan lisäystä voidaan soveltaa kuvasarjaan. Kuvien osalta oletan, että kansiossa, joka sisältää Jupyter-muistikirjan, sinulla on a Hedelmät kansio ja seuraavat alikansiot:

Hedelmät
|__banaani
|__banaani1.jpg
|__banaani2.jpg
|__banaani3.jpg
|__ ...
|__durian
|__durian1.jpg
|__durian2.jpg
|__durian3.jpg
|__ ...
|__oranssi
|__oranssi1.jpg
|__oranssi2.jpg
|__oranssi3.jpg
|__ ...
|__mansikka
|__mansikka1.jpg
|__mansikka2.jpg
|__mansikka3.jpg
|__ ...

Jokainen alikansio sisältää joukon kuvia. Esimerkiksi, banaani kansio sisältää useita nimettyjä kuvia banaani1.jpg, banaani2.jpg, ja niin edelleen. Alikansioiden nimet toimivat eri kuvien nimikkeinä. Tämä tarkoittaa, että kaikki tiedostot banaani kansio sisältää kuvia banaanista ja niin edelleen.

Jos haluat ladata kuvasarjan levyltä, soita nyt flow_from_directory() menetelmä ImageDataGenerator esimerkki sijasta flow() menetelmä (kuvien lataamiseen muistista):

train_datagen = ImageDataGenerator(
horizontal_flip = Totta,
vertical_flip = Totta,
rotation_range=50,
)
erän_koko = 8train_generator = train_datagen.flow_from_directory(
'./Hedelmät',
target_size=(224,224 XNUMX),
color_mode='rgb',
batch_size=erän_koko,
class_mode='categorical',
shuffle=True)

Huomaa, että olen nyt määrittänyt batch_size 8. Näet pian eräkoon käytön.

Palautetun iteraattorin avulla löydän eri hedelmien (banaani, durian, appelsiini ja mansikka) etiketit:

class_dictionary = train_generator.class_indexes#---luo tunnistesanakirja---
class_dictionary = { arvo:avain avaimelle,arvo sisään
class_dictionary.items()}
#---muuta sanakirja luetteloksi---
class_list = [arvo kohteelle _,arvo kohdassa class_dictionary.items()]
print(class_list)

Näet seuraavan tuloksen:

Löytyi 54 kuvaa, jotka kuuluvat 4 luokkaan.
['banaani', 'durian', 'appelsiini', 'mansikka']

Kaikkiaan 54 kansiossa on yhteensä 4 kuvaa. Myös, class_list muuttuja sisältää luettelon hedelmistä.

Tulostan nyt joukon lisättyjä kuvia, jotka on luotu ImageDataGenerator luokkaa. Asetan rivit mielivaltaisesti 10:ksi, ja haluan tulostaa jokaiselle riville palautettujen kuvien erän (joka tässä esimerkissä on 8):

riviä = 10kuva, akselit = plt.subplots(rivit,erän_koko)r:lle alueella (rivit):    
#---hae joukko lisättyjä kuvia---
image_batch = train_generator.next()
#---hae palautettujen kuvien määrä---
kuvien_määrä = image_batch[0].shape[0]

c:lle alueella(images_count):
#---muunna etumerkittömiksi kokonaisluvuiksi katselua varten---
image = image_batch[0][c].astype('uint8')

#---näytä kuva---
akselit[r,c].imshow(kuva)

#---näytä kuvan nimi---
axes[r,c].title.set_text(
class_list[np.argmax(image_batch[1][c])])
#---piilottaa x- ja y-rastit---
axes[r,c].set_xticks([])
axes[r,c].set_yticks([])
fig.set_size_inches(15,18)

Koska batch_size on nyt asetettu arvoon 8 (eikä enää 1), the train_generator.next() menetelmä palauttaa sinulle a erä kahdeksasta lisätystä kuvasta aina kun kutsut sitä. Palautettujen kuvien määrä perustuu batch_size jonka asetit aiemmin kohdassa flow_from_directory() menetelmä:

train_generator = junan_datagen.flow_from_directory(
'./Hedelmät',
target_size=(224,224 XNUMX),
color_mode='rgb',
batch_size=erän_koko, # eräkoko = 8
class_mode='categorical',
shuffle=True)

Arvon arvo image_batch muuttuja (palauttaa next() menetelmä) on monikko kahdesta elementistä:

  • Ensimmäinen elementti (image_batch[0]) on joukko erä_koko kuvat (4D-taulukko)
  • Toinen elementti (image_batch[1]) sisältää kuvien tunnisteet

Yllä oleva koodinpätkä tuottaa seuraavan tulosteen:

Huomaa, että seitsemännellä rivillä on kaksi tyhjää kaaviota, joissa ei ole kuvia. Muista, että kuvasarjassa on yhteensä 54 kuvaa, ja koska jokainen erä palauttaa 8 kuvaa (per rivi), ensimmäisillä seitsemällä rivillä näkyy yhteensä 54 kuvaa (8×6 + 6). Seuraava kuva selventää:

Huomaa, että voit asettaa rows mihin tahansa numeroon ja ImageDataGenerator luokka luo jatkuvasti uusia lisättyjä kuvia sinulle.

Mallin rakentaminen siirtooppimisen avulla

Tiedät nyt kuinka käyttää ImageDataGenerator ladataksesi kuvasarjoja levyltä lisäystä varten. Mutta miten käytät sitä harjoitteluun? Seuraava koodinpätkä näyttää, kuinka syväoppimismalli luodaan käyttämällä siirrä oppimista.

Siirtooppiminen on koneoppimismenetelmä, jossa tehtävää varten kehitettyä mallia käytetään uudelleen mallin lähtökohtana toisessa tehtävässä. Siirto-oppiminen vähentää koulutukseen käytettävää aikaa.

osoitteesta tensorflow.keras.models tuonti Malli
osoitteesta tensorflow.keras.applications tuonti VGG16
osoitteesta tensorflow.keras.layers tuonti tiheä, GlobalAveragePooling2D
#---hedelmien määrä---
EI_LUOKKAA = max(train_generator.class_indices.values()) + 1
#---lataa VGG16-malli koulutuksen perusmalliksi---
perusmalli = VGG16(include_top=False, input_shape=(224, 224, 3))
#---lisää omat tasot ---
x = perusmalli.lähtö
x = GlobalAveragePooling2D()(x)
x = Tiheä(1024,aktivointi='relu')(x) # lisää tiheitä kerroksia niin
# että malli voi
# opi monimutkaisempaa
# toimintoa ja
# luokittele parempaan
# tulosta.
x = Tiheä(1024,aktivointi='relu')(x) # tiheä kerros 2
x = Tiheä(512,aktivointi='relu')(x) # tiheä kerros 3
preds = Tiheä(EI_LUOKKAA,
activation='softmax')(x) # viimeinen kerros
# softmax-aktivointi
#---luo uusi malli perusmallin alkuperäisestä
# tulo ja uuden mallin lähtö ---
malli = Malli (tulot = perus_malli.tulo, lähdöt = preds)
#---älä harjoittele 19 ensimmäistä kerrosta - 0..18---
tasolle model.layers[:19]:
layer.trainable=Epätosi
#---harjoita loput kerrokset - 19 eteenpäin---
tasolle model.layers[19:]:
layer.trainable=Tosi

#---kokoa malli---
model.compile(optimizer='Adam',
loss='categorical_crossentropy',
metrics = ['tarkkuus'])

Siirto-oppimisen toiminnan selittäminen ei kuulu tämän artikkelin piiriin. Jätän sen toiseen artikkeliin.

Luotujen kuvien käyttäminen harjoitteluun

Jos haluat käyttää lisättyjä kuvia harjoitteluun, ohita train_generator osaksi fit() mallin menetelmä:

#---kouluta malli---
step_size_train = train_generator.n // train_generator.batch_size
malli.fit(junageneraattori,
steps_per_epoch=step_size_train,
aikakaudet = 15)

- steps_per_epoch parametri tarkoittaa pohjimmiltaan kuinka monta vaihetta aikakaudella on - se riippuu kuvien määrästä ja aiemmin määritetystä erän koosta. Jos asetat tämän suureksi, teet toistuvaa harjoittelua. Sinun tulisi asettaa se tämän kaavan perusteella:

kuvien määrä / eräkoko

Esimerkissämme meillä on yhteensä 54 kuvaa. Ja niin jokaisella aikakaudella, ImageDataGenerator luokka muuttaa kaikki 54 kuvaa harjoittelua varten. Jokaisella aikakaudella malli saa eri muunnelmia kuvista. Jos sinulla on 15 aikakausia, niin kuvista luodaan ja syötetään koulutusmalliin yhteensä 15×54 muunnelmaa.

- ImageDataGenerator luokka antaa mallillesi mahdollisuuden saada uusia muunnelmia kuvista kullakin aikakaudella. Muista kuitenkin, että se palauttaa vain muunnetut kuvat, eikä lisää niitä olemassa oleviin kuviin.

Toivon, että tämä artikkeli on antanut sinulle hyvän käsityksen siitä, mitä kuvadatan lisäyksessä on kyse ja miksi tarvitset niitä syväoppimismalliesi koulutuksessa. Erityisesti olen osoittanut sen käyttämällä Keras-moduulia TensorFlow-kirjastossa.

Kuvatietojen lisäys syväoppimista varten Julkaistu uudelleen lähteestä https://towardsdatascience.com/image-data-augmentation-for-deep-learning-77a87fabd2bf?source=rss—-7f60cf5620c9—4 https://towardsdatascience.com/feed

<!-

->

Aikaleima:

Lisää aiheesta Blockchain-konsultit