Klassifisering av håndskrevne tegninger. Rapport i Yandex

For noen måneder siden, våre kolleger fra Google brukt på Kaggle en konkurranse for å lage en klassifisering for bilder oppnådd i den oppsiktsvekkende spillet "Raskt, tegn!" Teamet, som inkluderte Yandex-utvikleren Roman Vlasov, tok fjerdeplassen i konkurransen. På maskinlæringsopplæringen i januar delte Roman teamets ideer, den endelige implementeringen av klassifisereren og interessant praksis fra motstanderne.


- Hei alle sammen! Jeg heter Roma Vlasov, i dag skal jeg fortelle deg om Quick, Draw! Doodle Recognition Challenge.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Det var fem personer på laget vårt. Jeg ble med rett før sammenslåingsfristen. Vi var uheldige, vi ble rystet litt, men vi ble ristet fra pengeposisjonen, og de ble ristet fra gullposisjonen. Og vi tok en hederlig fjerdeplass.

(Under konkurransen observerte lagene seg selv i en vurdering, som ble dannet basert på resultatene vist på en del av det foreslåtte datasettet. Den endelige vurderingen ble på sin side dannet på en annen del av datasettet. Dette er gjort slik at konkurransedeltakerne ikke justerer algoritmene sine til spesifikke data Derfor, i finalen, når man bytter mellom rangeringer, rister posisjonene litt opp (fra engelsk shake up - to mix): på andre data kan resultatet vise seg. å være annerledes. Romans lag var først blant de tre beste. I dette tilfellet er de tre beste pengene, monetær vurderingssone, siden bare de tre første plassene ble tildelt en pengepremie. Etter omveltningen var laget allerede i fjerdeplass. På samme måte tapte det andre laget seieren, gullposisjonen. - Red.)

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Konkurransen var også betydelig ved at Evgeniy Babakhnin mottok en stormester, Ivan Sosin mottok en mester, Roman Soloviev forble en stormester, Alex Parinov fikk en mester, jeg ble en ekspert, og nå er jeg allerede en mester.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Hva er dette Quick, Draw? Dette er en tjeneste fra Google. Google hadde som mål å popularisere AI og ønsket med denne tjenesten å vise hvordan nevrale nettverk fungerer. Du går dit, klikker på La oss tegne, og det dukker opp en ny side der du får beskjed: tegn en sikksakk, du har 20 sekunder på deg til å gjøre dette. Du prøver å tegne en sikksakk på 20 sekunder, som for eksempel her. Hvis du lykkes, sier nettverket at det er en sikksakk og du går videre. Det er bare seks slike bilder.

Hvis Googles nettverk ikke klarte å gjenkjenne det du tegnet, ble det satt et kryss på oppgaven. Senere vil jeg fortelle deg hva det vil bety i fremtiden om en tegning gjenkjennes av nettverket eller ikke.

Denne tjenesten samlet et ganske stort antall brukere, og alle bildene som brukerne tegnet ble loggført.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Vi klarte å samle nesten 50 millioner bilder. Fra dette ble tog- og testdatoen for vår konkurranse dannet. Forresten, mengden data i testen og antall klasser er markert med fet skrift av en grunn. Jeg skal fortelle deg om dem litt senere.

Dataformatet var som følger. Dette er ikke bare RGB-bilder, men grovt sett en logg over alt brukeren gjorde. Word er målet vårt, landskode er der forfatteren av doodlen kommer fra, tidsstempel er tid. Den gjenkjente etiketten viser bare om nettverket gjenkjente bildet fra Google eller ikke. Og selve tegningen er en sekvens, en tilnærming av en kurve som brukeren tegner med punkter. Og tidspunkter. Dette er tiden fra begynnelsen av å tegne bildet.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Data ble presentert i to formater. Dette er det første formatet, og det andre er forenklet. De kuttet ut tidspunktene derfra og tilnærmet dette settet med punkter med et mindre sett med punkter. Til dette brukte de Douglas-Pecker-algoritme. Du har et stort sett med punkter som ganske enkelt tilnærmer en rett linje, men faktisk kan du tilnærme denne linjen med bare to punkter. Dette er ideen med algoritmen.

Dataene ble fordelt som følger. Alt er ensartet, men det er noen ytterliggere. Da vi løste problemet, så vi ikke på det. Hovedsaken er at det ikke var noen klasser som var virkelig få, vi trengte ikke å gjøre vektede samplere og dataoversampling.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Hvordan så bildene ut? Dette er "fly"-klassen og eksempler fra den med etikettene gjenkjent og ugjenkjent. Forholdet deres var et sted rundt 1 til 9. Som du kan se, er dataene ganske støyende. Jeg vil tippe det er et fly. Hvis du ser på ikke gjenkjent, er det i de fleste tilfeller bare støy. Noen prøvde til og med å skrive «fly», men tilsynelatende på fransk.

De fleste deltakerne tok ganske enkelt rutenett, tegnet data fra denne sekvensen av linjer som RGB-bilder og kastet dem inn i nettverket. Jeg tegnet omtrent på samme måte: Jeg tok en palett med farger, tegnet den første linjen med en farge, som var i begynnelsen av denne paletten, den siste linjen med en annen, som var på slutten av paletten, og mellom dem Jeg interpolerte overalt ved å bruke denne paletten. Dette ga forresten et bedre resultat enn om du tegner som på det aller første lysbildet – bare i sort.

Andre teammedlemmer, som Ivan Sosin, prøvde litt andre tilnærminger til tegning. Med en kanal tegnet han ganske enkelt et grått bilde, med en annen kanal tegnet han hvert slag med en gradient fra begynnelse til slutt, fra 32 til 255, og med den tredje kanalen tegnet han en gradient over alle slag fra 32 til 255.

En annen interessant ting er at Alex Parinov lastet opp informasjon til nettverket ved hjelp av landskode.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Beregningen som brukes i konkurransen er gjennomsnittlig snittpresisjon. Hva er essensen av denne beregningen for konkurranse? Du kan gi tre prediksjoner, og hvis det ikke er noen riktig prediksjon i disse tre, får du 0. Hvis det er en riktig, blir rekkefølgen tatt i betraktning. Og målresultatet vil bli regnet som 1 delt på rekkefølgen til prediksjonen din. For eksempel har du laget tre prediktorer, og den riktige er den første, så deler du 1 på 1 og får 1. Hvis prediktoren er riktig og rekkefølgen er 2, deler du 1 på 2, får du 0,5. Vel, osv.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Med dataforbehandling - hvordan tegne bilder og så videre - har vi bestemt oss litt. Hvilke arkitekturer brukte vi? Vi prøvde å bruke fete arkitekturer som PNASNet, SENet, og slike allerede klassiske arkitekturer som SE-Res-NeXt, de deltar i stadig større grad i nye konkurranser. Det var også ResNet og DenseNet.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Hvordan lærte vi dette? Alle modellene vi tok var forhåndstrent på imagenet. Selv om det er mye data, 50 millioner bilder, men likevel, hvis du tar et nettverk som er forhåndstrent på imagenet, viste det bedre resultater enn om du bare trente det fra bunnen av.

Hvilke undervisningsteknikker brukte vi? Dette er Cosing Annealing with Warm Restarts, som jeg skal snakke om litt senere. Dette er en teknikk som jeg bruker i nesten alle de siste konkurransene mine, og med dem viser det seg å trene rutenettene ganske bra, for å oppnå et godt minimum.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Neste Reduser læringsraten på platået. Du begynner å trene nettverket, setter en viss læringsrate, fortsetter å lære det, og tapet ditt konvergerer gradvis til en viss verdi. Du sjekker dette, for eksempel for ti epoker har tapet ikke endret seg i det hele tatt. Du reduserer læringsraten med en viss verdi og fortsetter å lære. Det synker litt igjen, konvergerer på et minimum, og du senker igjen læringshastigheten, og så videre, til nettverket ditt endelig konvergerer.

Neste er en interessant teknikk: Ikke forfall læringshastigheten, øk batchstørrelsen. Det er en artikkel med samme navn. Når du trener et nettverk, trenger du ikke redusere læringshastigheten, du kan ganske enkelt øke batchstørrelsen.

Denne teknikken ble forresten brukt av Alex Parinov. Han startet med en batch lik 408, og når nettverket hans nådde et visst platå, doblet han ganske enkelt batchstørrelsen osv.

Faktisk husker jeg ikke hvilken verdi batchstørrelsen hans nådde, men det som er interessant er at det var team på Kaggle som brukte samme teknikk, batchstørrelsen deres var omtrent 10000 XNUMX. Forresten moderne rammeverk for dyp læring, som f.eks. PyTorch, for eksempel, lar deg gjøre dette veldig enkelt. Du genererer batchen din og sender den til nettverket ikke som den er, i sin helhet, men deler den opp i biter slik at den passer inn i skjermkortet ditt, regner ut gradientene, og etter at du har beregnet gradienten for hele batchen, oppdaterer du vektene.

Forresten, store batchstørrelser var fortsatt inkludert i denne konkurransen, fordi dataene var ganske støyende, og en stor batchstørrelse hjalp deg mer nøyaktig tilnærmet gradienten.

Pseudo-merking ble også brukt, mest brukt av Roman Soloviev. Han samplet omtrent halvparten av dataene fra testen i batcher, og trente rutenettet på slike batcher.

Størrelsen på bildene betydde noe, men faktum er at du har mye data, du må trene lenge, og hvis bildestørrelsen din er ganske stor, vil du trene veldig lenge. Men dette bidro ikke mye til kvaliteten på den endelige klassifiseringen din, så det var verdt å bruke en slags avveining. Og vi prøvde kun bilder som ikke var veldig store i størrelsen.

Hvordan ble det hele lært? Først ble det tatt små bilder, det ble kjørt flere epoker på dem, dette tok ganske mye tid. Så ble det gitt bilder i store størrelser, nettverket ble trent, så enda mer, enda mer, for ikke å trene det fra bunnen av og ikke kaste bort mye tid.

Om optimerere. Vi brukte SGD og Adam. På denne måten var det mulig å få en enkelt modell, som ga en hastighet på 0,941-0,946 på den offentlige ledertavlen, noe som er ganske bra.

Hvis du setter sammen modellene på en eller annen måte, vil du få et sted rundt 0,951. Hvis du bruker en teknikk til, vil du få en sluttscore på 0,954 på den offentlige tavlen, akkurat som vi fikk. Men mer om det senere. Deretter vil jeg fortelle deg hvordan vi satte sammen modellene, og hvordan vi klarte å oppnå en slik endelig hastighet.

Deretter vil jeg snakke om Cosing Annealing med varme omstarter eller Stokastisk gradientnedstigning med varme omstarter. Grovt sett kan du i prinsippet bruke hvilken som helst optimizer, men poenget er dette: hvis du bare trener ett nettverk og gradvis konvergerer det til et minimum, så er alt i orden, du får ett nettverk, det gjør visse feil, men du kan trene det litt annerledes. Du vil angi en innledende læringsrate, og gradvis senke den i henhold til denne formelen. Du senker det, nettverket ditt kommer til et minimum, så sparer du vektene, og igjen stiller du inn læringsraten som var i begynnelsen av treningen, og går derved et sted oppover fra dette minimumet, og senker læringsraten igjen.

Dermed kan du besøke flere minimumskrav samtidig, der tapet ditt vil være, pluss eller minus, det samme. Men faktum er at nettverk med disse vektene vil gi forskjellige feil på daten din. Ved å snitte dem vil du få en slags tilnærming, og hastigheten din blir høyere.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Om hvordan vi satte sammen modellene våre. I begynnelsen av presentasjonen sa jeg å være oppmerksom på mengden data i testen og antall klasser. Legger du til 1 i antall mål i prøvesettet og deler på antall klasser får du tallet 330, og dette ble skrevet på forumet - at klassene i prøven er balansert. Dette kan brukes.

Basert på dette, kom Roman Soloviev opp med en beregning, vi kalte den Proxy Score, som korrelerte ganske bra med ledertavlen. Poenget er: du gjør en prediksjon, tar topp 1 av prediktorene dine og teller antall objekter for hver klasse. Deretter trekker du 330 fra hver verdi og legger sammen de resulterende absolutte verdiene.

Følgende verdier ble oppnådd. Dette hjalp oss med å ikke lage en sonderende ledertavle, men å validere lokalt og velge koeffisienter for ensemblene våre.

Med et ensemble kunne man få en slik fart. Hva annet kan jeg gjøre? Anta at du brukte informasjonen om at klassene i testen din er balansert.

Balanseringen var annerledes. Et eksempel på en av dem — balansering fra gutta som tok førsteplassen.

Hva gjorde vi? Balanseringen vår var ganske enkel, ble det foreslått av Evgeny Babakhnin. Vi sorterte først spådommene våre etter topp 1 og valgte kandidater fra dem – slik at antallet klasser ikke oversteg 330. Men for noen klasser ender du opp med færre enn 330 prediktorer. Ok, la oss også sortere etter topp 2 og topp 3 , og vi vil også velge ut kandidater.

Hvordan skilte vår balansering seg fra balanseringen i utgangspunktet? De brukte en iterativ tilnærming, tok den mest populære klassen og reduserte sannsynlighetene for den klassen med et lite antall til den klassen ikke lenger var den mest populære. Vi tok den nest mest populære timen. Så de fortsatte å senke dem til antallet av alle klasser ble likt.

Alle brukte pluss eller minus én tilnærming til tognett, men ikke alle brukte balansering. Ved å bruke balansering kunne du gå inn i gull, og hvis du var heldig, så inn i penger.

Hvordan forhåndsbehandle en dato? Alle forhåndsbehandlet datoen, pluss eller minus, på samme måte - laget håndlagde funksjoner, prøvde å kode tidtaking med forskjellige strekfarger osv. Alexey Nozdrin-Plotnitsky, som tok 8. plass, snakket om dette.

Klassifisering av håndskrevne tegninger. Rapport i Yandex

Han gjorde det annerledes. Han sa at alle disse håndlagde funksjonene dine ikke fungerer, du trenger ikke gjøre det, nettverket ditt bør lære alt dette på egen hånd. Og i stedet kom han med læringsmoduler som forhåndsbehandlet dataene dine. Han kastet de originale dataene inn i dem uten forbehandling - punktkoordinater og tidspunkter.

Deretter tok han forskjellen basert på koordinatene, og satte gjennomsnittet av det hele basert på tidspunktene. Og han kom opp med en ganske lang matrise. Han brukte 1D konvolusjon på den flere ganger for å oppnå en matrise med størrelse 64xn, der n er det totale antall punkter, og 64 er laget for å mate den resulterende matrisen til laget til ethvert konvolusjonsnettverk, som aksepterer antall kanaler - 64. han fikk en 64xn matrise, så var det nødvendig å lage en tensor av en eller annen størrelse slik at antall kanaler var lik 64. Han normaliserte alle punktene X, Y i området fra 0 til 32 for å lage en tensor av størrelse 32x32. Jeg vet ikke hvorfor han ville ha 32x32, det bare ble sånn. Og ved denne koordinaten plasserte han et fragment av denne matrisen med størrelse 64xn. Så det endte bare opp med en 32x32x64 tensor som du kunne sette lenger inn i det konvolusjonelle nevrale nettverket ditt. Det var alt jeg ville si.

Kilde: www.habr.com

Legg til en kommentar