Clasificarea alimentelor cu Deep Learning în Keras/Tensorflow

Computer, ce mănânc oricum?

deep

Dacă citiți acest lucru pe GitHub, demonstrația arată așa. Vă rugăm să urmați linkul de mai jos pentru a vizualiza demo-ul live pe blogul meu.

ACTUALIZĂRI

Rețelele neuronale convoluționale (CNN), o tehnică din câmpul mai larg de învățare profundă, au fost o forță revoluționară în aplicațiile de viziune computerizată, în special în ultimul jumătate de deceniu. Un caz de utilizare principal este cel al clasificării imaginilor, de ex. stabilind dacă o imagine este cea a unui câine sau a unei pisici.

Nu trebuie să vă limitați la un clasificator binar, desigur; CNN-urile se pot scala cu ușurință la mii de clase diferite, așa cum se vede în bine-cunoscutul set de date ImageNet de 1000 de clase, utilizat pentru a evalua performanța algoritmului de viziune pe computer.

În ultimii câțiva ani, aceste tehnici de ultimă oră au început să devină disponibile comunității mai largi de dezvoltare software. Pachetele de rezistență industrială, cum ar fi Tensorflow, ne-au oferit aceleași elemente de bază pe care Google le folosește pentru a scrie aplicații de învățare profundă pentru dispozitive încorporate/mobile în clustere scalabile din cloud - Fără a fi nevoie să codificați manual operațiunile matricei GPU, gradienții derivați parțiali și optimizatorii stochastici care face posibilă aplicațiile eficiente.

Pe lângă toate acestea, există API-uri ușor de utilizat, cum ar fi Keras, care abstrag unele detalii de nivel inferior și ne permit să ne concentrăm pe prototiparea rapidă a unui grafic de calcul de învățare profundă. La fel ca am amesteca și asorta Legos pentru a obține rezultatul dorit.

Ca proiect introductiv pentru mine, am ales să folosesc un clasificator de imagine pre-antrenat care vine cu Keras și să-l recalific pe un set de date care mi se pare interesant. Sunt foarte îndrăgit de mâncarea bună și de gătit acasă, așa că ceva în acest sens a fost apetisant.

În lucrare, Food-101 - Componente discriminante miniere cu păduri aleatorii, ele introduc setul de date Food-101. Există 101 clase diferite de alimente, cu 1000 de imagini etichetate pe clasă disponibile pentru instruire supravegheată.

M-a inspirat această postare pe blogul Keras: Construirea unor modele puternice de clasificare a imaginilor folosind foarte puține date și un script conex pe care l-am găsit pe github: keras-finetuning.

Am construit recent un sistem în scopul experimentării cu Deep Learning. Componentele cheie sunt un Nvidia Titan X Pascal cu 12 GB de memorie, 96 GB de memorie RAM de sistem, precum și un procesor Intel Core i7 cu 12 nuclee. Rulează Ubuntu 16.04 pe 64 de biți și folosește distribuția Anaconda Python. Din păcate, nu veți putea urmări împreună cu acest notebook pe propriul sistem decât dacă aveți suficientă memorie RAM. În viitor, aș dori să învăț cum să gestionez mai mult decât seturile de date RAM într-un mod performant. Vă rugăm să luați legătura dacă aveți idei!

Am petrecut aproximativ o lună înăuntru și în afara construcției acestui proiect, încercând să antrenez zeci de modele și explorând diverse domenii, cum ar fi multiprocesarea, pentru o creștere mai rapidă a imaginii. Aceasta este o versiune curățată a notebook-ului care conține modelul meu cel mai performant începând cu 22 ianuarie 2017.

După reglarea fină a unui model Google InceptionV3 pre-antrenat, am reușit să realizez 82,03% Exactitate Top-1 pe setul de testare folosind o singură cultură per articol. Folosind 10 culturi pe exemplu și luând cele mai frecvente clase prezise, ​​am reușit să realizez 86,97% Exactitate Top-1 și 97,42% Precizie Top-5

Alții au reușit să obțină rezultate mai precise:

  • Încărcarea unei cantități mari de date în memorie, cum să evitați?
  • Salvarea datelor într-un fișier h5py pentru procesarea în afara benzii?
  • Utilizarea Dask pentru procesarea distribuită?
  • Îmbunătățirea augmentării imaginii multiprocesare?
  • Exportul în aplicația mobilă Tensorflow?

Încărcarea și preprocesarea setului de date

Să importăm toate pachetele necesare pentru restul notebook-ului:

Descărcați setul de date și extrageți-l în folderul notebook. Poate fi mai ușor să faceți acest lucru într-o fereastră terminală separată.

Să vedem ce fel de alimente sunt reprezentate aici:

Să ne uităm la câteva imagini aleatorii din fiecare clasă de mâncare. Puteți să faceți clic dreapta și să deschideți imaginea într-o fereastră nouă sau să o salvați pentru a o vedea la o rezoluție mai mare.

O multiprocesare.Piscina va fi utilizată pentru a accelera mărirea imaginii în timpul antrenamentului.

Avem nevoie de hărți de la clasă la index și invers, pentru o codificare corectă a etichetelor și o imprimare frumoasă.

Setul de date Food-101 are o divizare tren/test furnizată. Vrem să folosim acest lucru pentru a compara performanțele noastre de clasificare cu alte implementări.

Acum suntem pregătiți să încărcăm antrenamentul și să testăm imaginile în memorie. După ce totul este încărcat, vor fi alocați aproximativ 80 GB de memorie.

Toate imaginile care au o lățime sau o lungime mai mică decât min_size vor fi redimensionate. Aceasta este astfel încât să putem lua culturi de dimensiuni adecvate în timpul măririi imaginii.

Trebuie să codificăm fiecare valoare pentru fiecare etichetă pentru a crea un vector de caracteristici binare, mai degrabă decât o caracteristică care poate lua valori n_class.

Aveam nevoie de o conductă de creștere a imaginii mai puternică decât cea livrată cu Keras. Din fericire, am putut găsi această versiune modificată pe care să o folosesc ca bază.

Autorul a adăugat o conductă extensibilă, care a făcut posibilă specificarea modificărilor suplimentare, cum ar fi funcțiile de decupare personalizate și posibilitatea de a utiliza preprocesorul de imagine Inception. A fost capabil să aplic preprocesarea în mod dinamic a fost necesară, deoarece nu aveam suficientă memorie pentru a păstra tot setul de antrenament ca float32s. Am putut încărca întregul set de antrenament ca uint8s .

În plus, nu foloseam pe deplin GPU-ul sau CPU-ul meu multicore. În mod implicit, Python este capabil să utilizeze un singur nucleu, limitând astfel cantitatea de imagini procesate/mărite pe care le-aș putea trimite GPU-ului pentru antrenament. Pe baza unor monitorizări de performanță, foloseam în medie doar un procent mic din GPU. Prin încorporarea unui pool multiprocesare python, am putut obține aproximativ 50% utilizare CPU și 90% utilizare GPU.

Rezultatul final este că fiecare epocă de antrenament a trecut de la 45 de minute la 22 de minute! Puteți rula graficele GPU dvs. în timp ce vă antrenați în acest notebook. Inspirația pentru încercarea de a îmbunătăți augmentarea datelor și performanța GPU a venit de la Jimmie Goode: Generatoare tamponate Python pentru mărirea datelor

În acest moment, codul este destul de bug și necesită repornirea nucleului Python ori de câte ori antrenamentul este întrerupt manual. Codul este destul de piratat împreună și anumite caracteristici, cum ar fi cele care implică montarea, sunt dezactivate. Sper să îmbunătățesc acest ImageDataGenerator și să îl lansez comunității în viitor.

Putem vedea ce fel de imagini ies din aceste ImageDataGenerators:

Vom recalifica un model Google InceptionV3, predeterminat pe ImageNet. Arhitectura rețelei neuronale este prezentată mai jos.

În acest moment, vedem până la 81,65 de acuratețe Top-1 cu o singură cultură pe setul de testare. Putem continua să instruim modelul la o rată de învățare și mai lentă pentru a vedea dacă se îmbunătățește mai mult.

Experimentele mele inițiale au folosit optimizatori mai moderni, cum ar fi Adam și AdaDelta, împreună cu rate mai mari de învățare. Am rămas o vreme sub o precizie de 80% înainte să decid să urmez literatura mai îndeaproape și să folosesc Descendența gradientului stocastic (SGD) cu un program de învățare în scădere rapidă. Când căutăm prin suprafața multidimensională, uneori mersul mai lent merge mult.

Din cauza instabilității cu codul meu multiprocesare, uneori trebuie să repornesc notebook-ul, să încarc ultimul model, apoi să continuu antrenamentul.

În acest moment, ar trebui să avem mai multe modele antrenate salvate pe disc. Putem să le parcurgem și să folosim funcția load_model pentru a încărca modelul cu cea mai mică pierdere/cea mai mare precizie.

De asemenea, dorim să evaluăm setul de testare folosind mai multe culturi. Acest lucru poate genera un impuls de precizie de 5% comparativ cu evaluarea unei singure culturi. Este comun să se utilizeze următoarele culturi: stânga sus, dreapta sus, stânga jos, dreapta jos, centru. De asemenea, luăm aceleași culturi pe imaginea răsucită de la stânga la dreapta, creând un total de 10 culturi.

În plus, dorim să returnăm predicțiile top-N pentru fiecare cultură pentru a calcula acuratețea Top-5, de exemplu.

De asemenea, trebuie să preprocesăm imaginile pentru modelul Inception:

Acum creăm culturi pentru fiecare articol din setul de testare și obținem predicții. Acesta este un proces lent în acest moment, deoarece nu profit de multiprocesare sau de alte tipuri de paralelism.

Acum avem un set de 10 predicții pentru fiecare imagine. Folosind o histogramă, pot vedea cum sunt distribuite numărul de predicții unice pentru fiecare imagine.

Să creăm un dicționar pentru a mapa indexul articolelor de testare la predicțiile sale top-1/top-5.

O matrice de confuzie va trasa fiecare etichetă a clasei și de câte ori a fost etichetată corect vs. celelalte ori a fost etichetat incorect ca o clasă diferită.

Vrem să vedem dacă acuratețea a fost consecventă în toate clasele sau dacă unele clase au fost mult mai ușor/mai greu de etichetat decât altele. Potrivit complotului nostru, câteva clase au fost aberante în ceea ce privește faptul că sunt mult mai dificil de etichetat corect.