Recunoașterea feței cu Eigenfaces

Recunoașterea feței este omniprezentă în science fiction: protagonistul se uită la o cameră, iar camera îi scanează fața pentru a recunoaște persoana. În mod mai formal, putem formula recunoașterea fețelor ca o sarcină de clasificare, în care intrările sunt imagini, iar ieșirile sunt numele persoanelor. Vom discuta o tehnică populară de recunoaștere a fețelor numită eigenfaces. Iar în centrul eigenfaces se află o tehnică nesupravegheată de reducere a dimensionalității numită analiză a componentelor principale (PCA), iar noi vom vedea cum putem aplica această tehnică generală la sarcina noastră specifică de recunoaștere a fețelor. Descărcați codul complet aici.

Nu ratați! Oferta se termină în
  • Accesați toate cele peste 200 de cursuri
  • Cursuri noi adăugate lunar
  • Anulați oricând
  • Certificate de absolvire

Recunoașterea fețelor

Înainte de a discuta despre analiza componentelor principale, ar trebui mai întâi să definim problema noastră. Recunoașterea fețelor este provocarea de a clasifica a cui este fața într-o imagine de intrare. Acest lucru este diferit de detectarea feței, unde provocarea este de a determina dacă există o față în imaginea de intrare. În cazul recunoașterii fețelor, avem nevoie de o bază de date existentă de fețe. Având în vedere o nouă imagine a unei fețe, trebuie să raportăm numele persoanei.

O modalitate naivă de a realiza acest lucru este de a lua noua imagine, de a o aplatiza într-un vector și de a calcula distanța euclidiană dintre ea și toate celelalte imagini aplatizate din baza noastră de date.

Există mai multe dezavantaje ale acestei abordări. În primul rând, dacă avem o bază de date mare de fețe, atunci efectuarea acestei comparații pentru fiecare față va dura ceva timp! Imaginați-vă că construim un sistem de recunoaștere a fețelor pentru utilizare în timp real! Cu cât setul nostru de date este mai mare, cu atât algoritmul nostru este mai lent. Dar mai multe fețe vor produce, de asemenea, rezultate mai bune! Ne dorim un sistem care să fie atât rapid, cât și precis. Pentru aceasta, vom folosi o rețea neuronală! Putem să ne antrenăm rețeaua pe setul nostru de date și să o folosim pentru sarcina noastră de recunoaștere a fețelor.

Există o problemă cu utilizarea directă a unei rețele neuronale: imaginile pot fi mari! Dacă am avea o singură imagine m\ ori n

, ar trebui să o aplatizăm într-un singur vectorm\dot n\ ori 1pentru a o introduce în rețeaua noastră neuronală ca intrare. Pentru imagini de dimensiuni mari, acest lucru ar putea afecta viteza! Acest lucru este legat de cea de-a doua problemă legată de utilizarea imaginilor ca atare în abordarea noastră naivă: acestea sunt foarte dimensionale! (O imagine

m\ ori neste de fapt unm\dot n\ ori 1vector) O nouă intrare ar putea avea o tonă de zgomot, iar compararea fiecărui pixel folosind scăderea matricei și distanța euclidiană ne-ar putea da o eroare mare și clasificări greșite!

Aceste probleme sunt motivul pentru care nu folosim metoda naivă. În schimb, am dori să luăm imaginile noastre cu dimensiuni mari și să le reducem la o dimensionalitate mai mică, păstrând în același timp esența sau părțile importante ale imaginii.

Reducerea dimensionalității

Secțiunea anterioară motivează motivul pentru care folosim o tehnică de reducere a dimensionalității. Reducerea dimensionalității este un tip de învățare nesupravegheată în care dorim să luăm date cu dimensiuni mai mari, cum ar fi imaginile, și să le reprezentăm într-un spațiu cu dimensiuni mai mici. Să folosim următoarea imagine ca exemplu.

Aceste diagrame prezintă aceleași date, cu excepția graficului de jos care le centrează la zero. Observați că datele noastre nu au nicio etichetă asociată cu ele, deoarece aceasta este o învățare nesupravegheată! În cazul nostru simplu, reducerea dimensionalității va reduce aceste date de la un plan 2D la o linie 1D. Dacă am avea date 3D, am putea să le reducem la un plan 2D sau chiar la o linie 1D.

Toate tehnicile de reducere a dimensionalității au ca scop găsirea unui hiperplan, o linie cu dimensiuni mai mari, pe care să proiecteze punctele. Ne putem imagina o proiecție ca și cum am lua o lanternă perpendiculară pe hiperplanul pe care ne proiectăm și am trasa unde cad umbrele pe acel hiperplan. De exemplu, în datele noastre de mai sus, dacă am dori să proiectăm punctele noastre pe axa x, atunci ne imaginăm că fiecare punct este o minge, iar lanterna noastră ar fi îndreptată direct în jos sau în sus (perpendicular pe axa x), iar umbrele punctelor ar cădea pe axa x. Aceasta este o proiecție. Nu ne vom face griji cu privire la matematica exactă din spatele acestui lucru, deoarece scikit-learn poate aplica această proiecție pentru noi.

În cazul nostru simplu 2D, dorim să găsim o linie pe care să proiectăm punctele noastre. După ce proiectăm punctele, atunci avem date în 1D în loc de 2D! În mod similar, dacă am avea date 3D, dorim să găsim un plan pe care să proiectăm punctele în jos pentru a reduce dimensionalitatea datelor noastre de la 3D la 2D. Diferitele tipuri de reducere a dimensionalității constau în a afla pe care dintre aceste hiperplane să le selectăm: există un număr infinit de ele!

Analiza componentelor principale

O tehnică de reducere a dimensionalității se numește analiza componentelor principale (PCA). Ideea din spatele PCA este că dorim să selectăm hiperplanul astfel încât, atunci când toate punctele sunt proiectate pe el, acestea să fie răspândite la maximum. Cu alte cuvinte, dorim ca axa să aibă o varianță maximă! Să luăm în considerare exemplul nostru grafic de mai sus. O axă potențială este axa x sau axa y, dar, în ambele cazuri, aceasta nu este cea mai bună axă. Cu toate acestea, dacă alegem o linie care taie datele noastre pe diagonală, aceasta este axa pe care datele ar fi cel mai mult dispersate!

Axa albastră mai lungă este axa corectă! Dacă ar fi să proiectăm punctele noastre pe această axă, ele ar fi cât mai răspândite! Dar cum ne dăm seama de această axă? Putem împrumuta un termen din algebra liniară numit vectori proprii! De aici provine numele de eigenfaces! În esență, calculăm matricea de covarianță a datelor noastre și luăm în considerare cei mai mari vectori proprii ai acestei matrice de covarianță. Aceștia sunt axele noastre principale și axele pe care proiectăm datele noastre pentru a reduce dimensiunile. Folosind această abordare, putem lua date cu dimensiuni mari și le putem reduce la o dimensiune mai mică prin selectarea celor mai mari vectori proprii ai matricei de covarianță și proiectarea pe acești vectori proprii.

Din moment ce calculăm axele de răspândire maximă, păstrăm cele mai importante aspecte ale datelor noastre. Este mai ușor pentru clasificatorul nostru să separe fețele atunci când datele noastre sunt împrăștiate, spre deosebire de cele grupate.

(Există și alte tehnici de dimensionalitate, cum ar fi Analiza Discriminantă Lineară, care utilizează învățarea supravegheată și sunt, de asemenea, utilizate în recunoașterea fețelor, dar PCA funcționează foarte bine!)

Cum se leagă acest lucru de provocarea noastră de recunoaștere a fețelor? Putem conceptualiza imaginile noastre m\ ori n

ca puncte în spațiulm\dot ndimensional. Apoi, putem folosi PCA pentru a reduce spațiul nostru dinm\dot nîn ceva mult mai mic. Acest lucru va ajuta la accelerarea calculelor noastre și va fi robust la zgomot și variație.

Aspect privind detectarea fețelor

Până acum, am presupus că imaginea de intrare este doar cea a unei fețe, dar, în practică, nu ar trebui să cerem ca imaginile camerei să aibă o față perfect centrată. Acesta este motivul pentru care rulăm un algoritm de detectare a fețelor gata de utilizare, cum ar fi un clasificator în cascadă antrenat pe fețe, pentru a ne da seama ce porțiune din imaginea de intrare are o față în ea. Atunci când avem această cutie delimitatoare, putem tăia cu ușurință acea porțiune din imaginea de intrare și putem utiliza fețele proprii pe acea porțiune. (De obicei, netezim acea diapozitivă și efectuăm o transformare afină pentru a de-dezbina fața dacă aceasta apare sub un unghi). Pentru scopurile noastre, vom presupune că avem deja imagini de fețe.

Cod Eigenfaces

Acum că am discutat despre PCA și eigenfaces, să codăm un algoritm de recunoaștere a fețelor folosind scikit-learn! În primul rând, vom avea nevoie de un set de date. Pentru scopurile noastre, vom folosi un set de date out-of-the-box de la Universitatea din Massachusetts numit Labeled Faces in the Wild (LFW).

Simțiți-vă liberi să înlocuiți propriul set de date! Dacă doriți să vă creați propriul set de date privind fețele, veți avea nevoie de mai multe fotografii ale feței fiecărei persoane (în diferite unghiuri și cu iluminare diferită), împreună cu etichetele ground-truth. Cu cât veți folosi o varietate mai mare de fețe, cu atât mai bine se va descurca dispozitivul de recunoaștere. Cel mai simplu mod de a crea un set de date pentru recunoașterea fețelor este să creați un dosar pentru fiecare persoană și să puneți imaginile fețelor în el. Asigurați-vă că fiecare are aceeași dimensiune și redimensionați-le astfel încât să nu fie imagini mari! Nu uitați că PCA va reduce oricum dimensionalitatea imaginii atunci când o proiectăm în acel spațiu, așa că folosirea unor imagini mari, de înaltă definiție, nu va ajuta și va încetini algoritmul nostru. O dimensiune bună este de ~512×512 pentru fiecare imagine. Imaginile ar trebui să aibă toate aceeași dimensiune, astfel încât să le puteți stoca într-un array numpy cu dimensiunile (num_exemple, înălțime, lățime) . (Presupunem că imaginile sunt în tonuri de gri). Apoi folosiți numele dosarelor pentru a dezambiguiza clasele. Folosind această abordare, puteți folosi propriile imagini.

Cu toate acestea, noi vom folosi setul de date LFW. Din fericire, scikit-learn poate încărca automat setul nostru de date pentru noi în formatul corect. Putem apela o funcție pentru a ne încărca datele. Dacă datele nu sunt disponibile pe disc, scikit-learn le va descărca automat pentru noi de pe site-ul web al Universității din Massachusetts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
18
19

import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_people
from sklearn.metrics import classification_report
from sklearn.decomposition import PCA
from sklearn.neural_network import MLPClassifier
# Load data
lfw_dataset = fetch_lfw_people(min_faces_per_person=100)
_, h, w = lfw_dataset.images.shape
X = lfw_dataset.data
y = lfw_dataset.target
target_names = lfw_dataset.target_names
# split in a training and testing set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

Argumentul funcției noastre doar elimină toate persoanele care nu au cel puțin 100 de fețe, reducând astfel numărul de clase. Apoi putem extrage setul nostru de date și alte informații auxiliare. În cele din urmă, împărțim setul nostru de date în seturi de antrenament și de testare.

Acum putem folosi pur și simplu clasa PCA a lui scikit-learn pentru a efectua reducerea dimensionalității pentru noi! Trebuie să selectăm numărul de componente, adică dimensionalitatea de ieșire (numărul de vectori proprii pe care să ne proiectăm), la care dorim să reducem, și nu ezitați să modificați acest parametru pentru a încerca să obțineți cel mai bun rezultat! Noi vom folosi 100 de componente. În plus, vom albi datele noastre, ceea ce este ușor de făcut cu un simplu indicator boolean! (Albirea face doar ca datele noastre rezultate să aibă o variație unitară, ceea ce s-a demonstrat că produce rezultate mai bune)

1
2
3
4
5
5
6
7

# Compute a PCA
n_componente = 100
pca = PCA(n_componente=n_componente, whiten=True).fit(X_train)
# aplicați transformarea PCA
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)

Potem aplica transformarea pentru a reduce imaginile noastre la un spațiu cu 100 de dimensiuni. Observați că nu efectuăm PCA pe întregul set de date, ci doar pe datele de instruire. Acest lucru este astfel încât să putem generaliza mai bine la date nevăzute.

Acum că avem un vector cu dimensiuni reduse, putem antrena rețeaua noastră neuronală!

1
2
3

# antrenăm o rețea neuronală
print(„Fitting the classifier to the training set”)
clf = MLPClassifier(hidden_layer_sizes=(1024,), batch_size=256, verbose=True, early_stopping=True).fit(X_train_pca, y_train)

Pentru a vedea cum se antrenează rețeaua noastră, putem seta indicatorul verbose. În plus, folosim oprirea timpurie.

Să discutăm despre oprirea timpurie ca o scurtă paranteză. În esență, optimizatorul nostru va monitoriza precizia medie pentru setul de validare pentru fiecare epocă. Dacă observă că acuratețea noastră de validare nu a crescut semnificativ pentru un anumit număr de epoci, atunci oprim antrenamentul. Aceasta este o tehnică de regularizare care împiedică modelul nostru să se supraadapteze!

Considerați graficul de mai sus. Observăm supraadaptarea atunci când precizia setului nostru de validare începe să scadă. În acel moment, oprim imediat antrenamentul pentru a preveni supraadaptarea.

În cele din urmă, putem face o predicție și folosi o funcție pentru a tipări un întreg raport de calitate pentru fiecare clasă.

1
2

y_pred = clf.predict(X_test_pca)
print(classification_report(y_test, y_pred, target_names=target_names)))

Iată un exemplu de raport de clasificare.

1
2
3
4
5
6
7
8
9

precizie rechemare f1-scor suport
Colin Powell 0.86 0,89 0,87 66
Donald Rumsfeld 0,85 0,61 0,71 38
George W Bush 0,88 0,94 0,91 177
Gerhard Schroeder 0,67 0,69 0,69 0,91 177
Gerhard Schroeder 0,67 0,69 0.68 26
Tony Blair 0.86 0.71 0.78 35
avg / total 0.85 0.85 0.85 0.85 342

Rețineți că nu există o măsură de precizie. Precizia nu este cel mai specific tip de metrică pentru început. În schimb, vedem precision, recall, f1-score și support. Suportul este pur și simplu numărul de ori în care această etichetă de bază a apărut în setul nostru de testare, de exemplu, în setul nostru de testare, au existat de fapt 35 de imagini cu Tony Blair. Scorul F1 este, de fapt, calculat doar din scorurile de precizie și rechemare. Precizia și reamintirea sunt măsuri mai specifice decât un singur scor de precizie. O valoare mai mare pentru ambele este mai bună.

După antrenarea clasificatorului nostru, îi putem da câteva imagini pentru a le clasifica.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Vizualizare
def plot_gallery(images, titles, h, w, rows=3, cols=4):
plt.figure()
for i in range(rows * cols):
plt.subplot(rows, cols, i + 1)
plt.imshow(images.reshape((h, w))), cmap=plt.cm.gray)
plt.title(titles)
plt.xticks(())
plt.yticks(())
def titles(y_pred, y_test, target_names):
for i in range(y_pred.shape):
pred_name = target_names].split(‘ ‘)
true_name = target_names].split(‘ ‘)
yield ‘predicted: {0}\ntrue: {1}’.format(pred_name, true_name)
prediction_titles = list(titles(titles(y_pred, y_test, target_names))
plot_gallery(X_test, prediction_titles, h, w)

(funcțiile plot_gallery și titles modificate din documentația scikit-learn)

Potem vedea predicțiile rețelei noastre și valoarea adevărului de bază pentru fiecare imagine.

Un alt lucru interesant de vizualizat sunt însăși suprafețele proprii. Amintiți-vă că PCA produce vectori proprii. Putem remodela acești vectori proprii în imagini și vizualiza fețele proprii.

Acestea reprezintă fețele „generice” din setul nostru de date. În mod intuitiv, aceștia sunt vectori care reprezintă direcții în „spațiul fețelor” și sunt ceea ce rețeaua noastră neuronală folosește pentru a ajuta la clasificare. Acum că am discutat despre abordarea fețelor proprii, puteți construi aplicații care să utilizeze acest algoritm de recunoaștere a fețelor!

Am discutat despre o abordare populară a recunoașterii fețelor numită fețe proprii. Esența eigenfaces este un algoritm de reducere a dimensionalității nesupravegheat numit Analiza componentelor principale (PCA) pe care îl folosim pentru a reduce dimensionalitatea imaginilor în ceva mai mic. Acum că avem o reprezentare mai mică a fețelor noastre, aplicăm un clasificator care ia datele de intrare cu dimensiune redusă și produce o etichetă de clasă. Pentru clasificatorul nostru, am folosit o rețea neuronală cu un singur strat.

Recunoașterea fețelor este un exemplu fascinant de îmbinare a vederii computerizate și a învățării automate și mulți cercetători lucrează și astăzi la această problemă dificilă!

În prezent, rețelele neuronale convoluționale profunde sunt folosite pentru recunoașterea fețelor și au implicații vaste în ceea ce privește dezvoltarea lumii carierei. Încercați una dintre ele pe acest set de date!

Lasă un răspuns

Adresa ta de email nu va fi publicată.