Klassificering av handskrivna ritningar. Rapportera i Yandex

För några månader sedan, våra kollegor från Google tillbringade på Kaggle en tävling för att skapa en klassificerare för bilder som erhållits i det sensationella spelet "Snabb ritning!" Teamet, som inkluderade Yandex-utvecklaren Roman Vlasov, tog en fjärde plats i tävlingen. Vid maskininlärningsutbildningen i januari delade Roman sitt teams idéer, den slutliga implementeringen av klassificeraren och intressanta metoder från sina motståndare.


- Hej alla! Jag heter Roma Vlasov, idag ska jag berätta om Quick, Draw! Doodle Recognition Challenge.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Det var fem personer i vårt team. Jag gick med precis innan deadline för sammanslagningen. Vi hade otur, vi skakades lite, men vi skakades från pengapositionen, och de skakades från guldpositionen. Och vi tog en hedervärd fjärdeplats.

(Under tävlingen observerade lagen sig själva i ett betyg, som bildades baserat på de resultat som visades på en del av den föreslagna datamängden. Det slutliga betyget i sin tur bildades på en annan del av datasetet. Detta görs så att tävlingsdeltagarna inte anpassar sina algoritmer till specifik data Därför, i finalen, när man växlar mellan betyg, så skakar positionerna lite (från engelska shake up - to mix): på andra data kan resultatet visa sig. att vara annorlunda. Romans lag var först bland de tre bästa. I det här fallet är de tre bästa pengar, monetär ratingzon, eftersom endast de tre första platserna belönades med ett kontantpris. Efter omvälvningen var laget redan i fjärde plats. På samma sätt förlorade det andra laget segern, guldpositionen. - Red.)

Klassificering av handskrivna ritningar. Rapportera i Yandex

Tävlingen var också betydande genom att Evgeniy Babakhnin fick en stormästare, Ivan Sosin fick en mästare, Roman Soloviev förblev en stormästare, Alex Parinov fick en mästare, jag blev en expert och nu är jag redan en mästare.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Vad är det här Quick, Draw? Detta är en tjänst från Google. Google hade som mål att popularisera AI och ville med denna tjänst visa hur neurala nätverk fungerar. Du går dit, klickar på Låt oss rita och en ny sida dyker upp där du får veta: rita en sicksack, du har 20 sekunder på dig att göra detta. Du försöker rita en sicksack på 20 sekunder, som här till exempel. Om du lyckas säger nätverket att det är en sicksack och du går vidare. Det finns bara sex sådana bilder.

Om Googles nätverk inte kunde känna igen det du ritade, sattes ett kryss på uppgiften. Senare kommer jag att berätta vad det kommer att betyda i framtiden om en ritning känns igen av nätverket eller inte.

Denna tjänst samlade ett ganska stort antal användare och alla bilder som användarna ritade loggades.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Vi lyckades samla in nästan 50 miljoner bilder. Utifrån detta bildades tåg- och testdatum för vår tävling. Förresten, mängden data i testet och antalet klasser är markerade med fet stil av en anledning. Jag ska berätta om dem lite senare.

Dataformatet var som följer. Det här är inte bara RGB-bilder, utan, grovt sett, en logg över allt användaren gjorde. Word är vårt mål, landskoden är varifrån författaren till doodlen kommer, tidsstämpel är tid. Den igenkända etiketten visar bara om nätverket kände igen bilden från Google eller inte. Och själva ritningen är en sekvens, en approximation av en kurva som användaren ritar med punkter. Och tider. Detta är tiden från början av att rita bilden.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Data presenterades i två format. Detta är det första formatet och det andra är förenklat. De klippte ut tidpunkterna därifrån och approximerade denna uppsättning punkter med en mindre uppsättning punkter. Till detta använde de Douglas-Pecker-algoritm. Du har en stor uppsättning punkter som helt enkelt approximerar en rak linje, men i själva verket kan du approximera denna linje med bara två punkter. Detta är idén med algoritmen.

Uppgifterna fördelades enligt följande. Allt är enhetligt, men det finns några extremvärden. När vi löste problemet tittade vi inte på det. Huvudsaken är att det inte fanns några klasser som var riktigt få, vi behövde inte göra viktade sampler och dataöversampling.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Hur såg bilderna ut? Detta är "flygplansklassen" och exempel från den med etiketterna igenkända och okända. Deras förhållande var någonstans runt 1 till 9. Som du kan se är data ganska bullriga. Jag skulle gissa att det är ett flygplan. Om du tittar på inte igenkänd, i de flesta fall är det bara buller. Någon försökte till och med skriva "flygplan", men tydligen på franska.

De flesta deltagare tog helt enkelt rutnät, ritade data från denna sekvens av linjer som RGB-bilder och kastade in dem i nätverket. Jag ritade på ungefär samma sätt: jag tog en palett med färger, ritade den första linjen med en färg, som var i början av denna palett, den sista linjen med en annan, som var i slutet av paletten, och mellan dem Jag interpolerade överallt med denna palett. Detta gav för övrigt ett bättre resultat än om man ritar som på den allra första bilden - bara i svart.

Andra lagmedlemmar, som Ivan Sosin, provade lite olika sätt att rita. Med en kanal ritade han helt enkelt en grå bild, med en annan kanal ritade han varje slag med en gradient från början till slut, från 32 till 255, och med den tredje kanalen ritade han en gradient över alla slag från 32 till 255.

En annan intressant sak är att Alex Parinov laddade upp information till nätverket med hjälp av landskod.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Måttet som används i tävlingen är Mean Average Precision. Vad är kärnan i detta mått för konkurrens? Du kan ge tre prediktorer, och om det inte finns någon korrekt prediktion i dessa tre, så får du 0. Om det finns en korrekt, så tas hänsyn till dess ordning. Och målresultatet kommer att räknas som 1 dividerat med ordningen på din förutsägelse. Till exempel gjorde du tre prediktorer, och den korrekta är den första, sedan dividerar du 1 med 1 och får 1. Om prediktorn är korrekt och dess ordning är 2, dividerar du 1 med 2, får du 0,5. Tja osv.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Med dataförbearbetning - hur man ritar bilder och så vidare - har vi bestämt oss lite. Vilka arkitekturer använde vi? Vi försökte använda feta arkitekturer som PNASNet, SENet och sådana redan klassiska arkitekturer som SE-Res-NeXt, de deltar allt mer i nya tävlingar. Det fanns också ResNet och DenseNet.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Klassificering av handskrivna ritningar. Rapportera i Yandex

Klassificering av handskrivna ritningar. Rapportera i Yandex

Hur lärde vi ut detta? Alla modeller vi tog var förtränade på imagenet. Även om det finns mycket data, 50 miljoner bilder, men ändå, om du tar ett nätverk som är förtränat på imagenet, visade det bättre resultat än om du helt enkelt tränade det från grunden.

Vilka undervisningstekniker använde vi? Det här är Cosing Annealing with Warm Restarts, som jag kommer att prata om lite senare. Detta är en teknik som jag använder i nästan alla mina senaste tävlingar, och med dem visar det sig träna rutorna ganska bra, för att uppnå ett bra minimum.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Nästa Minska inlärningshastigheten på platån. Du börjar träna nätverket, ställer in en viss inlärningshastighet, fortsätter att lära ut det, och din förlust konvergerar gradvis till ett visst värde. Du kontrollerar detta, till exempel för tio epoker har förlusten inte förändrats alls. Du minskar din inlärningshastighet med något värde och fortsätter att lära dig. Det sjunker lite igen, konvergerar på ett minimum, och du sänker återigen inlärningshastigheten, och så vidare, tills ditt nätverk slutligen konvergerar.

Nästa är en intressant teknik: Försämra inte inlärningshastigheten, öka batchstorleken. Det finns en artikel med samma namn. När du tränar ett nätverk behöver du inte minska inlärningshastigheten, du kan helt enkelt öka batchstorleken.

Denna teknik användes förresten av Alex Parinov. Han började med en batch lika med 408, och när hans nätverk nådde någon platå fördubblade han helt enkelt batchstorleken osv.

Jag minns faktiskt inte vilket värde hans batchstorlek nådde, men det som är intressant är att det fanns team på Kaggle som använde samma teknik, deras batchstorlek var cirka 10000 XNUMX. Förresten, moderna ramverk för djupinlärning, som t.ex. PyTorch, till exempel, låter dig göra detta mycket enkelt. Du genererar din batch och skickar in den till nätverket inte som den är, i sin helhet, utan delar upp den i bitar så att den passar in i ditt grafikkort, beräknar gradienterna och efter att du har beräknat gradienten för hela batchen uppdaterar du vikterna.

Förresten, stora batchstorlekar ingick fortfarande i den här tävlingen, eftersom data var ganska bullriga, och en stor batchstorlek hjälpte dig att mer exakt approximera gradienten.

Pseudo-märkning användes också, mest använd av Roman Soloviev. Han provade ungefär hälften av data från testet i omgångar och tränade nätet på sådana partier.

Storleken på bilderna spelade roll, men faktum är att du har mycket data, du behöver träna länge, och om din bildstorlek är ganska stor så kommer du att träna väldigt länge. Men detta tillförde inte mycket till kvaliteten på din slutliga klassificerare, så det var värt att använda någon form av avvägning. Och vi provade bara bilder som inte var särskilt stora i storleken.

Hur lärde man sig allt? Först togs små bilder, flera epoker kördes på dem, detta tog ganska mycket tid. Sedan gavs stora bilder, nätverket tränades, sedan ännu mer, ännu mer, för att inte träna det från grunden och inte slösa bort mycket tid.

Om optimerare. Vi använde SGD och Adam. På så sätt gick det att få en enda modell, vilket gav en hastighet på 0,941-0,946 på den publika topplistan, vilket är ganska bra.

Om du ensembler modellerna på något sätt kommer du någonstans runt 0,951. Om du använder en teknik till får du ett slutresultat på 0,954 på den offentliga tavlan, precis som vi fick. Men mer om det senare. Härnäst kommer jag att berätta hur vi satte ihop modellerna och hur vi lyckades uppnå en sådan sluthastighet.

Härnäst skulle jag vilja prata om Cosing Annealing med varma omstarter eller Stokastisk Gradient Descent med varma omstarter. Grovt sett kan du i princip använda vilken optimerare som helst, men poängen är denna: om du bara tränar ett nätverk och gradvis konvergerar det till något minimum, då är allt okej, du kommer att få ett nätverk, det gör vissa misstag, men du kan träna det lite annorlunda. Du kommer att ställa in en initial inlärningshastighet och gradvis sänka den enligt denna formel. Du sänker det, ditt nätverk kommer till ett visst minimum, sedan sparar du vikterna och ställer igen inlärningshastigheten som var i början av träningen, och går därigenom någonstans uppåt från detta minimum och sänker återigen din inlärningshastighet.

Således kan du besöka flera miniminivåer samtidigt, där din förlust blir, plus eller minus, densamma. Men faktum är att nätverk med dessa vikter kommer att ge olika fel på din dejt. Genom att ta ett medelvärde av dem får du någon form av approximation, och din hastighet blir högre.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Om hur vi satt ihop våra modeller. I början av presentationen sa jag att vara uppmärksam på mängden data i testet och antalet klasser. Lägger du till 1 till antalet mål i testsetet och dividerar med antalet klasser får du siffran 330, och detta skrevs på forumet - att klasserna i testet är balanserade. Detta skulle kunna användas.

Baserat på detta kom Roman Soloviev med ett mått, vi kallade det Proxy Score, som korrelerade ganska bra med topplistan. Poängen är: du gör en förutsägelse, tar topp 1 av dina prediktorer och räknar antalet objekt för varje klass. Subtrahera sedan 330 från varje värde och addera de resulterande absoluta värdena.

Följande värden erhölls. Detta hjälpte oss att inte skapa en undersökningsresultattavla, utan att validera lokalt och välja koefficienter för våra ensembler.

Med en ensemble kunde man få en sådan fart. Vad mer kan jag göra? Anta att du använde informationen att klasserna i ditt test är balanserade.

Balanseringen var annorlunda. Ett exempel på en av dem — balansering från killarna som tog förstaplatsen.

Vad gjorde vi? Vår balansering var ganska enkel, föreslogs av Evgeny Babakhnin. Vi sorterade först våra förutsägelser efter topp 1 och valde ut kandidater från dem - så att antalet klasser inte översteg 330. Men för vissa klasser slutar du med färre än 330 prediktorer. Okej, låt oss också sortera efter topp 2 och topp 3 , och vi kommer också att välja ut kandidater.

Hur skilde sig vår balansering från balanseringen från första plats? De använde ett iterativt tillvägagångssätt, tog den mest populära klassen och minskade sannolikheterna för den klassen med ett litet antal tills den klassen inte längre var den mest populära. Vi tog den näst populäraste klassen. Så de fortsatte att sänka dem tills antalet av alla klasser blev lika.

Alla använde plus eller minus ett tillvägagångssätt för tågnät, men inte alla använde balansering. Med hjälp av balansering kunde du gå in i guld, och om du hade tur, sedan till pengar.

Hur förbearbetar man ett datum? Alla förbearbetade datumet, plus eller minus, på samma sätt - gjorde handgjorda funktioner, försökte koda timings med olika slagfärger, etc. Alexey Nozdrin-Plotnitsky, som tog 8:e plats, talade om detta.

Klassificering av handskrivna ritningar. Rapportera i Yandex

Han gjorde det annorlunda. Han sa att alla dessa handgjorda funktioner hos dig inte fungerar, du behöver inte göra det, ditt nätverk borde lära sig allt detta på egen hand. Och istället kom han med inlärningsmoduler som förbearbetade din data. Han kastade in originaldata i dem utan förbearbetning - punktkoordinater och tidpunkter.

Sedan tog han skillnaden baserat på koordinaterna och satte ett genomsnitt av allt baserat på tidpunkterna. Och han kom på en ganska lång matris. Han applicerade 1D-falsning på den flera gånger för att erhålla en matris med storleken 64xn, där n är det totala antalet punkter, och 64 görs för att mata den resulterande matrisen till lagret i vilket faltningsnät som helst, som accepterar antalet kanaler - 64. han fick en 64xn matris, sedan var det nödvändigt att skapa en tensor av någon storlek så att antalet kanaler var lika med 64. Han normaliserade alla punkter X, Y i intervallet från 0 till 32 för att skapa en tensor av storlek 32x32. Jag vet inte varför han ville ha 32x32, det blev bara så. Och vid denna koordinat placerade han ett fragment av denna matris med storleken 64xn. Så det slutade bara med en 32x32x64 tensor som du kunde lägga längre in i ditt konvolutionella neurala nätverk. Det var allt jag ville säga.

Källa: will.com

Lägg en kommentar