Publicat inițial: 22.12.2017

imaginii

Anul acesta, Carvana, o lansare de succes a mașinilor second hand online, a provocat comunitatea Kaggle să dezvolte un algoritm care elimină automat fundalul studioului foto. Acest lucru i-ar permite Carvana să suprapună mașinile pe o varietate de medii. În interviul acestui câștigător, echipa de pe primul loc de concurenți de procesare a imaginilor numită Team Best [over] fitting, împărtășește în detaliu abordarea lor câștigătoare.

Așa cum se întâmplă adesea în competiții, nu ne-am întâlnit niciodată în persoană, dar ne cunoșteam destul de bine din conversațiile fructuoase despre învățarea profundă desfășurate în comunitatea vorbitoare de limbă rusă Open Data Science, ods.ai.

Deși am participat ca o echipă, am lucrat la 3 soluții independente până la fuzionarea cu 7 zile înainte de sfârșitul competiției. Fiecare dintre aceste soluții a fost în top 10 - Artsiom și Alexander au fost pe locul 2 și Vladimir a fost pe locul 5. Soluția noastră finală a fost o medie simplă de trei predicții. Puteți vedea acest lucru și în codul pe care l-am pregătit pentru organizatori și l-am lansat pe GitHub - există 3 foldere separate:

Fiecare dintre noi a petrecut aproximativ două săptămâni pentru această provocare, deși pentru a reproduce complet soluția noastră pe un singur Titan X Pascal, ar fi nevoie de aproximativ 90 de zile pentru a se antrena și de 13 zile pentru a face predicții. Din fericire, am avut la dispoziție în jur de 20 de GPU-uri. În ceea ce privește software-ul, am folosit PyTorch ca Deep Learning Framework, OpenCV pentru procesarea imaginilor și imgaug pentru mărirea datelor.

Numele meu este Vladimir Iglovikov. Am obținut o diplomă de master în fizică teoretică a energiei înalte de la St. Universitatea de Stat din Petersburg și un doctorat. în fizica teoretică a materiei condensate de la UC Davis. După absolvire, am lucrat mai întâi la câteva start-up-uri unde meseria mea de zi cu zi era grea în domeniul învățării automate tradiționale. Acum câteva luni m-am alăturat Lyft ca Data Scientist, cu accent pe viziunea pe computer.

Am concurat deja la mai multe competiții de segmentare a imaginilor și experiența dobândită a fost foarte utilă cu această problemă. Iată realizările mele din trecut:

Această provocare arăta destul de similară cu problemele de mai sus și inițial nu intenționam să particip. Dar, doar pentru o verificare a sănătății, am decis să fac câteva trimiteri cu o conductă copiată de la problemele anterioare. Surprinzător, după câteva încercări am intrat în top 10 și băieții au sugerat o echipă să se unească. În plus, Alexander m-a ademenit promițând să împărtășesc abordarea sa non-UNet, care consuma mai puțină memorie, convergea mai repede și era probabil mai precisă.

În ceea ce privește hardware-ul, am avut 2 mașini acasă, unul pentru prototipuri cu 2 x Titan X Pascal și unul pentru ridicare grea cu 4 x GTX 1080 Ti.

Numele meu este Alexander Buslaev. Am absolvit Universitatea ITMO, Saint-Petersburg, Rusia. Am o experiență de 5 ani în viziunea computerizată clasică și am lucrat într-o serie de companii din acest domeniu, în special în UAV. Acum aproximativ un an am început să folosesc învățarea profundă pentru diverse sarcini în procesarea imaginilor - detectare, segmentare, etichetare, regresie.

Îmi plac competițiile de viziune computerizată, așa că am participat și la:

Numele meu este Artsiom Sanakoyeu. Am obținut masteratul în matematică aplicată și informatică de la Universitatea de Stat din Belarus, Minsk, Belarus. După absolvire, am început doctoratul. în Computer Vision la Universitatea Heidelberg, Germania.

Principalele mele interese de cercetare se află la intersecția dintre viziunea computerizată și învățarea profundă, în special învățarea nesupravegheată și învățarea metrică. Am publicații în conferințe de top-computer Vision/Deep Learning precum NIPS și CVPR.

Pentru mine, Kaggle este un loc pentru a-mi lustrui abilitățile aplicate și pentru a mă distra competitiv. Dincolo de Carvana, am participat la alte câteva competiții de viziune computerizată:

Obiectivul acestei competiții a fost de a crea un model pentru segmentarea binară a imaginilor auto de înaltă rezoluție.

  • Fiecare imagine are o rezoluție de 1918x1280.
  • Fiecare mașină prezentată în 16 orientări fixe diferite:

  • Set tren: 5088 Imagini.
  • Set de testare: 1200 în public, 3664 în privat, 95200 au fost adăugate pentru a preveni etichetarea manuală.

În general, calitatea datelor concurenței a fost foarte ridicată și credem că acest set de date poate fi folosit ca un punct de referință excelent în comunitatea de viziune computerizată.

Diferența de scor dintre rezultatul nostru (0,997332) și locul al doilea (0,997331) a fost de doar 0,00001, ceea ce poate fi interpretat ca o îmbunătățire medie de 2,5 pixeli pentru o imagine de 2,500,000 pixeli. Ca să fiu sincer, tocmai am avut noroc aici. Când am pregătit soluția pentru organizatori, am investit ceva timp suplimentar și am îmbunătățit soluția la 0.997343 pe LB privat.

Pentru a înțelege limitările modelelor noastre, am efectuat o inspecție vizuală a predicțiilor. Pentru setul de trenuri, am analizat cazurile cu cele mai mici scoruri de validare.

Majoritatea erorilor observate s-au datorat etichetării incoerente, unde cea mai frecventă problemă a fost găurile din roți. În unele mașini, erau mascați și în unele nu.

Nu avem un scor de validare pentru setul de testare, dar am găsit imagini problematice numărând numărul de pixeli în care încrederea în predicția rețelei era scăzută. Pentru a ține cont de dimensiunea diferită a mașinilor din imagini, am împărțit acest număr la aria fundalului. Valoarea noastră „neconfidență” a fost calculată ca un număr de pixeli cu scoruri în intervalul [0,3, 0,8], împărțit la un număr de pixeli cu scoruri în intervalul [0, 0,3) + [0,8, 0,9]. să fie mai robust, dar această euristică a funcționat suficient de bine.

Apoi am clasat imaginile după scorul „necredință” și am inspectat vizual predicțiile de top. Am aflat că majoritatea erorilor au fost cauzate de etichetarea incorectă a omului din categoria „duba albă”. Rețelele ofereau în mod consecvent predicții de încredere scăzută asupra acestor imagini. Credem că s-a datorat prezenței scăzute a camionetelor albe în setul de antrenament și a contrastului scăzut dintre camionetă și fundalul alb. Imaginea de mai jos prezintă zone gri în mască în care încrederea în predicție a fost scăzută.

Nu am fost singurii care au întâmpinat această problemă. A fost discutat la forum, iar alți participanți au implementat euristicile de post-procesare pentru a aborda acest caz și cazuri similare.

Au existat, de asemenea, câteva măști de antrenament cu erori mari, cum ar fi cea de mai jos. Heng CherKeng a postat versiuni fixe ale măștilor la forum, dar numărul lor a fost relativ mic și nu le-am folosit în timpul antrenamentului.

Prima mea încercare a fost să folosesc UNet cu aceeași arhitectură ca Sergey Mushinskiy. Am folosit acest lucru înainte în detectarea funcției de imagini prin satelit DSTL în primăvara trecută, dar nu am reușit să trec peste 0.997 (

Locul 50 în LB public).

În provocarea DSTL, UNet cu codificator pre-antrenat a funcționat exact la fel ca și cum ar fi inițializat aleatoriu. De asemenea, am putut arăta rezultate bune fără inițializarea pre-antrenată în celelalte provocări și, din această cauză, am avut impresia că pentru UNet, inițializarea pre-antrenată nu este necesară și nu oferă niciun avantaj.

Acum cred că inițializarea arhitecților de tip UNet cu greutăți pre-antrenate îmbunătățește convergența și performanța segmentării binare pe imaginile de intrare RGB pe 8 biți. Când am încercat UNet cu codificator bazat pe VGG-11 am obținut cu ușurință 0,972 (top 10 la clasamentul public).

Pentru mărirea imaginii, am folosit flip-uri orizontale, măriri de culoare și transformarea unei mașini (dar nu de fundal) în tonuri de gri.

TOP STÂNGA - ORIGINAL, TOP DREAPTA - MAȘINĂ ÎN SCARĂ DE GRI, RÂND DE FOND - AUGMENTAȚII ÎN SPAȚIUL HSV.

Imaginile originale au avut rezoluție (1918, 1280) și au fost umplute la (1920, 1280), astfel încât fiecare parte să fie divizibilă cu 32 (cerință de rețea), apoi utilizate ca intrare.

Cu această arhitectură și dimensiunea imaginii, aș putea încadra o singură imagine pe GPU, așa că nu am folosit codificatoare mai profunde precum VGG 16/19. De asemenea, dimensiunea lotului meu a fost limitată la doar 4 imagini.

O soluție posibilă ar fi să te antrenezi pe culturi și să prezici imagini complete. Cu toate acestea, am avut impresia că segmentarea funcționează mai bine atunci când obiectul este mai mic decât imaginea de intrare. În acest set de date, unele mașini au ocupat întreaga lățime a imaginii, așa că am decis să nu decupez imaginile.

O altă abordare, utilizată de alți participanți, a fost reducerea la scară a imaginilor de intrare, dar acest lucru ar putea duce la unele pierderi de precizie. Deoarece scorurile erau atât de apropiate unele de altele, nu am vrut să pierd niciun pixel la această transformare (amintim 0,000001 marjă între primul și al doilea loc în clasamentul privat)

Pentru a reduce varianța predicțiilor, am efectuat pungi prin antrenarea rețelelor separate pe cinci ori și media celor cinci predicții ale acestora.

În modelul meu am folosit următoarea funcție de pierdere:

Este utilizat pe scară largă în segmentarea imaginilor binare, deoarece simplifică pragul, împingând predicțiile până la capetele intervalului [0, 1].

Și am folosit Adam Optimizer. Pentru primele 30 de epoci am scăzut rata de învățare cu un factor de două, când pierderea validării nu s-a îmbunătățit pentru două epoci. Apoi, pentru alte 20 de epoci, am folosit rata ciclică de învățare, oscilând între 1e-4 și 1e-6 conform programului: 1e-6, 1e-5, 1e-4, 1e-5, 1e-6, cu 2 epoci în fiecare ciclu.

Cu câteva zile înainte de sfârșitul competiției am încercat o pseudoetichetare și a arătat o creștere constantă a scorului, dar nu am avut suficient timp pentru a valorifica pe deplin potențialul acestei tehnici în această provocare.

Predicții pentru fiecare dosar fără post procesare:

Ca toți ceilalți, am început cu binecunoscuta arhitectură UNet și am realizat curând că pe hardware-ul meu trebuie să redimensionez imaginile de intrare sau să aștept veșnic până când va afla ceva bun despre culturile de imagini. Următoarea mea încercare a fost să generez o mască dură și să creez culturi numai de-a lungul graniței, cu toate acestea învățarea a fost încă prea lentă. Apoi am început să caut noi arhitecți și am găsit un videoclip de instruire de învățare automată care arată cum să utilizați LinkNet pentru segmentarea imaginilor. Am găsit hârtia sursă și am încercat-o.

LinkNet este o arhitectură clasică de segmentare codificator-decodor cu următoarele proprietăți:

  1. Ca codificator, folosește diferite straturi de rețele ușoare, cum ar fi Resnet 34 sau Resnet 18.
  2. Decodorul este format din 3 blocuri: convoluție 1x1 cu n // 4 filtre, convoluție transpusă 3x3 cu pasul 2 și n // 4 filtre și, în cele din urmă, o altă convoluție 1x1 pentru a se potrivi cu numărul de filtre cu o dimensiune de intrare.
  3. Straturile de codificator și decodor cu dimensiuni de hartă ale caracteristicilor potrivite sunt conectate printr-o operație plus. De asemenea, am încercat să le concatenez în dimensiunea filtrelor și să folosesc conv1x1 pentru a reduce numărul de filtre din straturile următoare - funcționează puțin mai bine.

Principalul dezavantaj al acestei arhitecturi este legat de prima caracteristică puternică care începe de la o dimensiune a imaginii de 4 ori mai mică, deci s-ar putea să nu fie atât de precisă pe cât ne-am putea aștepta.

Am ales Resnet 34 pentru un codificator. Am încercat și Resnet 18, care nu era suficient de puternic, și Resnet 50, care avea o mulțime de parametri și era mai greu de antrenat. Codificatorul a fost pregătit în prealabil pe setul de date Imagenet. O epocă a durat doar 9 minute să se antreneze și s-a produs o soluție decentă după doar 2-3 epoci! Cu siguranță ar trebui să încercați LinkNet - este extrem de rapid și eficient din punct de vedere al memoriei. L-am antrenat pe imagini complete 1920 * 1280 cu 1 imagine/GPU (7,5 GB) pentru un lot.

Am aplicat augmentări moi: flip-uri orizontale, 100 pix shift-uri, 10% scalări, rotații de 5 ° și augmentări HSV. De asemenea, am folosit optimizatorul Adam (și RMSProp) cu rata de învățare 1e-4 pentru primele 12 epoci și 1e-5 pentru încă 6 epoci. Funcția de pierdere: 1 + BCE - zaruri. Augmentarea timpului de testare: flip-uri orizontale.

De asemenea, am efectuat pungi pentru a reduce varianța predicțiilor. Întrucât timpul meu de antrenament a fost atât de rapid, aș putea antrena mai multe rețele și le pot calcula predicțiile. În cele din urmă, am avut 6 rețele diferite, cu și fără trucuri, cu 5 pliuri în fiecare rețea, adică În total, am avut în medie 30 de modele. Nu este o mare îmbunătățire absolută, fiecare rețea a adus o contribuție, iar diferența de scor cu locul al doilea în clasamentul privat a fost mică.

Trucuri mai puțin frecvente:

  1. Înlocuiți conectarea plus LinkNet săriți conexiunile cu concat și conv1x1.
  2. Minare negativă dură: repetați cel mai rău lot din 10 loturi.
  3. Preprocesare de egalizare a histogramei adaptive cu contrast limitat (CLAHE): utilizată pentru a adăuga contrast la fundul negru.
  4. Rata ciclică de învățare la sfârșit. Programul exact al ratei de învățare a fost de 3 cicluri de: (2 epoca 1e-4, 2 epoca 1e-5, 1 epoca 1e-6). În mod normal, ar trebui să aleg un punct de control pe ciclu, dar din cauza timpului de inferență ridicat tocmai am ales cel mai bun punct de control din toate ciclurile.

Am instruit două rețele care au făcut parte din transmiterea noastră finală. Spre deosebire de colegii mei de echipă care și-au instruit modelele cu imagini cu rezoluție completă, am folosit imagini de intrare redimensionate 1024x1024 și am actualizat măștile prevăzute înapoi la rezoluția originală la pasul de inferență.

Prima rețea: UNet de la zero

Am adaptat un UNet personalizat cu 6 blocuri convoluționale Sus/Jos. Fiecare bloc Down a fost format din 2 straturi convoluționale, urmate de un strat de 2x2 max-pooling. Fiecare bloc Up a avut un strat bilinear upscaling urmat de 3 straturi convoluționale.

Ponderile rețelei au fost inițializate aleatoriu.

Am folosit f (x) = BCE + 1 - DICE ca funcție de pierdere, unde BCE este pierderea de entropie încrucișată binară pe pixel și DICE este un scor de zaruri.

La calcularea pierderii BCE, fiecare pixel al măștii a fost ponderat în funcție de distanța de la limita mașinii. Acest truc a fost propus de Heng CherKeng. Pixelii de pe graniță aveau o greutate de 3 ori mai mare decât în ​​adâncul zonei mașinii.

Datele au fost împărțite în 7 pliuri fără stratificare. Rețeaua a fost instruită de la zero pentru 250 de epoci folosind SGD cu impuls, multiplicând rata de învățare cu 0,5 la fiecare 100 de epoci.

A doua rețea: UNet-VGG-11

Ca a doua rețea, am luat UNet cu VGG-11 ca codificator, similar cu cel folosit de Vladimir, dar cu un decodor mai larg.

VGG-11 („VGG-A”) este o rețea convoluțională cu 11 straturi introdusă de Simonyan & Zisserman. Frumusețea acestei rețele este că codificatorul său (VGG-11) a fost pre-instruit pe setul de date Imagenet, ceea ce reprezintă o inițializare foarte bună a greutăților.

Pentru validări încrucișate am folosit 7 pliuri, stratificate după suprafața totală a măștilor pentru fiecare mașină în toate cele 16 orientări.

Rețeaua a fost pregătită pentru 60 de epoci cu pierderi ponderate, la fel ca în prima rețea, cu o rată de învățare ciclică. O buclă de învățare este de 20 de epoci: 10 epoci cu base_lr, 5 epoci cu base_lr * 0,1 și 5 epoci cu base_lr * 0,01.

Dimensiunea efectivă a lotului era de 4. Când nu se încadra în memoria GPU, am acumulat gradienții pentru mai multe iterații.

Am folosit două tipuri de augmentări:

  • Greu - traducere aleatorie, scalare, rotație, schimbare a luminozității, schimbare a contrastului, schimbare a saturației, conversie în tonuri de gri.
  • Lumina - traducere aleatorie, scalare și rotație.

Primul model a fost antrenat cu augmentări grele. Al doilea a fost antrenat pentru 15 epoci cu augmentări grele și pentru 45 de epoci cu augmentări ușoare.

În total am pregătit 14 modele (2 arhitecți, câte 7 pliuri). Tabelul de mai jos arată scorul zarurilor la validare încrucișată și la LB public.

Ansamblarea modelelor din diferite pliuri (linia „ansamblu” din tabel) a fost realizată prin media a 7 predicții din 7 pliuri pe imaginile de testare.

După cum puteți vedea, ansamblurile ambelor rețele au aproximativ aceeași performanță - 0,9972. Dar, datorită inițializării diferiților arhitecți și greutăți, o combinație a acestor două modele aduce o contribuție semnificativă la performanța ansamblului final al echipei noastre.

Am folosit o medie simplă la nivel de pixeli a modelelor ca strategie de fuziune. În primul rând, am făcut în medie 6 * 5 = 30 de modele ale lui Alexander și apoi am făcut o medie a tuturor celorlalte modele cu acesta.

De asemenea, am vrut să găsim valori aberante și cazuri dificile. Pentru aceasta, am luat o predicție medie, am găsit pixeli în intervalul de probabilitate 0,3-0,8 și le-am marcat ca fiind de încredere. Apoi am sortat toate rezultatele suprafeței de pixeli fiabile și am procesat în plus cele mai grave cazuri. Pentru aceste cazuri, am selectat cele mai performante modele și am ajustat limita de probabilitate. De asemenea, am realizat carena convexă pe zone cu fiabilitate redusă. Această abordare a dat măști frumoase pentru cazurile în care rețelele noastre au eșuat.