Az arcfelismerés sajátarcokkal

Az arcfelismerés mindenütt jelen van a sci-fiben: a főszereplő belenéz egy kamerába, és a kamera letapogatja az arcát, hogy felismerje a személyt. Formálisabban megfogalmazhatjuk az arcfelismerést osztályozási feladatként, ahol a bemenetek képek, a kimenetek pedig az emberek nevei. Az arcfelismerés egyik népszerű technikáját, a sajátarcokat fogjuk tárgyalni. A sajátarcok középpontjában pedig egy felügyelet nélküli dimenziócsökkentő technika, az úgynevezett főkomponens-analízis (PCA) áll, és megnézzük, hogyan alkalmazhatjuk ezt az általános technikát a mi konkrét arcfelismerési feladatunkra. Töltse le a teljes kódot innen.

Ne hagyja ki! Az ajánlat
  • Hozzáférés a több mint 200 tanfolyamhoz
  • Havonta új tanfolyamokkal bővül
  • Bármikor lemondható
  • Tanúsítványok a teljesítésről

Arcfelismerés

Mielőtt a főkomponens-elemzést tárgyalnánk, először is meg kell határoznunk a problémánkat. Az arcfelismerés az a feladat, hogy osztályozzuk, kinek az arca van egy bemeneti képen. Ez különbözik az arcfelismeréstől, ahol a kihívás annak meghatározása, hogy van-e arc a bemeneti képen. Az arcfelismerésnél szükségünk van egy meglévő arcadatbázisra. Adott egy új arckép, és meg kell adnunk a személy nevét.

A naiv módszer ennek megoldására az, hogy fogjuk az új képet, vektorrá lapítjuk, és kiszámítjuk az euklideszi távolságot a kép és az adatbázisunkban lévő összes többi lapított kép között.

Ennek a megközelítésnek több hátulütője is van. Először is, ha nagy adatbázisunk van arcokból, akkor ennek az összehasonlításnak az elvégzése minden egyes arcon sokáig fog tartani! Képzeljük el, hogy egy valós idejű arcfelismerő rendszert építünk! Minél nagyobb az adatállományunk, annál lassabb az algoritmusunk. De a több arc jobb eredményeket is fog produkálni! Olyan rendszert szeretnénk, amely egyszerre gyors és pontos. Ehhez neurális hálózatot fogunk használni! A hálózatunkat betaníthatjuk az adathalmazunkon, és használhatjuk az arcfelismerési feladatunkhoz.

A neurális hálózat közvetlen használatával van egy probléma: a képek nagyok lehetnek! Ha egyetlen m\times n

képünk lenne, akkor azt egyetlenm\dot n\times 1vektorba kellene simítanunk, hogy bemenetként betápláljuk a neurális hálózatunkba. Nagy képméretek esetén ez árthat a sebességnek! Ez összefügg a naiv megközelítésünkben a képek jelenlegi állapotukban történő felhasználásának második problémájával: ezek a képek nagy dimenziójúak! (Egym\times nkép valójában egym\dot n\times 1vektor) Egy új bemenet rengeteg zajt tartalmazhat, és minden egyes pixel összehasonlítása mátrixkivonással és euklideszi távolsággal nagy hibát és téves besorolásokat eredményezhet!

Ezek miatt nem használjuk a naiv módszert. Ehelyett szeretnénk a nagydimenziós képeinket kisebb dimenziószámra leforralni, miközben megtartjuk a kép lényegét vagy fontos részeit.

Dimenziócsökkentés

Az előző szakasz indokolja, hogy miért használunk dimenziócsökkentő technikát. A dimenziócsökkentés a felügyelet nélküli tanulás egy fajtája, ahol magasabb dimenziós adatokat, például képeket, szeretnénk kisebb dimenziós térben reprezentálni. Használjuk példaként a következő képet.

Az ábrák ugyanazokat az adatokat mutatják, csak az alsó ábra nullázza azokat. Vegyük észre, hogy adatainkhoz nem tartoznak címkék, mert ez egy felügyelet nélküli tanulás! Egyszerű esetünkben a dimenziócsökkentés ezeket az adatokat 2D-s síkból 1D-s vonalra csökkenti. Ha 3D-s adataink lennének, akkor le tudnánk redukálni őket 2D-s síkra vagy akár 1D-s vonalra is.

Minden dimenziócsökkentési technika célja, hogy találjon valamilyen hipersíkot, egy magasabb dimenziós vonalat, amelyre a pontokat vetíti. A vetítést úgy képzelhetjük el, hogy veszünk egy zseblámpát, amely merőleges a hipersíkra vetítünk, és megrajzoljuk, hogy az árnyékok hova esnek ezen a hipersíkon. Például a fenti adatainkban, ha a pontjainkat az x-tengelyre akarjuk vetíteni, akkor úgy teszünk, mintha minden pont egy gömb lenne, és a zseblámpánk közvetlenül lefelé vagy felfelé mutatna (az x-tengelyre merőlegesen), és a pontok árnyékai az x-tengelyre esnének. Ez egy vetület. Nem fogunk aggódni a mögötte lévő pontos matematika miatt, mivel a scikit-learn képes alkalmazni ezt a vetítést helyettünk.

A mi egyszerű 2D-s esetünkben egy olyan vonalat akarunk találni, amelyre a pontjainkat vetíthetjük. Miután kivetítettük a pontokat, akkor 2D helyett 1D-s adataink vannak! Hasonlóképpen, ha 3D-s adataink lennének, akkor egy síkot szeretnénk találni, amelyre a pontokat levetítjük, hogy az adataink dimenzióját 3D-ről 2D-re csökkentsük. A dimenziócsökkentés különböző típusai mind arról szólnak, hogy kitaláljuk, melyik hipersíkot válasszuk ki: végtelen sok van belőlük!

Főkomponens-elemzés

A dimenziócsökkentés egyik technikája az úgynevezett főkomponens-elemzés (PCA). A PCA lényege, hogy olyan hipersíkot akarunk kiválasztani, amelyre az összes pontot vetítve azok maximálisan eloszlanak. Más szóval, a maximális szórású tengelyt akarjuk! Nézzük a fenti példa ábránkat. Egy lehetséges tengely az x-tengely vagy az y-tengely, de mindkét esetben nem ez a legjobb tengely. Ha azonban olyan vonalat választunk, amely átlósan metszi az adatainkat, akkor ez az a tengely, ahol az adatok a legnagyobb szórást kapnák!

A hosszabb kék tengely a helyes tengely! Ha erre a tengelyre vetítenénk a pontjainkat, akkor azok maximálisan szóródnának! De hogyan találjuk ki ezt a tengelyt? A lineáris algebrából kölcsönözhetünk egy kifejezést, a sajátvektorokat! Innen kapta a nevét a sajátfelületek! Lényegében kiszámítjuk adataink kovarianciamátrixát, és megvizsgáljuk ennek a kovarianciamátrixnak a legnagyobb sajátvektorait. Ezek a főtengelyeink, és azok a tengelyek, amelyekre az adatainkat vetítjük a dimenziók csökkentése érdekében. Ezzel a megközelítéssel nagy dimenziójú adatokat vehetünk és csökkenthetjük alacsonyabb dimenzióra a kovarianciamátrix legnagyobb sajátvektorainak kiválasztásával és ezekre a sajátvektorokra való vetítéssel.

Mivel a maximális szórás tengelyeit számítjuk ki, megtartjuk adataink legfontosabb aspektusait. Az osztályozónk könnyebben elkülöníti az arcokat, ha az adataink szétszóródnak, szemben az összezsúfoltsággal.

(Vannak más dimenzionalitási technikák is, például a lineáris diszkriminancia-elemzés, amelyek felügyelt tanulást alkalmaznak, és amelyeket szintén használnak az arcfelismerésben, de a PCA nagyon jól működik!)

Hogyan kapcsolódik ez az arcfelismerési kihívásunkhoz? m\times n

képeinketm\dot ndimenziós tér pontjaiként fogalmazhatjuk meg. Ezután használhatjuk a PCA-t, hogy am\dot ntérből valami sokkal kisebbre redukáljuk a teret. Ez segít felgyorsítani a számításainkat, és robusztus lesz a zajjal és az eltérésekkel szemben.

Melléklet az arcfelismeréshez

Eleddig azt feltételeztük, hogy a bemeneti kép csak egy arc képe, de a gyakorlatban nem kell megkövetelnünk, hogy a kameraképek tökéletesen középre állított arcot mutassanak. Éppen ezért futtatunk le egy out-of-the-box arcfelismerő algoritmust, például egy arcokra képzett kaszkádosztályozót, hogy kitaláljuk, a bemeneti kép melyik részén van arc. Ha megvan ez a határoló doboz, könnyen kivághatjuk a bemeneti képnek ezt a részét, és ezen a szeleten használhatjuk a saját arcokat. (Általában kisimítjuk ezt a csúszkát, és affin transzformációt hajtunk végre, hogy eltorzítsuk az arcot, ha az szögben jelenik meg). A mi céljainkhoz feltételezzük, hogy már vannak képeink az arcokról.

Sajátarcok kód

Most, hogy megbeszéltük a PCA-t és a sajátarcokat, kódoljunk egy arcfelismerő algoritmust a scikit-learn segítségével! Először is szükségünk lesz egy adathalmazra. A mi céljainkhoz a Massachusetts-i Egyetem Labeled Faces in the Wild (LFW) nevű készletét fogjuk használni.

Bátran helyettesíthetjük saját adathalmazunkkal! Ha saját arcadatkészletet szeretne létrehozni, akkor minden egyes személy arcáról több képre lesz szüksége (különböző szögből és megvilágításban), valamint az alapigazság-címkékre. Minél többféle arcot használ, annál jobban fog teljesíteni a felismerő. A legegyszerűbb módja az arcfelismeréshez szükséges adathalmaz létrehozásának, ha minden egyes személyhez létrehoz egy mappát, és ebbe helyezi el az arcképeket. Győződjön meg róla, hogy mindegyik azonos méretű, és állítsa át a méretüket, hogy ne legyenek nagyméretű képek! Ne feledje, hogy a PCA amúgy is csökkenteni fogja a kép dimenzionalitását, amikor erre a térre vetítünk, így a nagy, nagy felbontású képek használata nem segít, és lelassítja az algoritmusunkat. A jó méret ~512×512 képenként. A képeknek mind egyforma méretűnek kell lenniük, így egy numpy tömbben tárolhatjuk őket a dimenziókkal (num_examples, height, width) . (Szürkeárnyalatos képeket feltételezünk). Ezután használjuk a mappaneveket az osztályok megkülönböztetésére. Ezzel a megközelítéssel használhatja saját képeit.

Mi azonban az LFW adathalmazt fogjuk használni. Szerencsére a scikit-learn automatikusan be tudja tölteni nekünk az adathalmazunkat a megfelelő formátumban. Meghívhatunk egy függvényt az adataink betöltéséhez. Ha az adatok nem állnak rendelkezésre a lemezen, a scikit-learn automatikusan letölti nekünk a Massachusetts Egyetem honlapjáról.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
# felosztás gyakorló és tesztkészletre
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

A függvényünk argumentuma csak kitisztítja az összes olyan személyt, akinek nincs legalább 100 arca, így csökkentve az osztályok számát. Ezután kivehetjük az adathalmazunkat és egyéb segédinformációkat. Végül az adathalmazunkat felosztjuk gyakorló és tesztelő halmazokra.

Most már egyszerűen használhatjuk a scikit-learn PCA osztályát, hogy elvégezze helyettünk a dimenziócsökkentést! Ki kell választanunk a komponensek számát, azaz a kimeneti dimenziósságot (a kivetítendő sajátvektorok számát), amire csökkenteni szeretnénk, és bátran finomítsuk ezt a paramétert, hogy megpróbáljuk a legjobb eredményt elérni! Mi 100 komponenst fogunk használni. Ezenkívül fehéríteni fogjuk az adatainkat, ami könnyen elvégezhető egy egyszerű boolean flag segítségével! (A fehérítés csak egységnyi szórásúvá teszi a kapott adatainkat, ami bizonyítottan jobb eredményeket ad)

1
2
3
4
5
6
7

# PCA kiszámítása
n_komponents = 100
pca = PCA(n_components=n_components, whiten=True).fit(X_train)
# PCA transzformáció alkalmazása
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)

A transzformációt alkalmazhatjuk, hogy a képeinket 100 dimenziós térbe hozzuk. Vegyük észre, hogy nem a teljes adathalmazon hajtjuk végre a PCA-t, csak a képzési adatokon. Ez azért van így, hogy jobban tudjunk általánosítani a nem látott adatokra.

Most, hogy van egy csökkentett dimenziójú vektorunk, betaníthatjuk a neurális hálózatunkat!

1
2
3

# neurális hálózat betanítása
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)

Azért, hogy lássuk, hogyan edz a hálózatunk, beállíthatjuk a verbose flaget. Ezen kívül használjuk a korai leállítást.

Rövid kitérőként tárgyaljuk a korai leállítást. Lényegében az optimalizátorunk minden epochában figyeli a validációs halmaz átlagos pontosságát. Ha azt veszi észre, hogy a validálási pontosságunk nem nőtt jelentősen egy bizonyos számú epocha alatt, akkor leállítjuk a képzést. Ez egy regularizációs technika, amely megakadályozza, hogy a modellünk túlilleszkedjen!

Nézzük meg a fenti ábrát. A túlilleszkedést akkor vesszük észre, amikor a validációs készletünk pontossága csökkenni kezd. Ekkor azonnal leállítjuk a képzést, hogy megakadályozzuk a túlillesztést.

Végül készíthetünk egy előrejelzést, és egy függvény segítségével kiírhatunk egy teljes jelentést az egyes osztályok minőségéről.

1
2

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

Itt egy példa az osztályozási jelentésre.

1
2
3
4
5
6
7
8
9

precision recall f1-score support
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.68 26
Tony Blair 0,86 0,71 0,78 35
avg / összesen 0,85 0,85 0,85 0,85 342

Nem létezik pontossági mérőszám. A pontosság nem a legkülönlegesebb fajta metrika a kezdéshez. Ehelyett a pontosságot, a visszahívást, az f1-pontszámot és a támogatást látjuk. A support egyszerűen az, hogy hányszor fordult elő ez a ground truth címke a tesztkészletünkben, pl. a tesztkészletünkben valójában 35 kép volt Tony Blairről. Az F1-pontszámot valójában csak a pontossági és a visszahívási pontszámokból számítjuk ki. A precizitás és a visszahívás sokkal specifikusabb mérőszámok, mint egyetlen pontossági pontszám. A magasabb érték mindkettőnél jobb.

Az osztályozónk betanítása után adhatunk neki néhány képet osztályozásra.

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

# Vizualizáció
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(y_pred, y_test, target_names))
plot_gallery(X_test, prediction_titles, h, w)

(plot_gallery és titles függvények a scikit-learn dokumentációból módosítva)

Láthatjuk a hálózatunk előrejelzéseit és a ground truth értéket minden képhez.

Egy másik érdekes dolog, amit megjeleníthetünk, maguk a sajátfelületek. Ne feledjük, hogy a PCA sajátvektorokat állít elő. Ezeket a sajátvektorokat átformálhatjuk képekké, és vizualizálhatjuk a sajátarcokat.

Ezek az adathalmazunk “általános” arcait képviselik. Intuitív módon ezek olyan vektorok, amelyek irányokat képviselnek az “arctérben”, és ezeket használja a neurális hálózatunk az osztályozáshoz. Most, hogy megvitattuk a sajátarcok megközelítést, olyan alkalmazásokat készíthetünk, amelyek ezt az arcfelismerő algoritmust használják!

Az arcfelismerés egy népszerű megközelítését, a sajátarcokat tárgyaltuk. A sajátarcok lényege egy felügyelet nélküli dimenziócsökkentő algoritmus, a Principal Components Analysis (PCA), amelyet arra használunk, hogy a képek dimenzióját valami kisebbre csökkentsük. Most, hogy rendelkezünk az arcok kisebb reprezentációjával, alkalmazunk egy osztályozót, amely a csökkentett dimenziójú bemenetet veszi, és létrehoz egy osztálycímkét. A mi osztályozónkhoz egy egyrétegű neurális hálózatot használtunk.

Az arcfelismerés a számítógépes látás és a gépi tanulás összeolvadásának lenyűgöző példája, és sok kutató még ma is dolgozik ezen a kihívást jelentő problémán!

Az arcfelismeréshez manapság mély konvolúciós neurális hálózatokat használnak, amelyeknek hatalmas jelentőségük van a fejlődési pálya világa szempontjából. Próbáljon ki egyet ezen az adatkészleten!

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.