Listă de figuri … … … … 3 [603555]

Cuprins

Listă de figuri ………………………….. ………………………….. ………………………….. ………………. 3
Listă de tabele ………………………….. ………………………….. ………………………….. ……………… 4
Capitolul 1. Intro ducere ………………………….. ………………………….. ………………………….. … 5
1.1. Tema aplicației ………………………….. ………………………….. ………………………….. .. 5
1.2. Obiectivele lucrării ………………………….. ………………………….. ………………………. 6
1.3. Starea domeniului cercetat ………………………….. ………………………….. ……………. 6
1.4. Conținutul lucrării ………………………….. ………………………….. ……………………….. 7
Capitolul 2. Teoria și practica în domeniul inteligenței artificiale ………………………….. .. 9
2.1. Neuronul ………………………….. ………………………….. ………………………….. ………… 9
2.1.1. Funcții de ac tivare ale neuronului ………………………….. ………………………. 10
2.2. Forward propagation ………………………….. ………………………….. ………………….. 13
2.3. Backpropagation ………………………….. ………………………….. ………………………… 13
2.4. Setul d e date ………………………….. ………………………….. ………………………….. …. 14
2.5. Rețele neuronale convoluționale ………………………….. ………………………….. ….. 15
2.5.1. Stratul Convoluțional ………………………….. ………………………….. ………………. 16
2.5.2. Stratul Pooling ………………………….. ………………………….. ……………………….. 17
2.5.3. Strat conectat în totalitate ………………………….. ………………………….. …………. 18
2.5.4. Stratul de normalizare ………………………….. ………………………….. ……………… 19
Capitolul 3. Tehnologii folosite ………………………….. ………………………….. ………………… 21
3.1. Python ………………………….. ………………………….. ………………………….. ………….. 21
3.2. Java ………………………….. ………………………….. ………………………….. ……………… 23
3.3. SQLite ………………………….. ………………………….. ………………………….. ………….. 25
Capitolul 4. Descrierea aplicației ………………………….. ………………………….. ………………. 27
4.1. Introducere ………………………….. ………………………….. ………………………….. ……. 27

4.2. Crearea setului de date ………………………….. ………………………….. ………………… 28
4.3. Construirea modelul rețelei neuronale ………………………….. ……………………….. 31
4.4. Antrenarea rețelei neuronale ………………………….. ………………………….. ………… 37
4.5. Transformarea modelul din Keras în Tensorflow ………………………….. ……….. 45
4.6. Dezvoltarea aplicației Android ………………………….. ………………………….. …….. 46
4.6.1. Baza de date ………………………….. ………………………….. ………………………… 46
4.6.2. Clasele și activitățile aplicației ………………………….. ………………………….. . 51
Capitolul 5. Documentație utilizator ………………………….. ………………………….. …………. 57
5.1. Utilizarea software -ului ………………………….. ………………………….. ………………. 57
5.2. Posibile probleme apărute și soluționarea lor ………………………….. ……………… 60
Capitolul 6. Concluzii ………………………….. ………………………….. ………………………….. …. 62
6.1. Atingerea funcționalității ………………………….. ………………………….. …………….. 62
6.2. Dezvoltări ulterioare ………………………….. ………………………….. …………………… 62
6.3. Opinie personală despre aplicație ………………………….. ………………………….. …. 63
Bibliografie ……………………………………………………………………………………………………… 65
Anexă cod sursă ………………………….. ………………………….. ………………………….. …………. 67
Extras 1 – Modelul rețelei ………………………….. ………………………….. …………………….. 67
Extras 2 – Antrenarea rețelei ………………………….. ………………………….. …………………. 68
Extras 3 – Descărcare imagini ImageNet ………………………….. ………………………….. … 73
Extras 4 – Clasa de clasificare a imaginilor ………………………….. …………………………. 74
Extras 5 – Clasa ce preia imaginea și furnizează răspunsul (Camera_activity) ……… 76

3
Listă de figuri
Figură 1 Neuronul artificial (Ioniță, 2009) ………………………….. ………………………….. …. 10
Figură 2 Graficul funcției ReLU (Wikipedia, Activation function, 2019) ……………….. 11
Figură 3 Graficul funcției sigmoidă (Wikipedia, Logistic function, 2019) ………………. 12
Figură 4 Graficul funcției liniare (Wikipedia, Activation function, 2019) ………………. 12
Figură 5 Împărțirea setului de date (Heaton, 2018) ………………………….. ………………….. 15
Figură 6 Structura unei rețele neuronale convoluționale (Sumit, 2018) ………………….. 16
Figură 7 Imagine de dimensiune 5x5x1 ce este filtrată cu un filtru de dimensiune 3x3x1
rezultând o mapă de caracteristici de dimensiune 3x3x1 (Sumit, 2018) ………………….. 17
Figură 8 Tipurile de pooling. Max Pooling și Average Pooling (Sumit, 2018) ………… 18
Figură 9 Proces prin care mapa de caracteristici este liniarizată și straturile întregi
conectate (Sumit, 2018) ………………………….. ………………………….. ………………………….. . 19
Figură 10 Sigla limbajului de programare Python (Python, 2019) …………………………. 21
Figură 11 Logo Java (Oracle, 2019) ………………………….. ………………………….. ………….. 24
Figură 12 Logo -ul Android și logo -ul SQLite (SQLite, 2019) ………………………….. ….. 25
Figură 13 Schema aplicației ………………………….. ………………………….. …………………….. 28
Figură 14 Eșantion de imagini extras din clasa gorilă ………………………….. ………………. 31
Figură 15 Arhitectura rețelei convoluționale ………………………….. ………………………….. . 36
Figură 16 Matrice de confuzie ………………………….. ………………………….. ………………….. 43
Figură 17 Grafic obținut din procesul de antrenare ………………………….. ………………….. 44
Figură 18 Diagrama entitate legătură ………………………….. ………………………….. ………… 47
Figură 19 Structura tabelului de legătură ………………………….. ………………………….. …… 48
Figură 20 Ecranul de întâmpinare și meniul ………………………….. ………………………….. .. 57
Figură 21 Prezentarea tuturor animalelor și detalii despre fiecare în parte ………………. 58
Figură 22 Informații despre aplicație și dezvoltator ………………………….. …………………. 58
Figură 23 Calea către ecranul de recunoașter e ………………………….. ………………………… 59
Figură 24 Clasificarea unui animal și afișarea detaliilor ………………………….. …………… 60
Figură 25 Eșuare în recunoaștere ………………………….. ………………………….. ………………. 61

4
Listă de t abele
Tabel 1 Componența setului de date ………………………….. ………………………….. ………….. 29
Tabel 2 Date despre starea ultimelor două antrenări ………………………….. ………………… 37
Tabel 3 Evaluarea rețelei neuronale utilizate ………………………….. ………………………….. 42
Tabel 4 Matrice de confuzie pentru estimatorii modelului (Shung, 2018) ……………….. 42

5
Capitolul 1. Introducere

1.1. Tema aplicației

Grădinile zoologice din ziua de astăzi încearcă să prezinte publicului diverse
animale exotice și neobișnuite precum și mediul din care acestea provin doar c ă într-o
manieră antropică . Mai precis, grădinile zoologice sunt împânzite de afișe și postere
care suprimă aspectul natural pe care acestea ar trebui să le aibă.
Din cauză că aspectul natural se diminuează iar vizitatorii nu sunt implicați activ
în căpătarea de noi cunoștințe, tema aplicației ce urmează a fi prezentată este
recunoașterea animalelor în imagini dintr -o grădină zoologică.
Aplicația va fi ușor de folosit și va funcționa în următorul mod: în momentul în
care vizitatorul vede un animal nou , acesta va folosi aplicația fu rnizată de gr ădina
zoologică pentru a afla numele animalului precum și informații despre el. Totul se va
face printr -o singură captură de imagine a animalului dorit.
Această aplicație este concepută în scop educativ, indiferent de vârstă sau gen,
putând f i utilizată de oricine iar conceptul ei este inovativ. Prin acest proces de
recunoaștere , cercetarea grădinii zoologice va căpăta o nouă formă, una în care
tehnologia se îmbină cu naturalul.
Recunoașterea animalelor din poze stârnește interesul oricărei pe rsoane fapt ce
poate consacra o anumită grădină zoologică prin modul său unic de a trata vizitatorii.
Unicitatea aplicației constă în faptul că utilizatorii sunt încurajați să descopere
informații despre diverse animale într -un mod interactiv, eliminându -se tehnica clasică
de a expune detalii despre animale pe afișe. Pe lângă faptul că persoanele ce ii trec
pragul grădinii zoologice sunt captivate de această idee, înfățișarea grădinii se schimbă
radical, aspectul ei devenind mai sălbatic întipărind în sufle tul vizitatorilor senzația că
sunt în respectivul mediu și pot observa animalele comportându -se natural.
Spectrul de utilizare al aplicației nu se rezumă doar la grădinile zoologice ci se
poate extinde la nivel global, aplicația având capacitatea de a det ecta diverse animale
care nu sunt obligatoriu plasate într -o grădină zoologică.

6
1.2. Obiectivele lucrării

Obiectivele pe care aplicația le are sunt acelea de a aduce o nouă față grădinilor
zoologice, de a le face mai realistice, de a stârni o dorință și o pl ăcere utilizatorilor să
se plimbe printr -un mediu sălbatic și, cel mai important lucru, să permită utilizatorilor
să descopere anumite informații sau anumite nume de animale pe care nu le văzuseră
niciodată , cu ajutorul unui dispozitiv modern cum este tele fonul.
Aplicația permite fiecărei persoane să parcurgă gradina zoologică și să
fotografieze animalele primind astfel informații referitoare la acestea.
Aplicația trebuie să fie prietenoasă, să aibă o interfață accesibilă și intuitivă care
să nu pună prob leme utilizatorilor ce nu au prea multă experiență în acest domeniu.
Platforma de dezvoltare a aplicației este mobilă datorită nevoii de portabilitate.
În ziua de astăzi se pune accent pe portabilitate și accesibilitate , atribute pe care
aplicație este n ecesar să le aibă , iar noile generații sunt captivate de progresele
tehnologice . Datorită stilului de viață al omului modern, crearea aplicațiilor ce folosesc
inteligență artificială au o prioritate deosebită, iar înglobarea acestora pe platformele
mobile devine o provocare cu un impact extrem de pozitiv asupra societății.
Telefoanele sunt cele mai întâlnite dispozitive, în momentul de față sunt 5.127.318.300
abonamente mobile unice în lume (GSMA, 2019) , această cifră variind constant.
1.3. Starea domeniului cercetat

Inteligența artificială este o ramură a informaticii, aceasta se ocupă cu crearea
de softuri ce au capacitatea de a observa mediul, a -l înțelege și de a -l modifica astfel
încât rezultatele obținute să fie maxime în funcție de problema de rezolvat. În ziua de
astăzi multe sisteme informatice se bazează pe inteligența artificială, sisteme precum:
Google sau YouTube . Se exploatează mult par tea de recunoaștere a imaginilor
deoarece marea parte din informația din mediu se află prin observarea vizuală a
acestuia, sunetele și alte caracteristici având un impact mai slab în recunoaștere.
(Wikipedia, Artificiall Intelligen ce, 2019)
Informatica definește cercetarea inteligenței artificiale ca studiu al agenților
inteligenți , cu alte cuvinte orice dispozitiv care își percepe mediul și efectuează acțiuni

7
care maximizează sau minimizează, în funcție de caz, un anumit obiec tiv. O definiție a
mișcării acesteia revoluționare, a inteligenței artificiale, dată de Kaplan și Haenlein
este: „capacitatea unui sistem de a interpreta corect datele externe, de a învăța din astfel
de date și de a folosi ceea ce a învățat pentru a -și ati nge obiective și sarcini specifice
printr -o adaptare flexibilă” (Andreas & Michael, 2008) .
1.4. Conținutul lucrării

În această lucrare se vor prezenta tehnologiile ce au fost folosite, pașii ce au fost
urmați precum și modul de utilizare al aplicației. În cele ce urmează se vor descrie pe
scurt părțile componente ale acestui proiect.
Prima parte , va conține informații teoretice actuale în domeniul inteligenței
artificiale, mai exact informații despre structurile atomice ale unei rețele neuronale,
elementele cheie ale acesteia precum și funcționalitatea lor. Înțelegerea unei astfel de
practici, aceea de a lucra cu rețel ele neuronale, reprezintă primul pas spre a crea lucruri
grandioase și inovative care pot face lumea un loc mai bun . Întreaga societate tinde
spre convergența dintre om și mașină iar acest domeniu este pilonul unei ere prospere.
Încercarea de a aduce calcu latoarele la nivelul creierului uman este reliefată chiar de
numele structurilor ce stau la baza inteligenței artificiale și anume, rețele neuronale.
A doua parte a lucrării va conține informații despre tehnologiile ce au făcut
posibilă realizarea acestei a. Fiecare tehnologie va fi explicată și detaliată pe porțiunile
relevante ce au fost integrate în aplicație. În această parte se vor detali a lucruri ce țin de
utilitatea tehnologiilor, scopul pentru care acestea au fost alese și modul lor de
exploatare.
Partea a treia din această lucrare va conține descrierea amănunțită a proiectului .
În această descriere se vor regăsi următoarele puncte: detalierea temei abordate,
prezentarea utilității ei în viața reală, precum și modul în care aceasta diferă față de
celelalte, analizarea unor versiuni mai slabe ale aplicației ce au stat la baza dezvoltării
și obținerii stării curente, dificultățile întâmpinate și fragmente importante.
Partea a patra a acestei lucrări se vor prezenta funcțiile aplicației sub forma unui
ghid, pentru a ajuta utilizatorii să interacționeze într -un mod corect cu softul. Tot în

8
acest capitol se va prezenta și modul în care utilizatorul poate acționa în cazul în care
aplicația nu furnizează un răspuns de încredere.
Partea a cincea va consta î n prezentarea concluziilor, în cadrul cărora vor intra
referiri legate de contribuția aplicației în lumea reală, problemele ce au fost întâmpinate
și cel mai important , vor fi prezentate idei despre îmbunătățiri ulterioare.
Ultima parte va reprezenta exp unerea porțiunilor cheie din codul sursă, acele
porțiuni ce formează nucleul aplicației. În acest caz fiind vorba de o aplicație din
inteligența artificială, se vor insera liniile de cod ce formează rețeaua neuronală, liniile
de cod ce antrenează și acele linii de cod ce realizează predicții pe baza rețelei
antrenate precum și acele linii de cod ce realizează setul de date în stare brută .

9
Capitolul 2. Teoria și practica în domeniul inteligenței
artificiale

Inteligența artificială este tot mai prezentă în viața noastră și ea ne remodelează
într-un mod benefic și în permanență stilul de viață , fapt pentru care trebuie să
înțelegem ce reprezintă ea și felul în care aceasta lucrează. În informatică se definește
acest concept ca studiu al agenților inteligenți: orice dispozitiv care își percepe mediul
și efectuează acțiuni care maximizează șansa de a -și atinge cu succes obiectivele.
Cel mai mare accent într -un sistem inteligent se pune pe latura de învățare
deoarece acesta trebuie să evalueze datele din mediu și în fu ncție de tipul învățare p e
care acesta îl deține: învățare supervizată , nesupervizată sau cu întărire , sistemul
trebuie să furnizeze un răspuns cât mai bun. Învățarea unui sistem este un concept
fundamental al cercetării inteligenței artificiale, aceasta r eprezintă studiul unor
algoritmi matematici de calcul ce se îmbunătățesc automat prin experiență. În cazul
învățării nesupervizate sistemul încearcă să găsească tipare, șabloane într -un flux de
intrare, fără a avea nevoie de îndrumarea omului, adică fără a fi necesar ca o persoană
să furnizeze valorile de adevăr pentru un caz de intrare, lucru ce se întâmplă în cazul
învățării supervizate. Învățarea supervizată constă în antrenarea sistemului oferind -ui
date de intrare precum și datele de ieșire corecte iar acesta, învață prin compararea
rezultatului său cu cel corect și încearcă pe viitor să minimizeze acea discrepanță.
În cazul învățării cu întărire agentul acționează într -un mediu iar rezultatele sunt
acceptate ca recompense, el trebuie să învețe să mani puleze acel mediu astfel încât
recompensa pe care o primește să fie cât mai mare. (Wikipedia, Artificiall Intelligence,
2019 , Stuart Russell, 2014)

2.1. Neuronul

Rețelele neuronale artificiale au structură similară cu structura umană nervoasă,
fiind conceput e din unități funcționale numite neuroni. Prin analogie cu neuronii
umani, neuronul artificial, are un număr n de intrări și o singură ieșire, care se poate
conecta la intrarea mai multor neuroni. Neuronul este o funcție matematică bazat pe

10
modelul neuroni lor umani, acesta reprezintă unitatea elementară pentru o rețea
neuronală.
Fiecare intrare este ponderată, cu alte cuvinte pentru fiecare valoare de intrare se
asociază o valoare numerică , se înmulțește cu o pondere apoi toate intrările sunt
însumate. Va loarea rezultată din suma acestor intrări la care se adaugă un parametru
numit bias este supusă unei fun cții ce o va „activa” și va avea ca rezultat o valoare de
ieșire. Bias-ul este o valoare ce ajută la controlul valorii ce va fi activată de către
funcți e. De exemplu , avem doi neuroni ce au valori 3 și 1 ambii fiind conectați cu un
singur neuron în stratul ascuns, ponderile sunt -0.3 ș i 0.1 iar funcția de activare va fi
ReLU. Rezultatul funcției va fi 0 deoarece se ia valoarea maxim ă dintre rezultat și 0.
Rezultatul 0 înseamnă ca acel neuron nu va transmite mai departe informația, se spune
ca neuronul nu este aprins sau activat. Adăugarea unui bias rezolvă această problemă.
Structura neuronului artificial este reprezentat în Figură 1.

Figură 1 Neuronul artificial (Ioniță, 2009)

2.1.1. Funcții de activare ale neuronului

Pentru ca neuronii să ofere un rezultat ce va servi drept intrare pentru alți
neuroni în viitor, suma ponderată la care se adaugă bias -ul trebuie să joace rolul de
variabilă pentru o funcție, rezultatul funcției fiind ut ilizat pe viitor. Cele mai întâlnite
funcții și cele mai utilizate în rețelele neuronale sunt: funcția liniară, funcția sigmoidă
și funcția ReLU. (Wikipedia, Activation function, 2019)
Funcția ReLU este o funcție de activare ce este foarte utilizată în zilele noastre
în modelele rețelelor neuronale. Această funcție este neliniară și îngrădește intervalul

11
valorilor de ieșire între [0,∞) . Avantajele pe care le prezintă această funcție de activare
sunt următoarele: este unilaterală în comparație cu antisimetria tanh, activare parțială,
adică dacă se utilizează o inițializare aleatoare a valorilor rețelei, aproximativ jumătate
din unitățile ascunse sunt activate, este mai buna la propagarea gradientului și se
calculează eficient. Scrierea matematică a acestei funcții este:
(1) 𝑓(𝑥)={0 𝑝𝑒𝑛𝑡𝑟𝑢 𝑥<0
𝑥 𝑝𝑒𝑛𝑡𝑟𝑢 𝑥≥0.
Graficul funcției este prezentat în Figură 2.

Figură 2 Graficul funcției ReLU (Wikipedia, Activation function, 2019)

Funcția sigmoidă cunoscută si sub numele de funcția logistică introduce neliniaritatea
în modelele de rețele neuronale. Acest mode l poate fi văzut ca o versiune mai fină a
funcției prag. Sigmoida are valorile de ieșire în intervalul (0,1) lucru ce este convenabil
pentru antrenarea rețelei deoarece cu c ât sunt valorile mai mici cu atât timpul
computațional scade. Ecuația matematică a acestei fun cții este:
(2) 𝑓(𝑥)=1
1+𝑒−𝑥.
Graficul funcției este reprezentat în Figură 3.

12

Figură 3 Graficul funcției sigmoidă (Wikipedia, Logistic function, 2019)

Funcția liniară se găsește sub mai mule denumiri cum ar fi: relație identică, hartă
identică sau transformare identică. Această funcție returnează aceeași valoare pe care
parametrul o are. Valorile pe care aceasta le întoarce sunt cuprinse în intervalul
(−∞,+∞). Graficul acestei funcții este o dreaptă într -un reper cartezian . Graficul
funcției se poate observa în Figură 4 iar ecuația ce formează acel grafic este dată de:
(3) 𝑓(𝑥)=𝑥

Figură 4 Graficul funcției liniare (Wikipedia, Activation function, 2019)

13
2.2. Forward propagation

Acest tip de propagare este un pas din antrenarea unei rețele neuronale artificiale.
Procedeul de propagar e este următorul: informația ce este primită în primul strat
neuronal numit și strat de intrare este dirijată către straturile ascunse până la aflarea
rezultatului final. Transferul informației se face doar într -o singură direcție . Scrierea
matematică a a cestui proces în care informația este transmisă și prelucrată de la un strat
la următorul este exemplificată în formulele (4) și (5).
(4) 𝑠𝑢𝑚 [𝑖]=∑ 𝑤[𝑖]𝐿−1
𝑗=0 [𝑗]∗𝑖𝑛𝑝[𝑗]+𝑏[𝑖]
(5) 𝑜𝑢𝑡[𝑖]=𝐹(𝑠𝑢𝑚 [𝑖]),𝑖=0…𝑁−1
Unde L reprezintă numărul de neuroni de intrare, N reprezintă numărul de neuroni de
ieșire , w[N][L] reprezintă matricea de ponderi, b [N] este vectorul deplasatorilo r de
scală sau bias și w[i][j] reprezintă ponderea conexiunii dintre neuronul i de ieșire și
neuronul j de intrare. (Ioniță, 2009)

2.3. Backpropagation

Algoritmi i de backpropagation fac parte din familia de antrenare a rețelelor neuronale
artificiale cu ajutorul gradientului descendent.
Principiul de lucru al acestei păr ți din antrenarea re țelei, parte ce este chiar cea mai
importantă în acest proces este Backpropagation. Principiul de funcționare al
algoritmului este : rezultatu l final oferit de mecanismul de forward propagation este
comparat cu rezultatul așteptat și se calculează eroare medie pătratică. În func ție de
diferen ța de valoare dintre rezultatul așteptat și rezultatul furnizat de rețea; se
recalculează ponderile neuro nale cu a jutorul metodei gradientului iar de cele mai multe
ori ponderile modificate sunt alese astfel încât pentru intrarea precedent ă să se ajungă
aproximativ la rezultatul dorit. Scopul antrenării rețelei neuronale este acela de a sa afla
combinația perfectă de ponderi ale neuronilor împreună cu bias -ul pen tru a se minimiza
eroare medie pătratică . În acest proces se lucrează foarte mult cu derivatele funcțiilor
sau derivatele parțiale ale acestora. (Wikipedia, Artificiall Intelligence, 2019) .

14
Pentru a se afla cantitatea valorilor pe care acest algoritm le are de modifi cat va
trebui să se calculeze modul în care eroarea se modifică în funcție de fiecare pondere.
După formula (6).
(6) 𝛿𝐸
𝛿∗𝑤𝑖𝑗
Din momentul în care se știu derivatele de eroare , ponderile se vor calcula după
următoarea formulă:
(7) 𝑤𝑖𝑗=𝑤𝑖𝑗−𝛼𝛿𝐸
𝛿∗𝑤𝑖𝑗
Unde 𝛼 este o constantă pozitivă numită rată de învățare ce trebuie reglată în mod
empiric. Dacă eroarea scade atunci când ponderile cresc atunci algoritmul va încerca să
crească valorile ponderilor, în caz contrar dacă erorile cresc atunci când ponderi le cresc
se va încerca minimizarea ponderilor. (Ioniță, 2009) .

2.4. Setul de date

Pentru a antrena o rețea neuronală aceasta are nevoie, în cazul învățării
supervizate , de date însoțite de etichete. Această relație între date și etichet e are rolul
de a îndruma învățarea sistemului. Seturile de date pot avea diferite forme și diferite
conținuturi, acestea pot fi de tip text, imagine sau sunet cuprinzând diferite date. Spre
exemplu , poze cu chipuri dintr -un set de date conceput pentru a ajuta la recunoașterea
facială.
Seturile de date sunt destul de greu de conceput iar conținutul lor trebuie să fie
uniform și în concordanță cu problema de rezolvat. În funcție de tiparul pe care acestea
le oferă, rețeaua neuronală ce a fost antrenată pe un set de date va avea capacitatea de a
recunoaște imagini similare cu imaginile prezente în setul de date . Rețeaua nu va avea
însă capacitatea de a recunoaște o persoană cu spatele dacă de exemplu , setul de
antrenare a avut doar persoa ne surprinse frontal .
În procesul de antrenare setul de date se împarte în două segmente, un segment
ce va fi folosit pentru antrenarea propriu zisă a rețelei, segment ce poartă numele de set
de antrenare și un segment ce va fi folosit pentru validarea re țelei, numit și set de
validare. Setul de antrenare este folosit de rețea pentru a învăța anumite tipare în date

15
iar cel de validare este folosit de rețea pentru a se calcula anumiți estimatori calitativi ai
rețelei. (Simona, 2018)
Pentru a ne raporta la aceste două seturi și anume, setul de antrenare și cel de
validare se utilizează două posibilități. Prima posibilitate de formare a acestor seturi
este prin folosirea anumitor rapoarte, cel mai întâlnit raport este cel în care 80% din
date sunt folosite pentru a antrena rețeaua și restul de 20% pentru a valida rețeaua.
Acest raport poate varia în funcție de dorința programatorului. O vizualizare asupra
împărțirii setului de date este reprezentată în Figură 5 Împărțirea setului de date .

Figură 5 Împărțirea setului de date (Heaton, 2018)

A doua posibilitate de creare a acestor seturi este metoda K Fold Cross
Validation în care setul de date se împarte egal în k mulțimi și fiecare parte este
utilizată pe rând pentru validare iar restul de k -1 sunt utilizate pentru antrenare.
(Simona, 2018)

2.5. Rețele neuronale convoluționale

Rețelele neuronale convoluționale sunt o clasă a rețelelor deep learning cu mai
multe straturi , ce se aplică de obicei pentru analiza imaginilor. O imagine generală a
structurii unei rețele de acest gen se poate observa în Figură 6. (Sumit, 2018 , Stanford,
2018)
Diferența fundamentală a acestor rețele față de cele obișnuite este dată de
prezența straturilor convoluționale ascunse. Fiecare neuron convoluțional procesează

16
date doar pentru câmpul receptiv (porțiune) , în acest proces neuronii sunt priviți
asemenea unor filtre . Deși rețelele neuronale normale por fi folosite pentru a învăța
caracteristici și pentru a clasifica date, nu este practic ca acestea să fie aplicate pe
imagini. Un număr foarte mare de neuroni ar fi necesari, chiar și într -o arhitectură de
mică adâncime, datorită dimensiunilor mar i de intrare asociate imaginilor, in care
fiecare pixel reprezintă o variabilă. De exemplu , pentru un strat complet conectat
pentru o imagine de dimensiune 64×64 sunt necesare 4096 de ponderi pentru fiecare
neuron din stratul următor. Acest lucru se evită prin operații de convoluție deoarece
aceste operații scad semnificativ numărul de parametri. De exemplu , dacă se folosește
un nucleu (filtru) de 5×5 ce scanează imaginea se vor obține doar 25 de parametrii
pentru fiecare neuron în parte , un număr mic ce nu mai pune probleme referitoare la
capacitatea necesară de calcul.

Figură 6 Structura unei rețel e neuronale convoluționale (Sumit, 2018)

2.5.1. Stratul Convoluțional

Elementul ce este implicat în efectuarea operațiilor de convoluție din acest strat
se numește kernel, filter sau K, acesta este reprezentat de cele mai multe ori sub forma
matriceală de dimensiune 3×3 sau 5×5 , în funcție de problema aceste dimensiuni pot
varia.
Filtrul scanează imaginea parcurgând pas cu pas întreaga suprafața, începe din
partea de sus a imaginii și se deplasează spre dreapta până când se atinge lungimea
maximă a pozei, după care coboară în imagine și repetă același procedeu. De fiecare

17
dată se realizează o multiplicare de matrice între matricea K (filtrul) și porțiunea din
imagine pe care se află. Deplasarea filtrului se poate observa în Figură 7.

Figură 7 Imagine de dimensiune 5x5x1 ce este filtrată cu un filtru de dimensiune 3x3x1 rezultând o mapă de
caracteristici de dimensiune 3x3x1 (Sumit, 2018)

Obiectivul acestui strat convoluțional este ace la de a extrage caracteristici din
imagini cum ar fi muchii , colțuri, linii.
Prin acest procedeu se pot obține două rezultate și anume: unul în care mapa de
caracteristici rezultată este de dimensiune mai mică comparativ cu intrarea și celălalt
rezultat este acela în care mapa de caracteristici este fie mai mare ca intrarea fie ega lă.
Acest lucru este dat de alegerea unui padding.
Padding -ul poate fi de două tipuri: same padding și valid padding . În cazul
same padding -ului daca avem o matrice de dimensiune 5x5x1 (înălțime x lățime x
adâncime sau număr de canale) inițial se extinde intrarea la 6x6x1 completându -se cu 0
liniile și coloanele adăugate, se setează pasul 0 după care se aplică un filtru de 3x3x1
iar rezultatu l va fi o matrice (un tensor) de dimensiune 5x5x1. În cazul în care se aplică
valid padding se va obține un output de dimensiune egală cu dimensiunea filtrului.
(Sumit, 2018)
2.5.2. Stratul Pooling

Acest strat este similar cu cel de convoluție prin faptul că este responsabil de a
reduce dimensiunile spațiale ale mapelor de caracteristici. Acțiunea stratului de

18
pooling, aceea de a reduce dimensiunile, are ca efect scăderea necesității puterii
computaționale pe care procesul de prelucra re a datelor îl cere.
O altă facilitate pe care stratul de pooling îl are este acela de a extrage
caracteristicile dominante care sunt invariante în raport cu rotația sau cu poziția, acest
lucru menține eficiența antrenării rețelei.
Extragerea caracteri sticilor importante, pooling -ul, se poate face prin două
metode și anume: parcurgerea harții de caracteristici și alegerea maximului dintr -o zonă
(max pooling) sau parcurgerea harții de caracteristici și alegerea mediei valorilor din
mapa de caracteristici deasupra căreia se află filtru (Figură 8).
De cele mai multe ori se utilizează Max Pooling -ul deoarece acesta diminuează
zgomotele și reduce dimensiunea spre deosebire de average pooling care doar reduce
dimensiunea, zgomotele fiind teoretic reduse prin acest meca nism. (Sumit, 2018)

Figură 8 Tipurile de pooling. Max Pooling și Average Pooling (Sumit, 2018)

2.5.3. Strat conectat în totalitate

Adăugarea acestui strat total conectat este esențială deoarece stratul învață
combinații neliniare ale caracteristicilor ce reies din mapele de caracteristici.

19
Odată ce s-a obținut mapa de caracteristici trebuie să fie converti tă în așa fel
încât să serv ească drept intrare unei rețele neuronale feed forward și backpropagation,
acest lucru obținându -se prin liniarizarea mapei. Liniarizarea tensor -ului de
caracteristici este realizată de un strat numit Flatten. Procesul de transformare a unei
mape de carac teristici într -o structură vectorială este reprezentat în Figură 9 .

Figură 9 Proces prin care mapa de caracteristici este liniarizată și straturile întreg i conectate (Sumit, 2018)

După ce modelul parcurge un număr de epoci acesta este capabil să distingă
caracteristicile din i magini iar cu ajutorul funcției Softmax, funcție de clasificare,
repartizează imaginile în categoriile aferente . (Sumit, 2018)

2.5.4. Stratul de normalizare

Batch normalization este o tehnică de normalizare care îmbunătățește viteza,
performanța și stabilitatea într -o rețea neuronală artificială. Această metodă a fost
introdusă în anul 2015 și normalizează ieșirea unui strat prin ajustarea și scalarea
funcției de activare. Norma lizarea ieșirii funcției de activare anterioare se face prin
extragerea mediei lotului și împărțirea acesteia la deviația standard a lotului. Spre
exemplu daca există valori între 0 și 1 in cadrul caracteristicilor dar avem și valori între
1 și 1000, acest ea din urmă ar trebui normalizate, cu alte cuvinte se încearcă o

20
normalizare a datelor din straturile ascunse asemenea modului în care se face o
normalizare pe datele de intrare în rețea.
Un beneficiu al acestei tehnici îl reprezintă reducerea supra ant renării deoarece,
în mod similar cu tehnica dropout, se adaugă anumite zgomote în fiecare strat de
activare fapt pentru care , dacă se utilizează aceasta tehnica nu va mai trebui folosit un
dropout ridicat iar informația rămâne în cantitate mare. Un alt ben eficiul este acela ca
nici o funcție de activare nu va avea un output prea mare sau prea mic. (Wikipedia,
Batch normalization, 2019) .

21
Capitolul 3. Tehnologii folosite

Pentru realizarea aplicației au fost necesare cunoașterea elementelor de bază dar
și a elementelor avansate ale următoarelor tehnologii: Python, Java și SQLite. Fiecare
dintre aceste tehnologii au avut de contribuit în egală măsură deoarece capacitățile
oferite sunt fundamentale pentru dezvoltarea aplicației. Limbajul Python este foarte
accesibil, ușor de utilizat și specializat pe acțiuni științifice, cum sunt rețelele
neuronale. Limbajul Java este foarte răspândit în lumea programatorilor și este utilizat
pentru dezvoltarea aplicațiilor Android. SQLite este o bibliotecă ce oferă posibilitatea
de a stoca informații într -un mod ușor și accesibil.

3.1. Python

Python este un limbaj de programare dinamic multi -paradigmă ce poate crea
aplicații web, aplicații desk top dar și aplicații pentru micro controlere. Acesta pune
accentul pe curățenia și simplitatea codului, sintaxa fiind clară și apropiată de limbajul
natural.

Figură 10 Sigla limbajului de programare Python (Python, 2019)

Limbajul de programare Python conține foarte multe module ce se pot integra
pentru manipularea a c ât mai multor servicii ale unui sistem. (Python, 2019) . Un
exemplu de modul ce se poate importa este cel folosit pentru utilizarea funcțiilor
sistemului de operare și anume modulul os. Modulul os poate citii sau scrie fișiere,
poate manipula căi sau poate crea fișiere temporale.
Pentru această aplicație s -au utilizat module ce sunt specializate pe operații
științifice precum calcul științific și evaluar ea rezultatelor, module ce sunt specializate

22
pe procesare de imagini și manipulare a acestora, module ce facilitează interacțiunea
dintre script și utilizator sau dintre script și sistemul de operare. Modulele științifice ce
au fost utilizate sunt: numpy , matplotlib , sklearn și random . Modulele pentru
prelucrare de imagini: Keras, cv2. Module pentru accesări pagini web: urllib . Module
pentru accesarea facilităț ile Windows: os. Module pentru machine learning și
inteligență artificială: Tensorflow și Keras .
Pentru procesarea imaginilor ce au fost utilizate pentru faza de antrenare și faza
de validare s -au folosit două module, OpenCV și keras.preprocessing.image . OpenCV
este un modul ce este specializat pe computer vision și poate manipula foarte ușor
imagini, de la schimbarea dimensiunilor acestora până la modificare contrastelor sau
evidențierea anumitor elemente. Tot pentru a altera imagini s -a folosit modulul
keras.preprocessing.image ce a avut rol de a crește numărul de imagini utilizat pentru
antrenare.
Keras este cel mai importat mod ul utilizat în această aplicație, el este
responsabil pentru crearea arhitecturii rețelei neuronale într -un mod accesibil. Acest
modul are și diferite facilități cum ar fi prelucrarea de imagini, lucru ce a fost amintit
anterior . Nucleul Keras -ului este specializat pe conceperea de modele pentru rețele
neuronale. Înc eputul formării unui model pentru o rețea neuronală în Keras este marcat
de funcția Sequential (). Sequential este un model simplu, liniar format din straturi ce
sunt așezate unul peste altul. Codul ce creează un nou model este următorul:
from keras.models import Sequential
model = Sequential()
Straturile noi din modelul rețelei sunt foarte ușor de adăugat, acestea pot fi de
mai multe tipuri, Conv2D ce reprezintă un strat convoluțional, MaxPooling2D ce
reprezintă un strat de Pooling de tip Max s au stratul de tip Dense ce reprezintă un strat
total conectat cu următorul. Pentru a adăuga straturi de tip dense în modelul construit
anterior se vor folosi următoarele linii de cod:
from keras.layers import Dense
model.add(Dense(units=64,activation=’relu’,input_dim =100)
model.add(Dense(units=10,activatio n=’softmax’)

23
După ce modelul este finalizat din punct de vedere structural acesta urmează a fi
compilat și antrenat, iar în ultimă fază va fi folosit pentru a se realiza predicții pe baza
acestuia . A compila un model înseamnă a -l pregăti pentru antrenarea, în compilarea
modelului trebuie precizate câteva lucruri de bază cum ar fi ce tip de optimizare se va
utiliza, funcția obiectiv ce trebuie minimizată sau maximizată și masurile pe care le
evaluează modelul în timpul antrenării și al evaluării. (Keras, 2019) .
După ce modelul este pregătit acesta este supus antrenării, testării și utilizării.
Faza de antrenare într -o rețea neuronală artificială este cea mai costisitoare din
punct de vedere al resurselor , în special al timpului. Pentru a avea o antrenare r apidă a
unei rețele neuronale convoluționale este recomandat ă rularea acesteia pe plăci video
puternice, dedicate, ce au rolul de a lucra cu imagini.
Setul de date este format cu ajutorul modului urllib ; acesta adună și salvează
fotografii de pe diverse link -uri furnizate.
Din urllib s-a folosit funcția request deoarece nu se dore ște trimiterea nici unei
informații către link -urile ce oferea imaginile necesare construirii bazei de date ci doar
extragerea acestora.

3.2. Java

Limbajul de programare Java este un limbaj orientat obiect (Lafore, 2002) ,
puternic tipizat. Un cod compilat Java poate rula pe orice mașină ce are instalată o
mașină virtuală Java. Cum acest limbaj de program are este foarte întâlnit în zilele
noastre sunt o multitudine de dispozitive ce pot executa codul compilat de Java, cod ce
este într -un format standardizat numit cod de octeți . El are forma unui limbaj
intermediar între codul mașină și codul sursă. Printre aceste dispozitive ce pot rula cod
compilat Java se numără și telefoanele. (Oracle, 2019) . Logo -ul acestui limbaj este
reprezentat în Figură 11.

24

Figură 11 Logo Java (Oracle, 2019)

Există o versiune de Java ce permite programatorului să creeze cod ce poate fi
executat pe platfor me mobile, această versiune este: Java Platform Micro Edition (Java
ME).
Pentru o aplicație Android, Java este motorul ce pune în mișcare toate acțiunile
pe care aplicația le execută. Cum XML -ul generează o interfață cu utilizatorul, Java
facilitează acț iunile pe care interfața le pune la dispoziție.
Deoarece în ziua de astăzi telefoanele sunt extrem de des întâlnite iar numărul
persoanelor ce nu dețin cel puțin un astfel de dispozitiv este foarte mic, s -au dezvoltat
biblioteci și unelte ce funcționează pe astfel de dispozitive, medii din punct de vede re
al puterii de procesare. O bibliotecă importantă ce a fost utilizată în Java a fost
TensorflowLite, o versiune mai mică a Tensorflow -ului, ce poate rula fără probleme pe
dispozitive cu asemenea specificații.
Cel mai des scenariu de utilizare în care s e folosește biblioteca Tensorflow este
următorul: se creează modelul în limbajul Python, se antrenează până se ajunge la un
rezultat dorit după care modelul se salvează. Tot în Python se utilizează modulul
Tensorflow ce convertește modelul salvat de Keras în format protocol buffer.
Tensorflowlite este folosit pe dispozitivele Android să încarce modelul antrenat și să
facă predicții asupra lui.
TensoflowLite este folosit foarte des doar pentru a încărca un model și de a -l
utiliza, nu pentru a -l antrena deo arece puterea de calcul este foarte redusă în cazul

25
telefoanelor față de stațiile de lucru cum ar fi calculatoare cu procesoare puternice (i7,
i9) sau cu plăci video la fel de puternice (GTX 1080, GTX 2080).
O altă facilitate ce a fost utilizată în apl icație a fost reprezentată de integrarea
hărților Google. Android fiind o platformă software și un sistem de operare pentru
dispozitivele și telefoanele mobil e dezvoltată inițial pe un nucleu linux de către
Google ; acesta din urmă pune la dispoziție dezvol tatorilor de aplicații mobile câteva
dintre serviciile sale, cum este de altfel Google Maps.
Interacțiunea cu hărțile Google se face printr -un API prin intermediul codului
Java. Acest API facilitează aplicarea asupra hărților a diferitelor acțiuni cum ar fi :
amplasarea diferitelor markere la anumite locații, mărirea sau micșorarea mapei sau
mișcarea camerei asupra unei porțiuni din mapă. (Smyth, 2017)

3.3. SQLite

SQLite este o bibliotecă C care implementează un motor de baze de date SQL .
Acesta nu funcționează dup ă modelul client -server ci este mai de grabă încorporat în
program. Această bază de date este o alegere foa rte populară pentru a ține toate
entitățile bazei de date deoarece se pot memora definițiile, tabelele, indicii și datele
într-o singură filă din interiorul dispozitivului. SQLite este incorporată în sistemul
Android. (SQLite, 2019) .

Figură 12 Logo -ul Android și logo -ul SQLite (SQLite, 2019)

Această tehnologie cere mai puține configurări decât un model de bază de date
ce funcționează după modelul client -server. SQLite poartă denumirea de zero -conf

26
deoarece nu necesi tă un management de serviciu cum ar fi un script de pornire sau nu
necesită un sistem de interacționare bazat pe o conectare cu un nume și cu o parolă.
Controlul asupra bazei de date este dat de permisiunile de fișiere pe care utilizatorul le
impune asupra bazei de date.
Tipurile de date ce există în SQLite sunt următoarele: null c e desemnează lipsa
unei valori, INTEGER ce reprezintă o valoare întreagă cu semn stocată pe 1, 2, 3, 4, 6
sau 8 biți depinzând de magnitudinea valorii, REAL ce reprezintă o valoare reală
memorată pe 8 biți, TEXT ce reprezintă o valoare de tip șir de caract ere și BLOB ce
reprezintă datele blob, se stochează exact cum au fost introduse.
După o mică observație asupra tuturor tipurilor de date prezente reiese faptul că
SQLite nu are o clasă rezervată pentru stocarea datelor și a orelor, în schimb el deține
anum ite funcții încorporate care sunt capabile să stocheze date și ore sub formă de text,
real sau întreg. În cazul stocării sub formă de text trebuie să se utilizeze un anumit
format pentru oră și pentru dată, pentru aplicația curentă formatul pentru dată est e
„yyyy -MM-dd” iar formatul pentru oră este „hh:mm”. În cazul stocării datei ca întreg,
se memorează sub formă de timp Unix, adică numărul de secunde de la 1970 -01-01 ora
00:00, în cazul stocării datei ca real se reprezintă numărul de zile de la amiază în
Greenwich pe 24 noiembrie, 4714 î.Hr. conform calendarului proleptic gregorian.
(SQLite, 2019)
Cele mai frecvente operații ce s -au realizat pe baza de date au fost operațiile de
selecție a informației deoarece adăugarea în baza de date se realizează o singură dată, la
început.
Pentru a se realiza legătura dintre SQLite și aplicație, Java oferă o clasă numită
SQLiteOpenHelper ce ajută la comunicarea cu biblioteca SQLite. În cele mai multe
cazuri pentru fiecare entitate ce urmează a fi creată în baza de date se creează și o clasă
Java pentru a se extrage sau introduce date într -un mod mult mai eficient și natural.
Baza de date se creează cu ajutorul unei scheme ce conține numele entității ce se
dorește a fi adăugată precum și atribu tele acesteia. Pe baza acestei scheme, baza de date
va crea reprezentările necesare.

27
Capitolul 4. Descrierea aplicației

4.1. Introducere

Inteligența artificială bazată pe recunoașterea obiectelor, a oamenilor și
animalelor în imagini este un lucru întâlnit frecvent în ziua de astăzi, această tehnologie
ne ajută și ne îmbunătățește viața.
Aplicația creată se bazează pe recunoașterea animalelor în imagini. Ea
analizează cadre primite de la utilizator și încearcă să clasifice formele pe care le
distinge. Aplic ația a fost concepută pentru a determin a persoanele să iasă, să exploreze
și să învețe cât mai multe despre faună.
Platforma pe care s -a ales dezvoltarea aplicației a fost cea mobilă din mai multe
motive printre care: este disponibilă oriunde, nu depinde de un loc în care se pot accesa
informațiile, platforma mobilă este preferată în rândul tinerilor și nu numai și est e o
oportunitate de a cerceta spațiul înconjurător, explorând un mediu calm și liniștit cum
este o grădină zoologică. Proiectul a fost făcut pentru o grădină zoologică de
dimensiuni mici cu anumite specii de animale . Aceste specii pot fi identificate de
aplicație într -un cadru mai vast decât cel al grădinii zoologice, cu alte cuvinte dacă un
utilizator dorește să cunoască un animal într -o excursie cu mașina prin savană iar
animalele de acolo sunt cunoscute de soft, aplicația poate furniza un răspuns prompt și
corect legat de tipul și denumirea ac elor animale.
Pentru a învăța modelul , a fost necesară crearea unui set de date cu un conținut
relevant pentru fiecare clasă în parte deoarece și cele mai mici poze nerelevante ar fi
influențat rezultatul antrenării . După ce setul de date a fost colectat a început căutarea
prin teste a unei arhitecturi potrivite a rețelei neuronale ce a fost antrenată și exportată
cu scopul de a fi utilizată în Android.
O reprezentare grafică a procedurii ce va fi urmate pentru a se realiza aplicația
este prezentată în Figură 13.

28

Figură 13 Schema aplicației

4.2. Crearea setului de date

Crearea unui set de date este un pas destul de complicat în procesul de
construire a rețelelor neuronale artificiale de convoluție deoarece găsirea și filtrarea
imaginilor necesită destul de mult timp . În primul rând s -a făcut o cercetare referitoare
la conținutului unei grădini zoolog ice, cu alte cuvinte s -au căutat informații despre
grădinile zoologice din mai multe țări și s -au extras doar animalele ce erau mai
frecvente . Aplicați a va avea în componență animalele cel mai des întâlnite într -o
grădină zoologică .
Clasele de animale ce se găsesc în această aplicație sunt reprezentate în Tabel 1.

29
Tabel 1 Componența setului de date
Nr. crt. Numele animalului Număr imagini d in setul de date Sursa imaginilor
1 Coiot 1000 ImageNet
2 Elefant 1000 ImageNet
3 Gorila 1000 ImageNet
4 Leu 1000 Flickr Images
5 Panda 1000 Flickr Images
6 Papagal 1000 ImageNet
7 Păun 1000 Flickr Images
8 Zebră 1000 Flickr Images

Imaginile au fost extrase de pe site -uri dedicate pentru formarea de seturi de
date pentru rețelele neuronale. Site -urile folosite pentru crearea setului de date curent
sunt ImageNet -ul -imaginile extrase din el fiind descărcate cu ajutorul unui script , și
Flickr Images, imaginile extrase de pe acest site fiind preluate cu ajutorul extensiei
Chrome, Download All Images .
ImageNet -ul este un site ce conține o bază de date în care se pot găsi imagini
despre animale, oameni și obiecte. Imaginile sunt oferite de diverse site -uri sub formă
de link. Pentru a descărca imaginile de pe acel site s -a creat un script special scris în
Python ce parcurge fiecare link oferit de către ImageNet referitor la o categorie și
descarcă conținutul acestora.
Modulul Python ce se folosește pentru a descărca imaginile este urllib.request ,
modulul os a fost și el utilizat pentru a automatiza crearea directoarelor în funcție de
numele animalului căutat.
Mai întâi s -au stocat numele și link -urile categoriilor furnizat e de Image Net
unde se găsesc link -urile cu pozele pentru fiecare categorie în parte , după care link-
urile categoriilor au fost preluate . Următorul cod permite citirea întregului conținut
aferent:
images_urls=urllib.request.urlopen(images_link[i]).read().decode()

30
Se stochează într -o variabilă întregul conținut al paginii din link . Conținutu l
link-ului este reprezentat de o listă de căi către imaginile clasei. Aceste căi sunt extrase
pe rând din conținut și sunt accesate pentru a descărca imaginile.
urllib.request.urlretrieve(j,'dataset/'+folder_name[i]+"/"+str(pic
_num)+'.jpg')
Unde j este un link extras din tr-o categorie, după care este destinația imaginii
salvate și numele ei și formatul de salvare, format jpg.
O problemă întâmpinată a fost aceea că imaginile de pe majoritatea link -urilor
au fost șterse sau nu existau permisiuni de accesib ilitate. Fapt pentru care numărul de
poze a fost diminuat destul de mult. Dacă în medie Image Net-ul furnizează pentru
fiecare categorie în jur de 1000 de imagini, prin descărcare se obțin undeva la jumătate
această jumătate fiind și ea aleasă astfel încât să rămână doar poze relevante. La pozele
extrase s -au mai adăugat poze provenite de pe internet , de pe site -ul Flickr Images.
Pentru clasele ce nu au fost găsite pe Image Net, acestea au fost extrase din
rezultate ale căutării de pe site -ul Flickr cu ajuto rul extensiei Chrome , Download All
Images .
Numărul pozelor obținute pentru fiecare clasa în final este de 1000 , un număr la
care se vor adăuga poze alterate artificial cu ajutorul codului.
Structura unei clase se poate observa în Figură 14.

31

Figură 14 Eșantion de imagini extras din clasa gorilă

Cum rețelele neuronale sunt capabile să clasifice poze similare, nu foarte
diferite, de cele cu care au fost antrenate, imaginile ce le va primi și alor căror precizie
va fi foarte mare vor fi cele ale căror aspect este similar cu ceea ce rețeaua a mai văzut.
Setul de date influențează foarte mult modul în care aplicația se compo rtă în mediul
real. În general pozele pe care le recunoaște aplicația foarte bine sunt acele poze în care
animalul este centrat în prim plan, procentajul de recunoaștere scăzând în cazul în care
pozele sunt foarte diferite față de cele din faza de antrenar e.
O adăugare de poze relevante pentru fiecare clasă în parte ar crește procentajul
în care rețeaua neuronală recunoaște imaginile deoarece a văzut mai multe cadre în care
animalul respectiv se află.
4.3. Construirea modelul rețelei neuronale

Construirea modelul este o parte dificilă și delicată în același timp deoarece
trebuie să se ia în calcul dimensiunea imaginilor ce vor intra în rețea și cum vor fi ele
procesate pe parcurs.

32
Un model bun este un model care extrage cât se poate de bine caracteristicile
din imagini și nu scade dimensiunea imaginii omițând anumite caracteristici
importante. Numărul neuronilor de pe fiecare strat este și el luat în considerare
deoarece numărul de neuroni trebuie să fie în concordanță cu numărul de filtre.
Atunci când se coboară în rețeaua de convoluție se extrag anumite caracteristici
ale imaginii, ce trebuie să aibă mai multe filtre disponibile care să le învețe. Tot în
acest proces descendent, în care se coboară în rețeaua convoluțională , reducerea
imaginii trebuie să scadă gradual , adică imaginea nu trebuie să se redimensioneze
repede deoarece în procesul de reducere se pot omite caracteristici vitale pentru
recunoaștere.
Construirea modelului î ncepe cu importarea modulelor specializate pe
construirea rețelelor artificiale . Aceste module sunt extrase din Keras și se preferă
importarea componentelor utilizate deoarece importarea întregului modul Keras nu este
necesară .
from keras.models import Se quential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.l ayers.core import Dropout
from keras.layers.core import Dense
from keras import backend as K
Modelul pe care se construiește este unul liniar suprapus, straturile sunt
succesive . Acest model se numește Sequential . Straturile ce se vor folosi în aplicație
sunt Conv2D , MaxPooling2D și BatchNormalization . Primul strat este stratul centrat al
acestei rețele convoluționale, fiind un strat convoluțional, al doilea este un strat de
Pooling , cel de MaxPooling care folosește un filtru 2D ce scanează imaginea și extr age
doar valoarea maximă dintre filtru și mapa de caracteristici , iar ultimul strat este un
strat de normalizare a valorilor din straturile ascunse.

33
După includerea componentelor principale în program se inițializează modelul,
se declară dimensiunile imag inii ce va urma a fi prelucrată într -o structură de tip tuplu.
Tot în această fază se cercetează ce canal se utilizează, cum în acest caz se folosește
partea din spate a Tensorflow -ului se va utiliza ultimul canal ; dacă se folosea alt
framework cum ar fi Theano se utiliza primul canal, diferența între canale este dată de
ordinea în care vin parametrii de dimensiune a imaginii. Pentru primul canal forma
imaginii va fi dată de un tuplu de forma (adâncime, înălțime, grosime) pe când în cazul
ultimului canal tu plul are forma (înălțime, grosime, adâncime), lucru important pentru
forma de intrare a rețelei dar și pentru straturile de normalizare. Imaginea ce va urma a
fi trecută prin rețeaua convoluțională va avea următoarele dimensiuni: înălțime=96,
grosime=96 și adâncime=3, adâncimea este dată de spectrul de culori din care este
formată . Cum imaginile introduse și antrenate sunt color atunci spectrul este RGB, 3
culori.
Primul bloc format este alcătuit din un strat convoluțional de 32 de filtre cu un
nucleu de 3 x3 activat de o funcție numită „relu”, urmat de un strat de normalizare.
model.add(Conv2D(32, (3, 3), padding="same",
input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(3, 3 )))
model.add(Dropout(0.25))
Următorul strat este de micșorare a imaginii, adică de pooling. Stratul de pooling este
de dimensiune 3×3 ce reduce dimensiunea repede, de la 96×96 la 32×32. După ce se
realizează micșorarea se utilizează stratul de Dropout în procent de 25%. Dropout -ul
deconectează aleator noduri ce conectează stratul curent de stratul următor, acest proces
de deconectare a nodurilor în timpul antrenării loturilor ajută învățarea . Nici un nod
individual nu este responsabil pentru predicția unei clase, a unui obiect, a unei muchii,
a unui colț sau a oricărei alte caracteristici.
Următorul bloc este format din două perechi formate dintr -un strat
convoluțional urmat de o activare de tip „relu”, perechile sunt urmate de un procent de
25% rată de d ropout. Prin metoda de a pune unul peste altul două straturi

34
convoluționale activate de „relu” obținem mult mai multe caracteristici fundamentale.
Filtrele pentru cele două straturi au fost crescute la 64 deoarece cu c ât coborâm printre
straturile rețelei cu atât se diminuează dimensiunile volumului iar necesitatea mai
multor filtre crește în prioritate. Stratul de pooling ce termină acest bloc este de
dimensiune mai mică deoarece nu vrem să reducem dimensiunile prea repede, fapt
pentru care dimensiunea ace stuia este de 2×2.
Alt bloc ce este preliminar în acest model este format din 2 straturi
convoluționale ce au 128 de filtre fiecare, cu un nucleu de 3×3, activate de o funcție
„relu”, finalizându -se cu un dropout de 25%.
Vârful modelului rețelei convoluționale este dat de liniarizarea mapelor de
caracteristici, acest lucru se realizează cu Flatten (). Liniarizarea este conectată total cu
un strat de 1024 de neuroni, strat activat de funcția „relu” cu un dropout de 50%. În
general se utilizează valori mici ale dropout -ului în interiorul rețelei și o valoare puțin
mai mare la finalul rețelei.
Modelul se încheie cu un strat întreg conectat ce are numărul de neuroni egal cu
numărul de clase, activat de funcția de clasificare „softmax”, funcție ce returnează
probabilitatea pentru fiecare clasă în parte.
Toate straturile convoluționale au fost formate cu padding -ul identic, adică
dimensiunea mapei de caracteristici rămânând identică în urma parcurgerii lor. Aceste
straturi au fost urmate de straturi de normalizare.
Această arhitectură a fost aleasă după multiple teste cu diferite structuri
posibile. Pentru a se ajunge la această versiune a rețelei s -au adăugat/șters straturi sau
filtre, s -au schimbat dimensiunile i maginii și s -au schimbat valorile de dropout.
Arhitectura rețelei a fost inspirată după arhitectura VGGNet deoarece are câteva
caracteristici comune. Asemănările între rețeaua construită pentru acest proiect și
VGGNet sunt următoarele: se utilizează doar straturi convoluționale ce au nucleul de
3×3 ce se suprapun unele peste celelalte atunci când se coboară în rețea, volumul se
reduce folosind Max -Pooling și nu Average -Pooling iar straturile complet conectate din
final sunt activate de funcția Softmax.

35
Modelul rețelei neuronale afectează în mod direct timpul de antrenare, în cazul
în care o rețea convoluțională este mai adâncă atunci timpul de antrenare este mai mare
deoarece imaginea parcurge mai multe filtre ceea ce înseamnă mai mulți parametrii de
antrenat.
Pentru o vizualizare mai bună asupra straturilor s -a creat Figură 15.

36

Figură 15 Arhitectura rețelei convoluționa le

37
4.4. Antrenarea rețelei neuronale

Antrenarea rețelei neuronale este prima în topul celor mai costisitoare activități
în crearea rețelelor artificiale convoluționale din punct de vedere al timpului și al
resurselor pe care această activitate le cere. Antrenarea finală a fost făcută pe un la ptop
cu o placă video performantă iar testele au fost făcute pe o mașină mai modestă dar
disponibilă la momentul acela.
Procesul de antrenare are o durată în general destul de mare : pentru arhitectura
creată anterior, antrenarea cu 50 de epoci a durat, pe o mașină ce avea placă grafica
dedicată model GTX 1050ti 4GB GDDR5, 11 minute . Timpul de antrenare a fost
îndelungat deoarece în momentul în care s-au realizat teste ale arhitecturi i,
disponibilitatea resurselor era limitată, testele fiind executate pe o mașină mai slabă . O
testare a unei rețele pe calculatorul pe care s -a început crearea aplicației ar fi durat între
3 și 5 ore . În Tabel 2 se găsesc ultimele două antrenări pe rețeaua formată. Ultimul test
este net superior în acuratețe deoarece numărul pozelor din setul de date este
semnificativ mai mare. Epocile au scăzut datorită observării prin teste a prezenței unei
supra antrenări după epoca 50.
Timpul în care s -a obținut configurația rețelei nu ar fi fost prea mare în cazul în
care se cunoștea arhitectura optimă a rețelei precum și imaginile optime pentru
antrenare. Cum în acest caz nu a fos t o situație fericită în care arhitectura a fost
construită o singură dată după care antrenată, testările repetate pe diferite arhitecturi, pe
diferite epoci și pe diferite imagini au făcut ca dezvoltarea unei rețele calitative și a
unei antrenări asemenea să dureze săptămâni de muncă.

Tabel 2 Date despre starea ultimelor două antrenări
Nr. crt. Nr. mediu de imagini
din setul de date Acuratetea
modelului Nr. epoci Timp de
antrenare Unitate de
antrenare
1 300 0.86 100 4 ore CPU
2 1000 0.96 50 11 minute GPU

38
Programul de antrenare începe cu includerea modulelor necesare, exact ca în
cazul construirii modelului.
from retea import Model
from sklearn.preprocessing import LabelBinarizer
from keras.callbacks import ModelCheckpoint
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from keras.preprocessing.image import ImageDataGenerator
from imutils import paths
import matplotlib.pyplot as plt
import numpy as np
import random
import pickle
import cv2
import os
Se importă modelul, apoi din sklearn.preprocessing se importă LabelBinarizer
ce ajută la introducerea unui șir de etichete ce sunt inițial în șiruri de caractere și sunt
codate printr -un procedeu numit One-hot encoding pentru a normaliza datele ce intra în
rețea, deoarece se dorește ca într -o rețea să se utilizeze doar valori numerice. Tot din
sklearn se importă și ModelCheckpoint ce creează un checkpoint în antrenare atunci
când se găsește o îmbunătățire sau după ce se te rmină o epocă d eoarece procesul de
antrenare durează mult iar în cazul unei defecțiuni neprevăzute antrenarea să nu
înceapă de la capăt. Train_test_split se va utiliza pentru a împărți setul de date format
în antrenare și testare, classifciation_report este utilizat pentru a afișa un raport de
acuratețe final pentru fi ecare clasă în parte. Path și os sunt utilizate pentru a găsi calea
pentru fiecare imagine din dosarul set de date precum și extragerea etichetei
corespunzătoare fiecărei imagini. Se importă i nstrumente matematice cum ar fi: numpy ,
random , matplotlib , acesta din urmă este utilizat pentru afișarea unui grafic pentru a
vedea starea rețelei la final. Biblioteca OpenCV este utili zată pen tru a normaliza
imaginile.
Se stabilește la început dimensiun ile imaginii, și anume 96×96, dimensiuni ce au
fost selectate după următoarele criterii: să nu aibă o dimensiune prea mare deoarece

39
timpul computațional ar crește semnificativ și să nu aibă o dimensiune prea mică
deoarece ar fi greu de extras caracteristic ile iar prin micșorare este posibil ca
fotografiile să piardă din calitate.
Biblioteca OpenCV citește imaginile, le modifică dimensiunea și le stochează
într-o listă . În acest timp se completează și o listă cu etichetele fiecărei imagini astfel
încât , la final se v or obține două liste ce vor avea aceeași dimensiune . Prin urmare poza
de pe poziția y va avea eticheta de pe poziția y din vectorul de etichete.
Normalizarea datelor se face în următorul mod: se parcurg listele de imagini iar
fiecare imagine est e transformată într -un np.array iar fiecare pixel al acelei imagini
este împărțit la 255 pentru a se obține numere cuprinse între 0 și 1, lucru ce grăbește
procesul de învățare. În cazul listei de etichete acestea sunt transformate în np.array
după care ma i târziu se va folosi LabelBinarizer pe etichetele de intrare și de ieșire
pentru convertirea lor în valori numerice.
Următorul pas este împărțirea bazei de date pentru antrenare și pentru testare,
lucru ce este realizat cu ajutorul opțiunii train_test_split . Se păstrează 25% din date
pentru testare și 75% din date vor fi utilizate pentru antrenare.
Se mărește numărul de poze pentru antrenare prin inițializarea unui
ImageDataGenerator care primește imaginile de antrenare și creează alte imagin i prin
procese de ro tație, de mutare, de răsturnare , de m ărire sau micșorare ; procese aplicate
imaginilor primite.

40
img_size = (96,96)
model = Model(width=img_size[0], height=img_size[1], depth=3,
classes=len(lb.classes_))
model = model.CreareModel()
INIT_LR = 1e -3
EPOCHS = 50
BS = 32
print("[INFO] antrenare retea…")
model.compile(loss="categorical_crossentropy",
optimizer='Adam',metrics=["accuracy"])
checkpointPath = "weights -best.hdf5"
checkpoint=ModelCheckpoint(checkpointPath,monitor='val_acc',verbo s
e=1,save_best_only=True,mode='Max')
callback_list = [checkpoint]

H = model.fit_generator(aug.flow(trainX, trainY,
batch_size=BS),validation_data=(testX, testY),
steps_per_epoch=len(trainX) // BS,epochs=EPOCHS, callbacks =
callback_list)
print("[INFO] evaluare retea…")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),
predictions.argmax(axis=1), target_names=lb.classes_))
model.save( iesire[0])
model.save("modeltrained.h5")
f = open( iesire[1],"wb")
f.write(pickle.dumps(lb))
f.close()
În codul de mai sus se observă că se instanțiază un obiect ce reprezintă modelul
creat, se stabilește rata de învățare, numărul de epoci și mărimea lotului. Modelul creat
se compilează și se stabil ește funcți a ce se dorește a fi minimizată adică funcție de
clasificare, se optimizează cu „Adam” și în momentul evaluării modelului se va avea ca
măsură de testat acuratețea modelului.
Se inițializează un checkpoint ce va fi apelat după fiecare epocă și acesta va
salva cea mai bună epocă găsit ă ce are valoarea acurateței cea mai mare.

41
Din moment ce modelul este format și compilat acesta este pregătit de
antrenare.
Antrenarea modelului se realizează cu funcția fit_generator ce are ca
argumente: imaginele crescute artificial prin ImageDataGenerator , datele de validare,
numărul de pași pentru fiecare epocă, numărul de epoci și checkpoint -ul creat anterior.
Procesul de antrenare durează o perioadă considerabilă de timp și utilizează
resurse din belșug.
Pe durata ant renării , se vor avea în vedere următorii parametrii: acc ce oferă
acuratețea rețelei pe datele de antrenare, val_acc ce oferă acuratețea rețelei pe datele de
validare, loss ce definește funcția obiectiv ce trebuie minimizată pentru datele de
antrenare și val_loss ce oferă informații despre starea funcției obiectiv pe datele de
validare.
După ce procesul se termină , rețeaua este evaluată , modelul antrenat precum și
etichetel e sunt salvate. La finalul procesului de antrenare se vor furniza trei metode ce
vor avea a scop oferirea de informații despre starea rețelei.
Prim a este evaluarea rețelei în funcție de precizie , recall și F1 score rezultate
consemnate în Tabel 3. (Shung, 2018)
A doua metodă este evaluarea ei în funcție de matricea de confuzie Figură 16.
Ultima metodă de evaluare este prin interpretarea graficului obținut prin
înregistrări ale parametrilor loss, acc, val_acc și val_loss .

42

Tabel 3 Evaluarea rețelei neuronale utilizate
Nume Precizie Recall F1-score
Coiot 0.90 0.89 0.89
Elefant 0.97 0.93 0.95
Gorilă 0.94 0.98 0.96
Leu 0.96 0.93 0.94
Panda 1.00 0.98 0.99
Papagal 0.95 0.97 0.96
Păun 0.99 0.98 0.98
Zebră 0.96 1.00 0.98
Acuratețe 0.96 0.96 0.96

Pentru explicarea parametrilor de măsurare ale rețelei se va utiliza următoarea
matrice de confuzie, reprezentată în Tabel 4.

Tabel 4 Matrice de confuzie pentru estimatorii modelului (Shung, 2018)
Prezis
Real Negativ Pozitiv
Negativ Adevărat Negativ Fals Pozitiv
Pozitiv Fals Negativ Adevărat Pozitiv

Precizia este un bun instrument de evaluare al rețelei neuronale deoarece ea
determină cât de calitativă este rețeaua. Precizia determină câte elemente identifica te
corect, sau pozitive, sunt într -adevăr pozitive. Calcului ei se face după formula (8).
(8) 𝑃𝑟𝑒𝑐𝑖𝑠𝑖𝑜𝑛 =𝐴𝑑𝑒𝑣 ă𝑟𝑎𝑡 𝑃𝑜𝑧𝑖𝑡𝑖𝑣
𝐴𝑑𝑒𝑣 ă𝑟𝑎𝑡 𝑝𝑜𝑧𝑖𝑡𝑖𝑣 +𝐹𝑎𝑙𝑠 𝑃𝑜𝑧𝑖𝑡𝑖𝑣
Recall calculează câte din răspunsurile real adevărate sunt identificate de model
ca adevărate. Formula prin care se calculează este (9).
(9) 𝑅𝑒𝑐𝑎𝑙𝑙 =𝐴𝑑𝑒𝑣 ă𝑟𝑎𝑡 𝑃𝑜𝑧𝑖𝑡𝑖𝑣
𝐴𝑑𝑒𝑣 ă𝑟𝑎𝑡 𝑝𝑜𝑧𝑖𝑡𝑖𝑣 +𝐹𝑎𝑙𝑠 𝑁𝑒𝑔𝑎𝑡𝑖𝑣=𝐴𝑑𝑒𝑣 ă𝑟𝑎𝑡 𝑃𝑜𝑧𝑖𝑡𝑖𝑣
𝑅𝑒𝑎𝑙 𝑃𝑜𝑧𝑖𝑡𝑖𝑣

43
F1 Score este utilizat atunci când se caută un echilibru între precizie și recall,
acesta este calculat după formula (10).
(10) 𝐹1=2∗𝑃𝑟𝑒𝑐𝑖𝑧𝑖𝑒 ∗𝑅𝑒𝑐𝑎𝑙𝑙
𝑃𝑟𝑒𝑐𝑖𝑧𝑖𝑒 +𝑅𝑒𝑐𝑎𝑙𝑙
O altă modalitatea prin care se poate face o estimare a calității unei rețelei
neuronale de clasificare este formarea matricei de confuzie. Această matrice reprezintă
grafic categoriile și valorile reale și prezis e. De exemplu, dacă pe o linie avem clasa
elefant pe coloane vom avea toate animalele din care se face clasificarea. În intersecția
dintre linia clasei elefant și o coloana ce reprezintă un animal din clasele rețelei, de
exemplu zebră, se va găsi o valoare între 0 și 1. Dacă valoarea este apropiată de 0
atunci modelul nu este tentat să furnizeze un rezultat pozitiv pentru zebră dacă va primi
un elefant, în caz contrar, dacă valoarea este apropiată de 1 rețeaua va întoarce eticheta
zebră de cele mai multe or i când va primi un elefant. Pentru această rețea neuronală,
matricea de confuzie este reprezentat ă în Figură 16.

Figură 16 Matri ce de confuzie

44
Ultima metodă de evaluare a rețelei este dată de interpretarea graficului rezultat în
timpul antrenării rețelei. Grafic ul este prezentat în Figură 17.
Din grafic se poate observa o creștere rapidă a valorii acurateței rețelei pentru
datele de test după care aceasta ajunge să se stabilizeze de la epoca 30, o continuare
după epoca 50 ar fi putut duce la o supra antrenare. Acuratețea pentru datele de test
oscilează foarte mult în primele epoci dar ușor se stabilizează si urmează calea
acurateței pentru datele de antrenare. Loss-ul pentru datele de antrenare scade în mod
constant îndreptându -se rapid spre valoarea 0, lucru ce poate fi periculos deoarec e o
apropiere extrem de mult către valoarea 0 poate indica o supra antrenare, rețeaua învață
datele de antrenare pe de rost neputând înțelege alte date. Val_loss oscilează destul de
mult, dar și aceasta are o tendință de diminuare reliefând faptul că rețea ua furnizează
rezultate calitative și pe datele de validare.

Figură 17 Grafic obținut din procesul de antrenare

45
Salvarea rețelei în această formă ajută la integrarea ei într-o aplicație Android.
Următorul pas ce trebuie realiza t pentru a crea un obiect compatibil cu platforma dorită
este convertirea modelului într -un format relevant.

4.5. Transformarea modelul din Keras în Tensorflow

Din moment ce modelul este antrenat și salvat, acesta trebuie să fie convertit
într-un format ce poate fi citit de tensorflowlite , bibliotecă ce este prezentă în Android.
Convertirea modelului începe prin inițializarea componentelor necesare,
Tensorflow și Keras .
Modelul s-a încărcat într-o variabilă după care s -a creat o funcție cu
argumentele: un saver, saver provenit din Tensorflow ce avea ca scop salvarea
modelului, modelul și numele straturilor de intrare și de ieșire. Numele straturilor de
intrare și de ieșire se pot deduce ușor din modelul creat la început. Pentru a identifica
numele stratului de început trebuie găsit locul din model în care s -a declarat forma de
intrare a datelor, în cazul curent acel start este primul strat convoluțional cu intrarea,
deci numele intrării este „conv2d_1_input”. Același raționament se aplică și în cazul
obținerii numele stratului de ieșire. Se caută ultimul strat și ca precizia de găsire a
acestuia să fie maximă se știe că este activat de softmax și este al doilea s trat
convoluțional prin urmare numele său este: „dense_2/Softmax”.
Exportarea modelului din Keras trebuie să fie reprezentata de crearea unui fișier
cu extensia .pb adică un protobuf file. Acest PB este o versiune serializată a modelului
creat cu toate po nderile antrenate.
Se scrie graful și se salvează , fapt ce ajută la identificare lui mult ma i ușoară, se
îngheață modelul, cu alte cuvinte se salvează ponderile care indiferent de variabilitatea
lor, devin constante, acestea neputând fi modificate. Model ul rezultat fiind salvat în
fișierele aplicației mobile.

46
def export(saver,model,nod_intrare,nod_iesire):
tf.train.write_graph(K.get_session().graph_def,'out', \
numeModel +"_graph.pbtxt")
saver.save(K.get_session(),'out/'+numeModel+'.chk p')

freeze_graph.freeze_graph('out/'+numeModel+'_graph.pbtxt',None, \
False,'out/'+numeModel+'.chkp',nod_iesire, \
"save/restore_all","save/Const:0", \
"out/blocat_"+numeModel+'.pb',True,"")

print("Graph salvat")

model = load_model("outputNvidia/model.model")
export(tf.train.Saver(),model,["conv2d_1_input"],"dense_2/Softmax"
)

4.6. Dezvoltarea aplicației Android

Aplicația Android are o structură complexă ce cuprinde partea vizuală, formată
cu ajutorul XML -ului, parte a din spate, reprezentată de codul Java și baza de date ce
ajută la stocarea și accesarea informațiilor.
În Android ferestrele se numesc activități iar fiecare activitate are în spate un
cod scris în Java, cu alte cuvinte pentru fiecare fer eastră, layout, există o clasă
corespunzătoare care gestionează evenimentele pe care utilizatorul le declanșează.

4.6.1. Baza de date

Baza de date folosită în Android este SQLite. Pentru crearea ei s -a realizat o
clasă specială numită DatabaseHelper ce extind e, moștenește, clasa
SQLiteOpenHelper . Clasa creată, DatabaseHelper , este corpul bazei de date, aici se va
declara imaginea bazei de date, entitățile ce o conțin și atributele ei.
Această clasă ne permite să creăm baza de date, să o îmbunătățim sau să o
ștergem, acțiuni obligatorii deoarece provin din clasa de bază. Pe lângă funcțiile pe care
trebuie să le avem obligatoriu pentru a crea baza de date și a adăuga entitățile se pot
adăuga funcții noi ce vor fi utilizate în interiorul aplicației unde este nevo ie de

47
informații din baza de date. Acest mod de lucru este necesar pentru a ține toate funcțiile
și alte variabile relevante pentru un obiect, cum este în acest caz baza de date, pentru a
nu se îngreuna codul.
Având pregătită funcția ce va crea baza de da te și va interacționa cu ea pe
parcursul programului trebuie să se formeze schema bazei de date, entitățile, atributele
și legăturile dintre acestea. Reprezentarea bazei de date a fost făcută cu ajutorul
diagramei entitate legătură din Figură 18 Diagrama entitate legătură . (Vlădoiu, 2019) .

Figură 18 Diagrama entitate legătură

În această figură se observă mulțimile:
1) Mulțimea Animal, ce stochează informații despre animalele ce sunt învățate de
către rețeaua neuronală. Atributele acestei entități sunt:
a. Nume – numele animalului
b. Tip – tipul animalului (ex. mamifer)
c. Dietă – tipul de hrană consumat de animal (ex. ierbivor)
d. Înălțime – înălțimea animalului măsurată în centimetrii (cm)
e. Greutate – greutatea animalului măsurată în kilograme
f. Viteză – viteza pe care animalul o poate atinge măsurată în km/h
g. Dviață – durata medie de viață la care animalul poate ajunge măsurată în
ani
h. Culoare – culoarea predominantă a animalului
i. HranăF – alimentul preferat pe care animalul în consumă

48
j. Descriere – descrierea lui cu câteva lucruri interesante despre acesta
k. Imagine – calea imaginii ce va fi exploatată pentru a se afișa imaginea
În această mulțime cheia primară este Nume, aceasta ajută la identificarea unică a
fiecărei înregistrări în baza de date.
2) Mulțimea Locație ajută la stocarea informațiilor legate de regiunea globa lă unde
se găsesc animalele. Atributele acestei entități sunt:
a. ID – id-ul locației
b. Nume – numele locației, acesta se denumește identic cu continentul pe
care este amplasat dar zona este dată de coordonatele următoare
c. Lat – coordonatele latitudinii globale la care se găsește tipul de animal
d. Lon – coordonatele longitudinii globale le care se găsește tipul de animal
Cheia prim ară ce identific ă unic un tuplu în această tabelă este ID.
Aceste două entități sunt unite printr -o legătura de tip multi -multi (m -m)
denumită „se află”. Legătura multi -multi nu se poate reprezenta în nici una dintre cele
două tabele. Singura cale de reprezentare a unei legături de acest tip este prin
construirea unei tabele separate. Acest lucru este reliefat prin prezența în baza de da te a
tabelei denumită „Poziție”.
Tabela „Poziție” conține două atribute, Nume și ID_locație ce reprezintă chei
străine pentru tabela Animale respectiv Locație. Structura tabelei poate fi vizualizată în
Figură 19. Cheia primară în acest tabel este o cheie compusă formată din combinația
celor 2 tabele .

Figură 19 Structura tabelului de legătură

După definirea corectă și logică a schemei bazei de date se completează clasa
Java, DatabaseHelper.

49
Datele membru ale clasei vor fi reprezentate de: șiruri de caractere cu numele
capului de tabel pentru fiecare atribut al fiecărei entități în parte, numele fiecărui tabel,
numele bazei de date, versiunea bazei de date și contextul în care se lucrează adică
contextul ce provine din activitatea care a cerut o interogare pentru baza de date.
Funcția ce creează baza de date este următoarea:
@Override
public void onCreate(SQLiteDatabase db) {
String query = "create table "+TABLE_NAME+"("+COL1+" text
primary key,"+COL2+" text,"+COL3+" text,"
+COL4+" real,"+COL5+" real,"+COL6+" real,"+COL7+"
integer,"+COL8+" text,"+COL9+" t ext,"+COL10+" text,"+COL11+"
text)";
db.execSQL(query);
query="create table "+TABLE_LOCATIE+"("+COL1L+" integer
primary key,"+COL2L+" text,"+COL3L+" real,"+COL4L+" real)";
db.execSQL(query);
query="create table "+TABLE_POZIT IONARE+"("+COL1P+"
string,"+COL2P+" integer, primary key ("+COL1P+","+COL2P+"))";
db.execSQL(query);
initDatabase(db);
}
Se execută instrucțiunile SQL de creare a tabelelor independent, iar după
crearea tabelelor se apelează o funcție n umită initDatabase(db) ce ia ca parametru baza
de date și are ca scop popularea bazei de date cu înregistrări. Această acțiune de
populare se face direct în cod și pentru a nu se încărca foarte mult codul la partea în
care se adaugă descrierea animalelor, parte ce necesită un șir lung de caractere,
Android păstrează un inventar al string -urilor într -un fișier XML din resurse numit
strings.xml , loc în care descrierea este scrisă și apelată în codul în care se adaugă toate
datele.
Modularizarea string -urilor este o metodă foarte utilă în Android deoarece aici
se pot păstra toate denumirile, descrierile și textele din întregul program, acestea fiind
apelate la nevoie după numele pe care le primesc.

50
Pentru această aplicație s -au creat funcții ce au ca obiectiv interogarea bazei de
date, nu s -au creat și pentru adăugare deoarece utilizatorul nu are nevoie să adauge
animale, aplicația fiind una educativă și informativă.
O funcție nou definită este fillList(), funcție ce întoarce o listă de animale. În
această f uncție se realizează o interogare a bazei de date pentru a colecta numele și
imaginea tuturor animalelor prezente în baza de date, s -au selectat doar cele două
componente deoarece se dorește prezentarea animalelor sub formă de listă iar cele mai
reprezenta tive lucruri de prezentat în prim -plan sunt: numele animalului și înfățișarea
sa. Atributele selectate sunt setate unor obiecte de clasă animal și adăugate într -un
vector ce mai apoi este întors de către funcție.
La selectarea unui animal sau atunci când se realizează o clasificare se dorește
aflarea amănuntelor despre acel animal, fapt pentru care s -a construit o funcție ce aduce
din baza de date toate informațiile legate de un animal, identificarea animalului
făcându -se după nume. Informațiile din baza d e date sunt colectate și atribuite u nui
obiect de tip animal. În această fază se dorește și locația sau locațiile în care animalul
trăiește fapt pentru care se realizează un „join”, o intersecție de tabele, având toate
datele necesare obiectul de tip anima l este returnat.
Un exemplu de interogare este următorul:
SQLiteDatabase db = this.getReadableDatabase();
Cursor data = db.rawQuery("Select * from "+TABLE_NAME+"
where "+COL1+"='"+nume+"'",null);
Animal animal=null;
while (data.mov eToNext()){
String Nume=data.getString(data.getColumnIndexOrThrow(COL1));

Se inițializează o instanță a bazei de date pregătită pentru citire iar cu ajutorul
unui obiect de tip Cursor se scrie instrucțiunea sql care realizează interogarea. Structura
while este utilizată pentru a lua fiecare tuplu în parte și a -l exploata. În ac est exemplu
extras din cod se poate observa faptul că din tabela „Animal” valoare ce se află în
variabila TABLE_NAME, se extrage în variabila „Nume” string -ul ce se găsește pe

51
coloana „Nume” adică pe COL1, aceasta din urmă fiind atribuită cu valoarea capul ui
de coloană.

4.6.2. Clasele și activitățile aplicației

Clasele esențiale ce au avut rolul de a face posibilă dezvoltarea aplicației sunt
Classifier.java, Classification.java și TFClassifier.java, aceste clase formează nucleul
aplicației de recunoaștere.
Classification .class

Prima clasă ce va fi discutată este Classif ication .java . În ea se regăsesc trei
metode, un constructor și două date membru. Datele membru sunt utilizate pentru a
memora rata de încredere a clasificării și numele animalu lui rezultat, aceste variabile
fiind de tip real respectiv șir de caractere .
Constructorul setează valorile celor două variabile pentru început cu -1 și null,
pentru rată de încredere respectiv numele animalului detectat.
O metodă denumită update(float c onf,String nume) schimba cele două valori cu
parametrii conf și nume primit. Ultimele două funcții fiind funcții de tip get, ce întorc
valorile variabilelor conf și etichetă, aceste funcții având nume sugestive, getConf()
respectiv getLabel() .
Classifier .class

A doua clasă importantă este o clasă abstractă numită Classifier ce are în
componență declarările a două funcții, o funcție de tip String nume () și o funcție de tip
Classification recognize(final float pixels []). Această clasă urmează a fi moștenită
(extinsă) pentru a se definii cele două funcții într -un context logic. Clasa a fost creată
pentru gestionarea mai ușoară a codului.
TFClassifier .class

Clasa ce este utilizată pentru efectuarea clasificării este TFCla ssifier.java .

52
Aici se va utiliza biblioteca TensorflowLite iar pentru introducerea ei în aplicație
nu este suficient importarea la începutul clasei ci trebuie precizat importarea ei în
Grandle Scripts în secțiunea de dependențe.
implementation 'org.tenso rflow:tensorflow -android:+'
În această porțiune de cod aplicației i se precizează că se va utiliza biblioteca
Tensorflow , varianta pentru android cu cea mai nouă versiune, precizarea pentru
versiune este dată de prezența semnului „+”.
În momentul în care sistemul este înștiințat de importarea bibliotecii
Tensorflow , aceasta poate fi utilizată în interiorul clasei dorite.
Import
org.tensorflow.contrib.android.TensorFlowInferenceInterface;
Datele membru ale clasei TFClassifier sunt: eroarea ce va fi obținută în urma
clasificării, o instanță a interfeței cu Tensoflow -ul, un nume pentru modelul creat,
numele stratului de intrare, numele stratului de ieșire, dimensiunea imaginilor ce vor fi
prelucrate, lista de etichete și o listă de valori de predicție pentru fiecare animal în
parte.
TFClassifier.java conține patru funcții, create, name, recognize și citesteClase.
Funcția create este de tip TFClassifier primește ca parametru o variabilă de tip
AssetManager pentru ca programul să poată găsi calea către locul în care se află
modelul antrenat, variabile de tip String nume, caleModel, fisierClase, numeinput,
numeout și o variabilă de tip întreg denumită diminput. În interiorul acestei funcții se
va crea un obiect de tip TFClassifie r iar datele membru ale instanței noi create se vor
cupla corespunzător cu datele primite ca parametru. O diferență va apărea atunci când
se inițializează variabila de tipul TensorFlowInferenceInterface , această variabilă se
instanțiază cu ajutorul constru ctorului cu parametrii din clasa
TensorflowInfer enceInterface cu parametrii te tip AssetManager și String,
reprezentând locul în care se află modelul și calea, numele în acest caz, al acestuia.
Funcția citește clase folosește AssetManager -ul pentru a col ecta din asset -uri
fișierul ce conține etichetele fiecărei clase. Acest fișier este parcurs iar vectorul clasei
responsabil pentru păstrarea numelor claselor de animale este populat.

53
Cea mai importantă funcție din această clasă este cea de tipul Classfica tion
recognize(float [] pixels) , aceasta primește ca parametru un vector de pixeli ce
reprezintă imaginea.
Instanța clasei TensorFlowInferenceInterface are trei acțiuni pe care trebuie să
le execute, să încarce modelul cu noua poză, să ruleze modelul și s ă ofere rezultatele.
Se precizează forma intrării , se rulează precizându -se stratul de ieșire și se realizează
clasificarea.
tfi.feed(inputName,pixels,1,inputSize,inputSize,3);
tfi.run(outputNames);
tfi.fetch(outputName,output);
tfi reprezintă obiectul de tip TensorFlowInfernceInterface . Metoda feed precizează
numele stratului de intrare, imaginea reprezentată ca vector de pixeli, și dimensiunile
acesteia, 1 reprezintă numărul de poze introduse, inputSize este dimensiunea pozei,
acesta este dublat deoarece poza este pătratică de dimensiune 96 iar 3 reprezintă
adâncimea pozei, numărul de culori. Variabila output este un vector de numere reale
cuprinse între 0 și 1 reprezentând clasificarea. Acest vector se parcurge și se alege cea
mai mare valoare, se creeaz ă o instanță a clasei Classifier și se completează conf cu
valoarea maximă din vectorul format anterior și eticheta cu eticheta corespunzătoare
poziției pe care s -a găsit cel mai mare factor de încredere.

Camera_activity (Activity)

Camera_activity este o activitate ce are clasa cu același nume în care se
primește o poză și este clasificată. Clasa face parte dintr -o activitate prin urmare
aceasta are și interfață scrisă în cod XML. Pe interfață se regăsesc trei butoane, unul ce
are ro lul de a porni camera pentru a primi o poză imortalizată pe moment, altul pentru a
deschide galeria și a oferi posibilitatea să se aleagă o poză deja existentă iar ultimul
reprezintă butonul ce realizează clasificare. Pe lângă aceste butoane, în interfață se mai
găsește și un view de tip imageView pentru a afișa imaginea .
La inițializarea interfeței se încarcă modelul , se creează o instanță de tip
TFClassifier și se pregătește pentru primirea și procesarea imaginii.

54
O imagine poate proveni fie de la camer a telefonului fie din galerie, în ambele cazuri
fotografia se citește și se inserează în image View. Când fotografia este încărcată în
image View se poate efectua clasificarea.
Pentru clasificare , imaginea trebuie modificată deoarece intrarea rețelei
neuronale acceptă imagini de dimensiune 96x96x3. Se creează un obiect de tip bitmap
ce va avea exact dimensiunile dorite și va fi încărcat cu imaginea aleasă. Se
inițializează un vector de pixeli de di mensiune 96×96 și se stochează în el toți pixelii
din imagine. Cu ajutorul vectorului format se va crea vectorul imaginii ce va conține
imaginea liniarizată, vectorul acesta va avea dimensiunea 96x96x3 deoarece imaginea
este color RGB. Pentru completarea v ectorului cu datele pozei se parcurge vectorul
imaginii extrase din bitmap iar fiecare pixel este preluat și împărțit în cele trei culori.
final int pix = pixels[i];
dataimage[i * 3 + 2] = Color.red(pix);
dataimage[i * 3 + 1] = Color.green(pix);
dataimage[ i * 3] = Color.blue(pix);
Înainte ca imaginea vectorizată să fie trimisă către rețea pixelii rezultați sunt
normalizați, adică sunt aduși în intervalul [0, 1]; acest lucru se face prin împărțirea
fiecărui pixel la valoarea 255.
Apare o instanță a clasei Clasificator ce va fi inițializată cu rezultatul funcției
recognize () a modelului ce a fost creat la inițializarea interfeței. Rezultatul nu este
afișat în aceiași interfață ci va fi redirecționat către o altă activitate a aplicației. Pentru a
se adăuga anu mite informați dintr -o activitate în alta se utilizează un obiect de tip
Intent ce este inițializat cu un obiect nou ce știe contextul curent și activitatea ce va
trebui lansată. Obiectul de tip intent creat anterior are anumite funții utile pentru
transfe rul de informații, cea mai utilizată este putextra () ce primește ca parametru un
nume și valoarea dorită, numele va fi utilizat în activitatea ce se deschide pentru a
extrage din intent datele asociate fiecărui nume.

55
Rezultat (Activity)

În această activitate se afișează rezultatul clasificării. În interfață se regăsesc
următoarele view -uri: un image View, două textView-uri și un buton de redirecționare
către detalii despre animalul recunoscut.
În momentul în care se primesc rezultatele rețelei neuronale, eticheta animalului
și precizia cu care a fost recunoscut, se testează dacă valoarea preciziei este mai mare
decât 75%, dacă această valoare este mai mică atunci este posibil ca animalul
recunoscut să nu fie cel real.
Dacă rezultatul trece „testul de calitate” atunci se caută în asset -uri și se
deschide imaginea ce va fi încărcată într -un obiect drawable , obiect ce poate umple un
image View. Obiectul ce face posibilă deschiderea și citirea imaginii este un obiect de
tip InputStream .
Anima l.class și Locație .class

Cele două clase sunt utilizate pentru a se lucra într -un mod eficient cu datele din
baza de date. Datele membr u ale acestor clase sunt exact atributele entităților din baza
de date.
Reprezentarea legăturii dintre cele două tabele s -a realizat în clasa „Animal”
prin declararea ca dată membru a unei liste de tipul „Locație”, în această listă fiind
adăugate locații le în care animalul respectiv trăiește.
Activitățile All_Animals și ListAdapter

În activitatea All_Animals se dorește afișarea unei liste cu toate animalele
prezente în baza de date, fiecare element din listă trebuie să conțină o imagine și un
text. Pentru acest lucru se utilizează un ListView ce va încărca informațiile necesare.
Popularea unui ListView se face cu ajutorul unui adaptor . Cum cerința este ca fiecare
item să conțină o poză a unui animal și un text cu nume le acestuia, nu se poate folosi
un adaptor predefinit. Adaptoarele predefinite pot oferii o vizualizare simplă de listă,
fiecare element având un titlu și un subtitlu.
Activitatea ListAdapter are casa cu același nume, clasă ce este o extindere a
clasei ArrayAdapter și are scopul de a personaliza ListView -ul prezent în activitatea

56
All_Animals . În interfața acestei activități sunt prezente exact elementele de interes
pentru afișarea în listă, un imageView și un textView, acestea așezate într -un mod
plăcut. S-a adăugat pentru această formă și un efect de intrare, întreaga interfața
apărând pe ecran cu un efect de translație de la stânga la dreapta, efect definit în
resurse cu ajutorul xml -ului. Cum efectul se aplică pe întreaga formă atunci și
elementele lis tei ce vor avea ca template acest layout vor avea acest efect.
Pentru a se adăuga acest layout pentru elementele listei, se definește în clasa
All_animals un obiect de tip ListAdapter cu parametrii: contextul, layout -ul și lista din
care se vor lua infor mațiile. Adapter -ul format va fi inclus în ListView prin funcția
membru a acestui obiect numită setAdapter(adapter).
Selectarea unui item este realizată de funcția setOnItemClickListener care
recunoaște poziția selectată și extrage din lista de animale animalul de pe poziția
aleasă. Numele acestuia este preluat, pus într -un intent și trimis către forma de detalii.
Activitatea Detalii

În această activitate partea din spate, codul, pria din baza de date toate elementele
ce țin de descrierea unui animal. Extragerea datelor din baza de date pentru un anumit
animal este deja realizată în clasa în care am definit baza de date fapt ce scuteșt e
redundanța codului. Funcția prezentă în DatabaseHelper va fi apelată iar rezultatul
acesteia, un obiect de tip Animal, va fi împărțit pe componente pentru ca acestea să fie
afișate utilizatorului.
Componentele vor fi afișate sub formă de stivă cu excep ția locațiilor care vor fi
afișate într -o componentă specială și relevată anume GoogleMapView .
Activitatea Informații

Activitatea informații prezintă ca parte frontală o imagine a dezvoltatorului
precum , detalii despre acesta dar și detalii despre situațiile în care aplicația nu
furnizează un răspuns corect , detalii despre soluționarea situaților delicate și enunțarea
site-urilor de unde s -au extras informațiile și imaginile utilizate în aplicație . Cu alte
cuvinte pe parte frontală vizibilă de către utilizatori se află o componentă de tip
imageView și o componentă de tip textView .

57
Capitolul 5. Documentație utilizator

În acest capitol se vor prezenta detalii despre modul de folosire al aplicației de
către utilizator i. Sunt descriși și vizualizați pașii ce trebuie urmați în accesarea tuturor
funcțiilor disponibile în aplicație. Tot aici se vor găsi cele mai frecvente probleme
întâlnite și modul prin care acestea pot fi rezolvate.
5.1. Utilizarea software -ului

La intrarea în ecranul principal se găsește un meniu ce vă permite să accesați
trei funcții. Lucru ce se observă în Figură 20.

Figură 20 Ecranul de întâ mpinare și meniul

Prima funcție este aceea în care se afișează o listă cu toate animalele înregistrare
pe care aplicația le poate identifica (stânga jos).
La selectarea unui animal veți fi întâmpinați de o altă fereastră ce vă va furniza
informații despre un animal, informații cum sunt: viteza pe care o poate atinge, dieta
sau culoare. Tot în această formă se poate observa și o mapă în care sunt marcate
zonele în care acel animal trăiește. Mapa va fi disponibilă doar dacă telefonul este
conectat la o sursă de internet. Pentru prima funcție a aplicației este prezentat un ghid
vizual în Figură 21.

58

Figură 21 Prezentarea tuturor animalelor și detalii despre fiecare în parte

A doua funcție (dreapta jos) ce poate fi accesată este afișarea informațiilor
suplimentare despre aplicație precum, modul de utilizare în cazul în care apar
problemele la recunoaștere , informații despre creator și sursele de unde provin detaliile
animalelor precum și imaginile extrase. Ecranul ce va fi accesibil prin această funcție
este prezentat în Figură 22.

Figură 22 Informații despre aplicație și dezvoltator

59

Ultima funcție disponibilă (partea de sus) este și cea mai importantă, aceea de
recunoaștere a animalelor. Pe ecran vor apărea trei butoane, două dintre acestea, su nt
pentru a introduce imaginea . Prima modalitate prin care imaginea poate servi ca intrare
a algoritmului de clasificare este capturarea pe loc a unei poze cu ajutorul camerei . Cea
de-a doua modalitate de introducere a pozei este prin deschiderea galeriei și alegerea ei
de acolo. În ambele cazuri poza selectată va fi vizualizată pe formă (Figură 23).

Figură 23 Calea către ecranul de recunoaștere

În momentul în care imaginea este selectată , este disponibilă funcția de
clasificar e. Această funcție vă redirecți onează către o formă ce vă va furniza denumirea
animalului identificat precum și o posibilitate de a afla mai multe caracteristici ale
acestuia (Figură 24).

60

Figură 24 Clasificarea unui animal și afișarea detaliilor

5.2. Posibile probleme apărute și soluționarea lor

Identificarea unui animal poate fi eronată din cauza mai multor factori precum:
calitatea slabă a imaginii, ambiguitatea locului în care animalul se află, poziția
animalului nu este tocmai una foarte întâlnită sau luminozitatea lasă de dorit .
Această problemă poate genera la faza de identificare două posibilități: una este
aceea în care se identifică alt animal, iar cealal tă posibilitate este de afișare a unui
mesaj în care se comunică imposibilitatea de a recunoaște.
O situație în care apare o problemă este prezentată în Figură 25. Cauza acesteia
este următoarea: fotografia a fost făcută la un ecran de calculator, iar calitatea ei este
slabă, pixeli sunt alterați ceea ce deformează total imaginea iar rețeaua neuronală nu
mai este capabilă să distingă ce animal se află în poză.

61

Figură 25 Eșuare în recunoaștere

Pentru a soluționa această problemă se încearcă cu altă poză a animalului
respectiv, dintr -un alt unghi sau cu zoom, pentru a se focaliza toată atenția pe el.
Pentru a obține un număr mare de reușite se cere a avea o poză clară cu animalul în
prim plan.

62
Capitolul 6. Concluzii

6.1. Atingerea funcționalității

Aplicația ce a fost realizată a atins toate obiectivele ce au fost propuse. Aceasta
are o interfață prietenoasă, simplistă și intuitivă ce ajută utilizatorul să o folosească cu
plăcere, este portabilă și la îndemână și se poate utiliza și în condiții în care nu există
conexiune la internet.
Rata cu care aplicația de recunoaștere clasifică corect imaginile de intrare este
medie de 96%, un procent mare. Situaț iile în care aceasta eșuează în a clasifica corect
un animal sunt acelea în care calitatea pozei este precară, animalul nu domină cadrul
sau luminozitatea este puternic afectată. Aceste cauze ale perturbării predicției sunt
lucruri ce pot înșela și creierul uman.
Aplicația este una educativă ce stârnește curiozitatea persoanelor indiferent de
vârstă, le face să exploreze și să se relaxeze. Ea este proiectată pentru a fi utilizată într –
un spațiu amenajat cum este grădi na zoologică, acest spațiu nu este fix, aplicația putând
fi folosită și într -un cadru deschis, chiar în habitatul animalelor respective.
Informațiile despre animale sunt accesate foarte ușor și sunt foarte captivante și
punctuale.

6.2. Dezvoltări ulterioare

Aplicația în acest moment este complet funcțională și dotată cu strictul necesar
de informații și acțiuni dar se mai poate îmbunătății.
O îmbunătățire ar consta prin introducerea în sistem a mai multor clase de
animale, ca aplicația să poat ă detecta cât mai multe vietăți și să fie utilizată în cât mai
multe medii. Prin includerea mai multor animale în spectrul cunoașterii, aplicația poate
evolua de la un simplu ghid zoologic într -un adevărat atlas ce poate fi accesat prin
recunoaștere de ima gini.

63
Altă îmbunătățire pe care aplicația o poate atinge este aceea a îmbunătățirii ratei
de predicție. Pentru acest lucru, la baza de date existentă se pot adăuga noi poze cu
animale din mai multe unghiuri, în mai multe medii și în mai multe ipostaze.
Adăugarea noilor poze va avea ca efect generalizarea mai profundă a rețelei, aceasta
având capacitatea de a efectua predicții pe imagini în care animalul nu este chiar în
prim plan sau acesta se află într -o poziție mai dificilă. Tot prin adăugarea mai multo r
poze cu diferite contraste aplicația va învăța să recunoască animalele în diferite condiții
de lumină sau în diferite condiții meteorologice, vremea fiind un factor ce ar putea
influența imaginile și automat ar influența recunoașterea.
Aplicația poate primi ca adaos și capacitatea de creare a unui album personalizat
cu locațiile și cu pozele animalelor identificate în acele zone. Utilizatorul păstrând în
amintire locurile și animalele pe care l -a văzut.

6.3. Opinie personală despre aplicație

Din punctul meu de vedere dezvoltarea aplicației a avut un rol în dezvoltarea
mea deoarece am folosit o parte semnificativă din cunoștințele obținute în facultate iar
produsul obținut este de calitate și ușor utilizabil în lumea reală. Produsul realizat este
cuprinză tor și înglobează ultimele tehnologii importante ce sunt utilizate în majoritatea
aplicațiilor realizate până în acest moment și anume lucrul cu baze de date, utilizarea
API-urior cum este Google Maps, utilizarea platformei Android, utilizarea inteligenței
artificiale sau interacționarea cu site -urile web prin modulele Python.
Dezvoltarea aplicației a pus cel mai mare accent pe crearea unei arhitecturi
potrivite pentru rețeaua neuronală, lucru ce a fost destul de complicat, rezultatul fiind
obținut prin teste și rulări repetate cu diferite alterări. Partea de antrenare a fost unul
dintre cel mai obositor segment deoarece timpul de antrenare a fost extrem de lung iar
în anumite cazuri rezultatul era slab, munca depusă până în acel moment fiind utilizată
pentru îmbunătățirea modelului .
Alt segment ce a fost provocator a fost realizarea setului de date, adunarea
pozelor și filtrarea acestora a fost obositoare și a durat o perioadă destul de mare.

64
Concluzionând, din punctul meu de vedere aplicația a ieșit ex act cum a fost
planificată, predicțiile sunt satisfăcătoare, clasificarea funcționând foarte bine pe
imaginile pe care le -am testat și sunt mândru de rezultatul final.

65
Bibliografie

1. Andreas, K., & Michael, H. Siri, Siri, in my hand: Who’s t he fairest in the land?
On the interpretations, illustrations, and implications of artificial intelligence.
Preluat de pe Science Direct:
https://www.sciencedirect.com/science/article/pii/S0007681318301393. (2008,
Noiembrie 6).
2. Bond, M. a-z animals . Preluat de pe a -z animals: https://a -z-
animals.com/.(2008, Noiembrie).
3. GSMA. The mobile economy . Preluat de pe GSMA:
https://www.gsma.com/r/mobileeconomy/.(2019, Iunie 11).
4. Heaton, J. Applications of Deep Neural Networks Course . Preluat de pe
Washington Un iversity of St. Llouis: https://sites.wustl.edu/jeffheaton/t81 –
558/.(2018, Octombrie 1).
5. Ioniță, L. RNA – îndrumar IA. Ploiești: UPG Ploiești. (2009).
6. Keras. Keras Documentation. Preluat de pe Keras: https://keras.io/.(2019, Iunie
11).
7. Lafore, R. Object -Orientated Programming in C++ Fourth Edition. Sams
Publishing . (2002).
8. Oracle. Java Documentation . Preluat de pe Oracle Help Center:
https://docs.oracle.com/en/java/.(2019).
9. Pytho n. Python 3.7 documentation . Preluat de pe Python:
https://docs.python.org/3/.(2019).
10. Scikit learn. Scikit learn . Preluat de pe Confusion Matrix: https://scikit –
learn.org/stable/auto_examples/model_selection/plot_confusion_matrix.html#sp
hx-glr-auto-example s-model -selection -plot-confusion -matrix -py. (2019).

66
11. Shung, K. P. Accuracy, Precision, Recall or F1? Preluat de pe Towards Data
Science: https://towardsdatascience.com/accuracy -precision -recall -or-f1-
331fb37c5cb9. (2018, Martie 15).
12. Simona, N. Inteligență a rtificială – notițe de curs. Preluat de pe Timf:
https://timf.upg -ploiesti.ro/cursuri/cursuri/IA/.(2018, Noiembrie 27).
13. Smyth, N. Android Studio 3.0 Development Essential. Payload Media. (2017).
14. SQLite. SQLite documentation . Preluat de pe SQLite:
https://w ww.sqlite.org/lang_datefunc.html. (2019).
15. Stanford. Convolutional Neural Networks for Visual Recognition . Preluat de pe
Standford: http://cs231n.stanford.edu/.(2018).
16. Stuart Russell, P. N. Artificial Intelligence: A Modern Approach. New Jersey:
Pearson Edu cation Inc. (2014).
17. Sumit, S. A Comprehensive Guide to Convolutional Neural Networks  — the
ELI5 way. Preluat de pe Towards Data Science:
https://towardsdatascience.com/a -comprehensive -guide -to-convolutional –
neural -networks -the-eli5-way-3bd2b1164a53. (2018, Decembrie 15).
18. Vlădoiu, M. Baze de date – notițe de curs. Ploiești: Universitatea Petrol -Gaze.
(2019).
19. Wikipedia. Activation function . Preluat de pe Wikipedia:
https://en.wikipedia.org/wiki/Activation_function. (2019, Mai 18).
20. Wikipedia. Artificiall Intelligence . Preluat de pe Wikipedia:
https://en.wikipedia.org/wiki/Artificial_intelligence. (2019, Mai 21).
21. Wikipedia. Batch normalization . Preluat de pe Wikipedia:
https://en.wikipedia.org/wiki/Batch_normalization. (2019, Iunie 2).
22. Wikipedia. Logistic function . Preluat de pe Wikipedia:
https://en.wikipedia.org/wiki/Logistic_function. (2019, Mai 21).

67
Anex ă cod sursă

Extras 1 – Modelul rețelei
from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation
from keras.layers.core import Flatten
from keras.layers.core import Dropout
from keras.layers.core import Dense
from keras import backend as K

class Model:
def __init__(self,width, height, depth, classes):
self.width = width
self.height = height
self.depth = depth
self.classes = classes
def CreareModel(self):
model = Sequential()
inputShape = (self.height, self.width, self.depth)
chanDim = -1
if K.image_data_format() == "channels_first":
inputShape = (self.depth,self.height,
self.width)
chanDim = 1

model.add(Conv2D(32, (3, 3), padding="same",
input_shape=inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))

68

model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add( Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(128,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(Conv2D(128,(3,3),padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=chanDim))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(1024))
model.add(Activation("relu"))
model.add(BatchNorm alization())
model.add(Dropout(0.5))
model.add(Dense(self.classes,activation="softmax"))

return model
Extras 2 – Antrenarea rețelei
import matplotlib
from retea import Model
from sklearn.preprocessing import LabelBinarizer
from keras.callbacks import ModelCheckpoint
from sklearn.model_selection import train_test_split

69
from sklearn.metrics import classification_report
from keras.preprocessing.image import ImageDataGenerator
from imu tils import paths
import matplotlib.pyplot as plt
import numpy as np
import random
import pickle
import cv2
import os

dataset ='dataset'
iesire=
['outputNvidia/model.model','outputNvidia/labels.pickle','outputNv
idia/grafic.png']print("[INFO] incarcare ima gini…")

data = []
labels = []
imagePaths = sorted(list(paths.list_images(dataset)))
random.seed(21)
random.shuffle(imagePaths)
img_size = (96,96)

for imagePath in imagePaths:
try:
image = cv2.imread(imagePath)
image = cv2.resize(image, img_size)
data.append(image)

label = imagePath.split(os.path.sep)[ -2]
labels.append(label)
except:
print("x")

data = np.array(data, dtype="float") / 255.0
labels = np.array(labels)

70

(trainX, testX, trainY, testY) = train_test_split(data,
labels, test_size=0.25, random_state=42)

lb = LabelBinarizer()
trainY = lb.fit_transform(trainY)
testY = lb.tr ansform(testY)

aug = ImageDataGenerator(rotation_range=30, width_shift_range=0.1,
height_shift_range=0.1, shear_range=0.2, zoom_range=0.2,
horizontal_flip=True, fill_mode="nearest")

model = Model(width=img_size[0], height=img_size[1], depth=3,
classes=len(lb.classes_))
model = model.CreareModel()

INIT_LR = 1e -3
EPOCHS = 3
BS = 32

print("[INFO] antrenare retea…")
model.compile(loss="categorical_crossentropy", optimizer='Adam',
metrics=["accuracy"])

checkpointPath = "weights -best.hdf5"
checkpoint
=ModelCheckpoint(checkpointPath,monitor='val_acc',verbose=1,save_b
est_only=True,mode='Max')
callback_list = [checkpoint]

H = model.fit_generator(aug.flow(trainX, trainY, batch_size=BS),
validation_data=(testX, testY), steps_per_epoch=len(train X)
// BS,
epochs=EPOCHS, callbacks = callback_list)

71

print("[INFO] evaluare retea…")
predictions = model.predict(testX, batch_size=32)
print(classification_report(testY.argmax(axis=1),
predictions.argmax(axis=1), target_names=lb.classes_))

matplotlib .use('agg')
N = np.arange(0, EPOCHS)
plt.style.use("ggplot")
plt.figure()
plt.plot(N, H.history["loss"], label="train_loss")
plt.plot(N, H.history["val_loss"], label="val_loss")
plt.plot(N, H.history["acc"], label="train_acc")
plt.plot(N, H.history["val_acc"], label="val_acc")
plt.title("Antrenare")
plt.xlabel("Epoci")
plt.ylabel("Loss/Accuracy")
plt.legend()
plt.savefig(iesire[2])

print("[INFO] serializarea retelei si etichetelor…")
model.save(iesire[0])
model.save("modeltrained.h5")
f = open(iesire[1], "wb")
f.write(pickle.dumps(lb))
f.close()

matplotlib.use('TkAgg')
from keras.models import load_model
from sklearn.metrics import confusion_matrix
import pandas as pd

72
categorical_test_labels = pd.DataFrame(testY).idxmax(axis=1)
categorical_preds = pd.DataFrame(predictions).idxmax(axis=1)

confusion_matrix= confusion_matrix(categorical_test_labels,
categorical_preds)
def plot_confusion_matrix(cm,
classes,normalize=False,title='Confusion
matrix',cmap=plt.cm.Blues):
import itertool s
if normalize:
cm = cm.astype('float') / cm.sum(axis=1)[:,
np.newaxis]
print('Normalized confusion matrix')
else:
print('Confusion matrix, without normalization')
fig, ax = plt.subplots()
im = ax.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
ax.figure.colorbar(im,ax=ax)
tick_marks = np.arange(len(classes))
ax.set(xticks=np.arange(cm.shape[1]),
yticks=np.arange(cm.shape[0]),
xticklabels=classes,
yticklabels=classes,
title=title,
ylabel="Label Real",
xlabel="Label Prezis")

plt.setp(ax.get_xticklabels(),rotat ion=45,ha="right",rotation_mode
="anchor")
fmt = '.2f' if normalize else 'd'
thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]),
range(cm.shape[1])):
ax.text(j, i, format(cm[i, j], fmt),
horizonta lalignment='center', color='white' if cm[i, j] > thresh
else 'black')
fig.tight_layout()

73
return ax

plot_confusion_matrix(confusion_matrix,lb.classes_,normalize=True)
plt.show()
Extras 3 – Descărcare imagini ImageNet
import urllib.request
import os
folder_name= ['coiot','elefant','gorila','papagal']
images_link = ["http://www.image –
net.org/api/text/imagenet.synset.geturls?wnid=n02114855",
"http://www.image –
net.org/api/text/imagenet.synset.geturls?wnid=n02504458 ",
"http://www.image –
net.org/api/text/imagenet.synset.geturls?wnid=n02481103",
"http://image –
net.org/api/text/imagenet.synset.geturls?wnid=n01816887"
]

for i in range(0,len(folder_name)):
if not os.path.exi sts('dataset/'+folder_name[i]):
os.makedirs('dataset/'+folder_name[i])

images_urls=urllib.request.urlopen(images_link[i]).read().decode()
pic_num = 1
for j in images_urls.split(' \n'):
try:
print(".",end='')

urllib.request.urlretrieve(j,'dataset/'+folder_name[i]+"/"+str(pic
_num)+'.jpg')
pic_num+=1
except:
pass
if n==1300:
break
print("Seria ",folder_name[i]," terminata")

74
Extras 4 – Clasa de clasificare a imaginilor
package com.example.adrian.licenta;

import android.content.res.AssetManager;
import android.widget.ListView;

import
org.tensorflow.contrib.android.TensorFlowInferenceInterface;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class TFClassifier implements Classifier {
private static final float eroare = 0.1f;
private TensorFlowInferenceInterface tfi;

private String name;
private String inputName;
private String outputName;
private int inputSize;

private List<String> labels;
private float[] output;
private String[] outputNames;

private static List<String> citesteClase(AssetMa nager
am,String file) throws IOException {
BufferedReader br = new BufferedReader(new
InputStreamReader(am.open(file)));
String linie;
List<String> clase = new ArrayList<>();
while ((linie=br.readLine())!=null){

75
clase.add(linie);
}
br.close();
return clase;
}
public static TFClassifier create(AssetManager am,String
nume,String caleModel, String fisierClase,int diminput,String
numeinput,String numeout) throws IOException {
TFClassifier c = new TFClassifier();
c.name = nume;
c.inputName=numeinput;
c.outputName= numeout;
c.labels = citesteClase(am,fisierClase);
c.tfi = new TensorFlowInferenceInterface(am,caleModel);
c.inputSize = diminput;
c.outputNames = new String[] {numeout};
c.output = new float[c.labels.size()];
return c;
}
@Override
public String name() {
return name;
}
@Override
public Classification recogniz e(float[] pixels) {
tfi.feed(inputName,pixels,1,inputSize,inputSize,3);
tfi.run(outputNames);
tfi.fetch(outputName,output);
Classification clas = new Classification();
for(int i =0;i<output.length;++i){
System.out.println(output[i]);
System.out.println(labels.get(i));
if(output[i]>eroare && output[i] > clas.getConf()){
clas.update(output[i],labels.get(i));
}

76
}
return clas;
}
}
Extras 5 – Clasa ce preia imaginea și furnizează răspunsul (Camera_activity)
package com.example.adrian.licenta;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import org.tensorflow.Tensor;

import java.io.IOException;
import java.io.InputStream;

public class Camera_activity extends AppCompatActivity {
TFClassifier clasificator;
static final int REQUEST_IMAGE_CAPTURE = 1;
static final int IMG_SIZE = 96;
static final int REQUEST_GALERY =2;

Bitmap imageBitmap;

77
ImageView imageView ;
Button pozaBtn;
Button clasificaBtn,galerieBtn;
TextView outputTxt;

boolean selectat = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_activity);

imageView= findViewById(R.id.imageView1);
pozaBtn = findViewById(R.id.CameraButton);
clasificaBtn = findViewById(R.id.ClasificaButton);
outputTxt = findViewById(R.id.textView);
galerieBtn = findViewById(R.id.GalerieBtn);

IncarcaModelul();
galerieBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Int ent.ACTION_GET_CONTENT);

startActivityForResult(Intent.createChooser(intent,"Select
Picture"),REQUEST_GALERY);
}
});
pozaBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});

78
clasificaBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
if(selectat ) {
Bitmap resized =
Bitmap.createScaledBitmap(imageBitmap, IMG_SIZE, IMG_SIZE, true);
int[] pixels = new int[IMG_SIZE * IMG_SIZE];
float[] dataimage = new float[IMG_SIZE *
IMG_SIZE * 3];
resized.getPixels(pixels, 0, IMG_SIZE, 0, 0,
IMG_SIZE, IMG_SIZE);
for (int i = 0; i < pixels.length; i++) {
final int pix = pixels[i];

dataimage[i * 3 + 2] = Color.red(pix);
dataimage[i * 3 + 1] = Color.green(pix);
dataimage[i * 3] = Color.blue(pix);

dataimage[i * 3 + 2] /= 255.0;
dataimage[i * 3 + 1] /= 255.0;
dataimage[i * 3] /= 255.0;
}

Classification cf =
clasificator.recognize(dataimage);
Intent intent = new
Intent(getApplicationContext(), Rezultat.class);
intent.putExtra("Confidenta", cf.getConf());
intent.putExtra("Eticheta", cf.getLabel());
startActivity(intent);
}else
Toast.makeText(getApplicationContext(),"Nu s -a
selectat o imagin e!",Toast.LENGTH_SHORT).show();
}
});

79
}

private void dispatchTakePictureIntent() {
Intent takePictureIntent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager ())
!= null) {
startActivityForResult(takePictureIntent,
REQUEST_IMAGE_CAPTURE);
}
}
protected void onActivityResult(int requestCode, int
resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode ==
RESULT_OK) {
Bundle extras = data.getExtras();
imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
selectat =true;
}
if (requestCode == REQUEST_GALERY && resultCode ==
RESULT_OK) {
try{
Uri selectedImage = data.getData();
InputStream inputStream =
getContentResolver().openInputStream(selectedImage);
imageBitmap =
BitmapFactory.decodeStream(inputStream);
imageView.setImageBitmap(imageBitmap);
selectat=true;
}catch (Exception e){
e.printStackTrace();
}
}
}
private void IncarcaModelul(){
try {

80
clasificator =
TFClassifier.create(getAssets(),"model_keras",
"model.pb","labels.txt",IMG_SIZE,"conv2d_1_input","dense_2/Softmax
");
} catch (IOException e) {
e.printStackTrace();
}
}
}

Similar Posts