Umelá inteligencia - prvý praktický príklad v rozpoznávaní obrazu
V tomto zápisku si vyskúšame naprogramovať svoju prvú neurónovú sieť na rozpoznávanie obrazu. Pre nedočkavých je na konci v TL;DR hotový príklad.
Predchádzajúce zápisky
Data augmentationVytvorenie datasetu
Prvé kroky k programovaniu
Umelá inteligencia v rozpoznávaní obrazu
Umelá inteligencia nás všetkých zabije
Ideme na to
Budeme vychádzať z toho čo som písal v minulých zápiskoch ako sa učí malé dieťa rozpoznávať veci vo svojom okolí. Čiže ju naučíme rozpoznávať svoju mamu a to čo naša mama nie je (v našom prípade Angelina Jolie :)). To čo naša mama nie je môže byť postieľka, stolička, fľaška ...Použijeme neurónovú sieť ktorú som už spomínal a to konvolučnú neurónovú sieť z Wikipedie.
Nedostatky nášho postupu
1.) Ako som už spomínal pre dobré naučenie siete potrebujeme okolo tisíc obrázkov, ja som náhodne stiahol 22 obrázkov z ktorých som ešte jeden zmazal, pretože to bol len zarámovaný obrázok, čo mohlo viac ublížiť ako pomôcť. Potom som pomocou data augmentation vygeneroval (21 x 25 + 21) x 2 = 1092 obrázkov.2.) Tá sieť je dosť plytká, má len sedem vrstiev, čo v niektorých prípadoch môže byť aj dosť, ale pretože riešime trochu komplexnejší problém, asi nebude fungovať úplne perfektne.
Príprava
Dostatok obrázkov Angeliny Jolie sme si už vytvorili cez data augmentation. Pre dobré výsledky budeme potrebujeme sieti ukázať, čo všetko mama nie je. Takže si posťahujeme pár obrázkov detských fľašiek, stoličiek, postieľok a všetkého možného čo mama nie je.Začíname programovať
Pôvodný zámer som značne zredukoval, pretože sa to začalo rozťahovať cez tri zápisky. Takže si to skrátime na nejakú únosnú formu.Naklonujeme si už hotový projekt z GitHubu:
git clone https://github.com/bedna-KU/First-Convolutional_neural_network.gitVstúpime do projektu:
cd First-Convolutional_neural_networkV projekte máme štyri skripty:
divide.py - Rozdelí obrázky na train a test
predict.py - Predpoveď jedného obrázka
predict_live.py - Predpoveď obrázkov na desktope - live video
train.py - Učenie siete
Rozdelenie obrázkov na trénovacie a testovacie
Musíme mať dva priečinky s obrázkami a to mom a no_mom Obrázky si roztriedime do štruktúry pre trénovacie a testovacie obrázky, tak ideálne v pomere 80% ku 20%. Na to tu máme skript divide.py.python3 divide.py --test 20 --input mom --output dataa ešte rozdelíme obrázky kde nie je mama na 80% ku 20%:
python3 divide.py --test 20 --input no_mom --output dataŠtruktúra priečinku bude vyzerať takto:
├── LICENCE ├── README.md ├── data │ ├── test │ │ ├── mom │ │ │ ├── image_mom_1.jpg │ │ │ └── ... │ │ └── no_mom │ │ ├── image_no_mom_1.jpg │ │ └── ... │ └── train │ ├── mom │ │ ├── image_mom_1a.jpg │ │ └── ... │ └── no_mom │ ├── image_no_mom_1a.jpg │ └── ... ├── divide.py ├── live_predict_keras.gif ├── predict_live.py ├── predict.py └── train.pyPrepínače pre skript divide,py:
--test Počet percent pre testovacie dáta --input Vstupný priečinok s obrázkami --output Výstupný priečinok pre train a test
Učenie konvolučnej neurónovej sieťe
Na učenie slúži skript train.py. Na začiatku skriptu sa načítajú všetky potrebné knižnice. Riadok:os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'Potlačí všetky otravné hlášky z TensorFlow.
V časti PARAMETERS si nastavíme parametre pre učenie:
#################################################################### # PARAMETERS #################################################################### IMG_WIDTH = 50 # Šírka vstupného obrázka IMG_HEIGHT = 50 # Výška vstupného obrázka IMG_COLOR_DEPTH = 1 # Farebná hľbka INPUT_SHAPE = (IMG_HEIGHT, IMG_WIDTH, IMG_COLOR_DEPTH) # Vstupný tvar obrázkov NUM_CLASSES = 2 # Počet tried obrázkov BATCH_SIZE = 32 # Dávka naraz spracovaných obrázkov EPOCHS = 20 # Počet opakovaní učenia WEIGHTPATH = "weights.hdf5" # Súbor kde sa uložia váhy ###################################################################Funkcia def create_model (input_shape, num_classes): nám definuje celý model. Tento model sme si popísali tu.
Čo nám pribudlo je táto časť s nastaveniami:
model.compile (loss = categorical_crossentropy, optimizer = Adam (), metrics = ['accuracy'])Jedná sa o nastavenia a heuristiky ktoré som už spomínal tu, úplne dole. Loss a metrics nájdete vysvetlené tu a optimizéry tu.
Funkcia def load_dataset (): nahrá dataset a spraví s ním operácie ktoré sme nastavili.
Tu sa bajt (uint8) prevedie na hodnoty od nuly po jednotku:
datagen = ImageDataGenerator (rescale = 1. / 255)V kóde:
train_data = datagen.flow_from_directory (os.path.join (input, 'train'), target_size = (IMG_HEIGHT, IMG_WIDTH), color_mode = 'grayscale', class_mode = 'categorical', batch_size = BATCH_SIZE)je uvedená cesta odkiaľ sa obrázky majú načítať, na akú veľkosť sa majú obrázky skonvertovať, že sa budú obrázky načítavať v odtieňoch šedej, v akej forme triedy a koľko obrázkov naraz.
Teraz si uložíme páry trieda a číslo pre neskoršie použitie pri predikcií do JSON súboru:
classes = train_data.class_indices cprint (train_data.class_indices, 'yellow', attrs = ['bold']) json.dump (classes, open ("classes.json", 'w'))Samotné učenie sa spustí funkciou:
def train_model (): cprint ("Start learning", 'yellow', attrs = ['bold']) tst = model.fit_generator (train_data, validation_data = test_data, steps_per_epoch = train_data.n // BATCH_SIZE, validation_steps = (test_data.n // BATCH_SIZE), epochs = EPOCHS, callbacks = callbacks)train_data Sú trénovacie obrázky
validation_data Sú obrázky na ktorých sa overí naučenie siete
steps_per_epoch Na koľko krokov sa má rozdeliť jedno kolo učenia
validation_steps Na koľko krokov sa má rozdeliť overenie správnosti predpovedania siete
epochs Počet kôl učenia sa
callbacks Spustí každé kolo nejakú funkciu.
Okrem spomínanej možností fit_generator máme pre učenie sa neurónovej siete ešte možnosť fit.
Učenie neurónky spustíme skriptom train.py:
python3 train.py --input dataPrepínačom --input určíme priečinok, kde máme náš dataset.
Na notebooku Lenovo ThinkPad E560 mi naučenie siete trvalo približne 20 minút.
Predikcia s konvolučnou neurónovou sieťou
Na odhad toho čo je na obrázku slúži skript predict.py.Rozoberieme si čo v ňom nájdeme:
Funkcia def read_classes (): načíta triedy obrázkov.
Funkcia def create_model (input_shape, num_classes): načíta model, tu nič nového nie je.
Funkcia def load_weights (): načíta naučené váhy.
Funkcia def load_image (): načíta obrázok na predikciu v odtieňoch šedej.
Pre nás zaujímavá a nová vec sa nachádza vo funkcií def predict (image):, ktorá slúži na samotnú predikciu obrázka:
def predict (image): img_in = cv2.resize (image, dsize = (IMG_HEIGHT, IMG_WIDTH), interpolation = cv2.INTER_CUBIC) img_in = img_in.astype ('float') / 255 img_in = np.expand_dims (img_in, axis = 0) img_in = np.expand_dims (img_in, axis = 3) result = model.predict (img_in, batch_size = BATCH_SIZE, verbose = 1) class_name = classes[np.argmax (result)] return class_nameNa začiatku funkcie sa prevzorkuje obrázok na veľkosť vstupu siete.
Ďalej sa prevedú bajty na desatinné čísla v rozsahu 0 až 1.
Pomocou np.expand_dims expandujeme dimenzie obrázka na tvar (batch, 50, 50, 1) = vstup siete s dávkou (batch).
Samotnú predikciu robí model.predict, jediný povinný parameter je vstupný obrázok. Vráti sa nám ndarray s pravdepodobnosťou pre každú triedu.
Predikovanú triedu nám vráti classes[np.argmax (result)]. V našom prípade to bude mom, alebo no_mom.
Funkcia def draw_image (image): nám len ukáže obrázok ktorí sme dali na predikciu.
Teraz si predikciu spustíme:
python3 predict.py image.jpgimage.jpg si nahradíme názvom nejakého obrázka.
Vidíme že predikcia trvala 36 milisekúnd a rozpoznala, že to mama nie je.
Live predikcia s konvolučnou neurónovou sieťou
Skript pre live predikciu nájdeme v súbore predict_live.py.Funguje to tak, že si v našom obľúbenom internetovom vyhľadávači dáme vyhľadávať obrázky zmenšíme ho na polovicu plochy a umiestnime ho vľavo ako na obrázku a vyhodnocovanie prebieha v pravej polovici obrazovky. Predikcia je rovnaká ako s jedným obrázkom, akurát tu sa obrazovka rozseká na obdĺžniky veľkosti 159 x 180 pixelov. Keď sa zobrazí plný červený obdĺžnik, tak sa predpovedá, že to nie je mama a keď zelený rámik, tak že to je mama.
Skript spustíme pomocou príkazu:
python3 predict_live.py
TL;DR
Táto časť je pre tých čo nechcú nič riešiť, len si chcú vyskúšať umelú inteligenciu na rozpoznávanie obrazu.Naklonujeme si hotový projekt:
git clone https://github.com/bedna-KU/First-Convolutional_neural_network.gitVstúpime do projektu:
cd First-Convolutional_neural_networkUpgradneme pip:
python3 -m pip install --upgrade pipNainštalujeme závislosti:
python3 -m pip install -r requirements.txtStiahneme si naučené váhy:
wget https://downloads.sourceforge.net/project/example-dataset/weights.hdf5Vytvoríme si priečinok data:
mkdir dataVstúpime do priečinka:
cd dataStiahneme dataset:
wget https://downloads.sourceforge.net/project/example-dataset/data.zipRozbalíme dataset:
unzip dataVrátime sa do root projektu:
cd ..Live predikciu spustíme príkazom:
python3 predict_live.pyAk si chceme vyskúšať spustiť učenie:
python3 train.py --input data
Záver
Základom úspechu v rozpoznávaní obrazu konvolučnými neurónovými sieťami je dostatočne veľký počet obrázkov pre každú rozpoznávanú kategóriu, čo sme porušili a umelo sme z 21 obrázkov vyrobili 1092. Nejak nám sieť funguje, ale proste bude chybovať.Použili sme dosť plytkú sieť, len s dvomi konvolučnými vrstvami, bežne ich bývajú desiatky. Takže keď si to zhrnieme, spravili sme všetko zle, ale nejak nám to trochu funguje :-)
Ak sa chceme posunúť niekam ďalej potrebujeme podľa mojich skúseností minimálne tristo obrázkov a na ne nasadiť data augmentation a vytvoríme si napríklad tisícdvesto obrázkov.
Môžeme pridať ďalšie konvolučné vrstvy. V train.py sú zakomentované. Ďalej môžeme pre dve kategórie, čo je náš prípad, namiesto softmaxu použiť sigmoid. Môžeme sa pohrať s veľkosťou vstupu a podobne.
Prípadne môžeme použiť už nejaký hotový model z Keras.
Prílohy
Pre pridávanie komentárov sa musíte prihlásiť.
User Mario?
Pekné. Vedelo by sa to použiť aj na identifikáciu duplikátnych bobrázkov, s vyhdnotením najkvalitnejšieho? A bez uscalingu a zbierky vodoznakov.
Aby sieť usúdila ktorý obrázok je kvalitnejší, chcelo by to veľa obrázkov, kde by si každému dal počet hviezdičiek. Ak sa ti do toho chce, tak poďme na to. Kód ti k tomu naťukám :-)
Nejaké pokusy som už na nete videl, ale neskúšal.
Myslel som lepšie rozlíšenie a menšie zrno.
Tie hviezdičky by po verejnom trénovaní skončili inklinujúc ku falošnému hdr. Viac basov, lepšia muzika kámo. (Sarkazmus)
Pravdu povediac ja nie som odborník na digitálne fotky, to by musel niekto navrhnúť metriku, aké parametre sledovať. Ale viem si predstaviť, že by to šlo aj bez AI. Napr. na meranie šumu použiť scikit-image estimate_sigma
Myslel som vybratie fotky z bežného životného cyklu. Niekto nafotí strašidelného pavúka a dá na 9gag. Tam si to niekto pozrie na mobile. Keďže sa mu nechce kliknúť na "uložiť obrázok", tak stlačí Power+VolDown aby urobil snímok obrazovky. Ten sa mu objaví v Notifikáciách a odtiaľ tú akoby fotku nazdieľa na Facebook. Tam si tú fotku niekto zoberie, stiahne a zväčší v fotoobchode na 4k, a nahrá na rouming kde pribudne vodoznak. Tam to nájde ďalší, a pridá motivačný tekst so smajlíkami a postne na zomri.
Vo výsledku to vyzerá ako keď premietaš diapozitív na pokrčený pauzák. A teraz uhádni ktorý obrázok z toho je najkvalitnejší.
Aha, to by šlo.
Možno niekedy, keď sa budem moc nudiť :)
A v druhej generácii SW by si mohol urobiť detekciu širokouhlých filmov, ktoré niekto nahrával z telky mobilom ktorý mal v ruke, a potom do toho dorobil okraje aby sa to dalo pozerať na výšku bez otočenia telefónu.
Nemas tam uvedene zavistlosti, ze co treba mat vsetko nainstalovane.
Mno môžem doplniť.
Dopln. Lebo to jedine chyby v TL;DR.
Doplnené.
Sikovne.
Alebo pridat link na http://linuxos.sk/blog/zumpa/detail/umela-inteligencia-/, kde spominas instalaciu.
Ahoj,
Mna by zaujimalo, aky silny hardware clovek potrebuje,aby si to mohol vyskusat?
HW nemusí byť vôbec silný, jediná podmienka je, aby nebol moc technologicky zastaralý, pretože sa využívajú niektoré špeciálne "moderné" inštrukcie procesorov aby sa celý ten proces urýchlil. Čiže na jeden tik procesoru dokáže spracovať viac informácií ako bežné inštrukcie.