Salut, sunt Alex de la DEV STORIES DOT EU. scikit-image: The AI Image Pipeline, episodul 1 din 5. Înainte ca un model de deep learning să poată recunoaște o față, acesta trebuie să digere o grilă de numere. Dacă introduci acea grilă în ordinea greșită, modelul tău nu învață nimic, iar procesarea încetinește considerabil. The AI Image Pipeline:
NumPy at the Core este soluția pentru a structura corect acea grilă.
Când încarci o imagine folosind scikit-image, nu primești un obiect imagine proprietar. Primești un array N-dimensional standard, cunoscut sub numele de ndarray. O imagine este pur și simplu o matrice de pixeli. Pentru că este un simplu array NumPy, poți folosi orice operație standard pentru a face slice, mask sau pentru a manipula direct datele imaginii.
Aici este ideea esențială. Modul în care scikit-image indexează aceste array-uri îi pune în dificultate pe mulți developeri. În geometria standard, folosești coordonatele x și y, unde x este pe orizontală și y este pe verticală. scikit-image abandonează asta în favoarea notației de matrice. Primul index este rândul, care corespunde poziției verticale. Al doilea index este coloana, care corespunde poziției orizontale. Dacă ai o imagine color, al treilea index este canalul de culoare. O imagine color bidimensională standard este de fapt un array tridimensional ordonat ca rând, coloană, canal.
Să presupunem că pregătești un batch de imagini color pentru a le introduce într-o rețea neuronală convoluțională. Rețeaua ta se așteaptă la un anumit shape. Dacă imaginea ta are 256 de pixeli înălțime și 256 de pixeli lățime cu canale de roșu, verde și albastru, acel shape pentru o singură imagine este 256, 256, 3. Dar un batch cu aceste imagini adaugă o a patra dimensiune la început, reprezentând numărul de imagini.
Când aplici funcții scikit-image pe aceste date, funcția trebuie să știe care dimensiune conține valorile de culoare, ca să nu le proceseze drept date spațiale. Acest lucru este gestionat de argumentul channel axis. Setând argumentul channel axis la minus unu, îi spui funcției că acele canale de culoare se află mereu în ultima dimensiune a array-ului. Asta asigură că funcția țintește datele de culoare corecte, indiferent dacă îi pasezi o singură imagine sau un batch mare cu dimensiuni spațiale suplimentare.
Asta ne aduce la memorie. Asta este partea care contează pentru viteza de procesare. Array-urile NumPy sunt stocate în blocuri contigue de memorie, folosind by default o ordine de tip C. Asta înseamnă că ultima dimensiune din acel shape al array-ului se schimbă cel mai rapid în memoria fizică. Pentru array-ul nostru standard de imagine format din rând, coloană, canal, canalele individuale de culoare pentru un singur pixel stau unul lângă altul în memoria RAM hardware.
Dacă scrii cod custom pentru a face loop peste acești pixeli, trebuie să respecți acest memory layout. Regula este absolută: cea mai din dreapta dimensiune a array-ului tău ar trebui procesată în cel mai interior loop. Iterezi peste rânduri în acel outer loop, apoi peste coloane, apoi peste canale la interior. Dacă inversezi asta și faci loop peste rânduri la interior, forțezi CPU-ul să sară înainte și înapoi peste adrese de memorie fragmentate. Asta distruge cache locality și face codul tău să ruleze semnificativ mai lent.
Cel mai important lucru de reținut este că scikit-image nu folosește coordonate orizontale și verticale; folosește o indexare strictă de matrice cu rând, coloană și canal, iar potrivirea acelor loop-uri cu acea ordine exactă din memorie este ceea ce îți menține data pipeline-ul rapid.
Dacă vrei să ajuți acest podcast să continue, poți susține emisiunea căutând DevStoriesEU pe Patreon. Asta e tot pentru acest episod. Mulțumesc că m-ai ascultat și continuă să construiești!