Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Некалькі месяцаў таму нашы калегі з Google правялі на Kaggle конкурс па стварэнні класіфікатара малюнкаў, атрыманых у нашумелай гульні "Quick, Draw!". Каманда, у якой удзельнічаў распрацоўшчык Яндэкса Раман Уласаў, заняла ў конкурсе чацвёртае месца. На студзеньскай трэніроўцы па машынным навучанні Раман падзяліўся ідэямі сваёй каманды, фінальнай рэалізацыяй класіфікатара і цікавымі практыкамі сапернікаў.


- Ўсім прывітанне! Мяне клічуць Рома Уласаў, сёння я вам раскажу пра Quick, Draw! Doodle Recognition Challenge.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

У нашай камандзе было пяць чалавек. Я далучыўся да яе прамы перад мерж-дэдлайнам. Нам не пашанцавала, нас крыху шыйкапнула, але нас шыйкапнула з money, а іх з пазіцыі gold. І мы занялі ганаровае чацвёртае месца.

(Падчас спаборніцтва каманды назіралі сябе ў рэйтынгу, які фарміраваўся па выніках, паказаных на адной частцы прапанаванага набору даных. Фінальны рэйтынг, у сваю чаргу, фарміраваўся па іншай частцы датасета. Так робяць, каб удзельнікі спаборніцтва не падладжвалі свае алгарытмы пад канкрэтныя даныя. Таму ў фінале, пры пераключэнні паміж рэйтынгамі, пазіцыі крыху "шэйкапяцца" (ад англ. shake up - перамяшацца): на іншых дадзеных і вынік можа апынуцца іншым. Каманда Рамана спачатку была ў тройцы лідэраў. У дадзеным выпадку тройка - гэта money, грашовая зона рэйтынгу, паколькі толькі за першыя тры месцы належыў грашовы прыз. Пасля "шэйк апа" каманда апынулася ўжо на чацвёртым месцы. Гэтак жа іншая каманда страціла перамогу, пазіцыю gold. - Заўвага.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Таксама спаборніцтва было знамянальна тым, што Яўген Бабахнін атрымаў за яго гранмайстра, Іван Сосін — майстра, Раман Салаўёў так і застаўся гранмайстрам, Алекс Парын атрымаў майстра, я стаў экспертам, а цяпер я ўжо майстар.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Што гэта за Quick, Draw? Гэта сэрвіс ад Google. Google пераследваў мэту папулярызаваць ІІ і гэтым сэрвісам хацеў паказаць, як нейронавыя сеткі працуюць. Вы туды заходзіце, націскаеце Let's draw, і вам вылазіць новая старонка, дзе вам кажуць: намалюйце зігзаг, у вас на гэта ёсць 20 секунд. Вы спрабуеце намаляваць за 20 секунд зігзаг, як тут, напрыклад. Калі ў вас усё атрымліваецца, сетка кажа, што гэта зігзаг, і вы ідзяце далей. Такіх карцінак усяго шэсць.

Калі сеткі ад Google не ўдалося распазнаць, што вы намалявалі, на заданні ставіўся крыжык. Пазней я раскажу, што ў далейшым будзе значыць, распазнаны малюнак сеткай ці не.

Гэты сэрвіс сабраў даволі вялікую колькасць карыстальнікаў, і ўсе карцінкі, якія карыстальнікі малявалі, лагіраваліся.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Удалося сабраць амаль 50 млн карцінак. З гэтага фармаваўся трэйн і тэст дата для нашага спаборніцтва. Дарэчы, колькасць дадзеных у цесцю і колькасць класаў нездарма выдзелена тоўстым шрыфтам. Я пра іх раскажу крыху пазней.

Фармат даных быў наступны. Гэта не проста RGB-малюначкі, а, грубіянска кажучы, лог усяго, што рабіў карыстач. Word - гэта наш таргет, countrycode - гэта тое, адкуль родам аўтар дудла, timestamp - час. Лэйбл recognized як раз паказвае тое, распазнала сетку ад Google карцінку ці не. І сам drawing - паслядоўнасць, апраксімацыя крывой, якую карыстач малюе кропкамі. І таймінгі. Гэты час ад пачатку малявання карцінкі.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Дадзеныя былі прадстаўлены ў двух фарматах. Гэта першы фармат, а другі - спрошчаны. Яны адтуль выпілавалі таймінгі і апраксімавалі гэты набор кропак меншым наборам кропак. Для гэтага яны выкарыстоўвалі алгарытм Дугласа-Пекера. У вас вялікі набор кропак, які проста апраксімуе нейкую прамую лінію, а вы на самой справе можаце гэтую лінію апраксімаваць усяго двума кропкамі. У гэтым і заключаецца ідэя алгарытму.

Дадзеныя былі размеркаваны наступным чынам. Усё раўнамерна, але ёсць некаторыя выкіды. Калі мы рашалі задачу, то на гэта не глядзелі. Галоўнае, што не было тых класаў, якіх рэальна мала, нам не даводзілася рабіць weighted samplers і data oversampling.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Як выглядалі карцінкі? Гэта клас "самалёт" і прыклады з яго з пазнакамі recognized і unrecognized. Суадносіны іх былі дзесьці 1 да 9. Як відаць, дадзеныя дастаткова шумныя. Я б меркаваў, што гэта самалёт. Калі ж паглядзець на not recognized, гэта ў большасці выпадкаў проста шум. Хтосьці нават спрабаваў напісаць "самалёт", але мабыць, па-французску.

Большасць удзельнікаў проста бралі сеткі, адмалёўвалі дадзеныя з гэтай паслядоўнасці ліній як RGB-карцінкі і закідвалі ў сетку. Прыкладна гэтак жа адмалёўваў і я: браў палітру кветак, першы радок адмалёўваў адным колерам, які быў у пачатку гэтай палітры, апошні - іншым, які ў канцы палітры, а паміж імі ўсюды рабіў інтэрпаляцыю па гэтай палітры. Дарэчы, гэта давала лепшы вынік, чым калі вы будзеце маляваць як на самым першым слайдзе - проста чорным колерам.

Іншыя ўдзельнікі каманды, напрыклад Іван Сосін, спрабавалі крыху іншыя падыходы да малявання. Адным каналам ён проста маляваў шэрую карцінку, іншым каналам - маляваў кожны штрых градыентам ад пачатку да канца, з 32 да 255, а трэцім каналам маляваў градыент па ўсіх рысках ад 32 да 255.

Яшчэ з цікавага - Алекс Парын закідваў інфармацыю ў сетку па countrycode.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Метрыка, якая выкарыстоўвалася ў спаборніцтве, гэта Mean Average Precision. У чым сутнасць гэтай метрыкі для спаборніцтва? Вы можаце аддаць тры предикшина, і калі ў гэтых трох предикшинах няма правільнага, тыя вы атрымліваеце 0. Калі ёсць правільны, то ўлічваецца яго парадак. І вынік па таргеце будзе лічыцца як 1, падзеленае на парадак вашага прадказання. Напрыклад, вы зрабілі тры предикшина, і правільны з іх першы, тыя вы 1 дзяліце на 1 і атрымліваеце 1. Калі предикшин дакладны і яго парадак 2, то 1 дзяліце на 2, атрымліваеце 0,5. Ну і т.д.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

З перадапрацоўкай дадзеных - як маляваць карцінкі і гэтак далей - мы крыху вызначыліся. Якія архітэктуры мы выкарыстоўвалі? Мы спрабавалі выкарыстоўваць тлустыя архітэктуры, такія як PNASNet, SENet, і такія ўжо класічныя архітэктуры, як SE-Res-NeXt, яны ўсё больш заходзяць у новых спаборніцтвах. Таксама былі ResNet і DenseNet.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Як мы гэта навучалі? Усе мадэлі, якія мы бралі, мы бралі самі прадугледжанымі на imagenet. Хоць дадзеных шмат, 50 млн карцінак, але ўсё роўна, калі вы бераце сетку, прадугледжаную на imagenet, яна паказвала лепшы вынік, чым калі вы будзеце проста навучаць яе from scratch.

Якія тэхнікі для навучання мы выкарыстоўвалі? Гэта Cosing Annealing with Warm Restarts, пра яе я пагавару крыху пазней. Гэта тэхніка, якую я выкарыстоўваю практычна ва ўсіх маіх апошніх спаборніцтвах, і з імі атрымліваецца даволі добра навучыць сеткі, дасягнуць добрага мінімуму.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Далей Reduce Learning Rate on Plateau. Вы пачынаеце навучаць сетку, задаяце нейкі пэўны learning rate, далей яе вучыце, у вас паступова loss збягаецца да нейкага вызначанага значэння. Вы гэта чакаеце, напрыклад, на працягу дзесяці эпох loss ніяк не памяняўся. Вы памяншаеце ваш learning rate на нейкае значэнне і працягваеце вучыць. Ён у вас зноў крыху падае, сыходзіцца ў нейкім мінімуме і вы зноў паніжае learning rate і гэтак далей, пакуль у ваша сетка канчаткова не сыдзецца.

Далей цікавая тэхніка Не пазбягаючы каранірнага часу, павялічваецца падарожжа памеру. Ёсць артыкул з аднайменнай назвай. Калі вы навучаеце сетку, вам неабавязкова памяншаць learning rate, вы можаце проста павялічваць batch size.

Гэтую тэхніку, дарэчы, выкарыстоўваў Алекс Парынаў. Ён пачынаў з батча, роўнага 408, і калі сетка ў яго прыходзіла на нейкае плато, ён проста павялічваў batch size у два разы, і т. д.

Насамрэч, я не памятаю, да якога значэння ў яго batch size даходзіў, але што цікава, былі каманды на Kaggle, якія выкарыстоўвалі гэтую ж тэхніку, у іх batch size быў парадку 10000. Дарэчы, сучасныя фрэймворкі для deep learning, такія як PyTorch, напрыклад, дазваляюць вам гэта вельмі проста рабіць. Вы генеруеце свой батч і падаеце яго ў сетку не як ён ёсць, цалкам, а дзяліце яго на чанкі, каб у вас гэта залазіць у вашу відэакарту, лічыце градыенты, і пасля таго, як для ўсяго батча палічылі градыент робіце абнаўленне шаляў.

Дарэчы, у гэтым спаборніцтве яшчэ заходзілі вялікія batch sizes, таму што дадзеныя былі даволі шумнымі, і вялікі batch size дапамагаў вам больш дакладна апраксімаваць градыент.

Таксама выкарыстоўваўся псеўдалейблінг, яго па большай частцы выкарыстоўваў Раман Салаўёў. Ён у батч сэмпліў дзесьці палову дадзеных з цеста, і на такіх батчах навучаў сетку.

Памер карцінак гуляў значэнне, але факт у тым, што ў вас дадзеных шмат, трэба доўга навучаць, і калі ў вас памер карцінкі будзе даволі вялікім, то вы будзеце навучаць вельмі доўга. Але гэта прыносіла ў якасць вашага фінальнага класіфікатара не так шмат, так што каштавала выкарыстоўваць нейкі trade-off. І спрабавалі толькі малюнкі невялікага памеру.

Як гэта ўсё вучылася? Спачатку браліся карцінкі маленькага памеру, на іх праганялася некалькі эпох, гэта даволі хутка займала па часе. Потым даваліся карцінкі вялікага памеру, сетка вучылася, потым яшчэ больш, яшчэ больш, каб не навучаць гэта з нуля і не марнаваць вельмі шмат часу.

Пра аптымайзеры. Мы выкарыстоўвалі SGD і Adam. Такім спосабам можна было атрымаць single мадэль, якая давала хуткі 0,941-0,946 на паблік лідэрбордзе, што даволі нядрэнна.

Калі вы заансамбліруеце мадэлі нейкім чынам, тыя вы атрымаеце дзесьці 0,951. Калі ўжыць яшчэ адну тэхніку, то фінальны хуткі вы атрымаеце на паблік бардзе 0,954, як атрымалі мы. Але пра гэта крыху пазней. Далей я раскажу, як мы асамбліравалі мадэлі, і як такога фінальнага хутка ўдалося дабіцца.

Далей хацеў бы распавесці пра Cosing Annealing with Warm Restarts ці Stochastic Gradient Descent with Warm Restarts. Груба кажучы, у прынцыпе, аптымайзер вы можаце засунуць любы, але сутнасць у наступным: калі вы проста будзеце навучаць адну сетку і паступова яна будзе сыходзіцца да нейкага мінімуму, то ўсё окей, у вас атрымаецца адна сетка, яна робіць пэўныя памылкі, але вы можаце яе навучаць крыху па-іншаму. Вы будзеце задаваць нейкі пачатковы learning rate, і паступова яго паніжаць па дадзенай формуле. Вы яго прыніжае, у вас сетка прыходзіць да нейкага мінімуму, далей вы захоўваеце вагі, і зноў ставіце learning rate, які быў у пачатку навучання, тым самым з гэтага мінімуму выходзіце кудысьці наверх, і зноў прыніжае ваш learning rate.

Тым самым вы можаце наведаць адразу некалькі мінімумаў, у якіх loss у вас будзе плюс-мінус аднолькавым. Але факт у тым, што сеткі з дадзенымі шалямі будуць даваць розныя памылкі на вашай даце. Асерадніўшы іх, вы атрымаеце нейкую апраксімацыю, і ваш хуткі будзе вышэй.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Пра тое, як мы асэмблявалі нашы мадэлі. У пачатку прэзентацыі я казаў звярнуць увагу на колькасць дадзеных у тэсце і колькасць класаў. Калі да колькасці таргетаў у test set вы дадасце 1 і падзеліце на колькасць класаў, вы атрымаеце лік 330, і пра гэта пісалася на форуме - што класы ў цесцю збалансаваныя. Гэтым можна было скарыстацца.

Раман Салаўёў на аснове гэтага прыдумаў метрыку, мы яе называлі Proxy Score, якая даволі добра карэлявала з лідэрбордам. Сутнасць у чым: вы робіце предикшен, бераце топ-1 вашых прэдыктаў і лічыце колькасць аб'ектаў для кожнага класа. Далей з кожнага значэння адымаеце 330 і складаеце атрыманыя абсалютныя значэнні.

Атрымаліся такія значэнні. Гэта нам дапамагала не рабіць прабінг-лідэрборда, а валідзіравацца лакальна і падбіраць каэфіцыенты для нашых ансамбляў.

З ансамблем вы маглі атрымаць такі хуткі. Што б яшчэ зрабіць? Выкажам здагадку, вы скарысталіся інфармацыяй, што класы ў тэсце ў вас збалансаваны.

Балансіроўкі былі розныя. Прыклад адной з іх - балансіроўка ад рабят, якія занялі першае месца.

Што рабілі мы? У нас балансіроўка была даволі простая, яе прапанаваў Яўген Бабахнін. Мы спачатку сартавалі нашы прадказанні па топ-1 і з іх выбіралі кандыдатаў - такім чынам, каб колькасць класаў не перавышала 330. Але для некаторых класаў у вас атрымліваецца так, што прэдыктаў менш, чым 330. Окей, давайце яшчэ адсартуем па топ-2 і топ-3, і гэтак жа абярэм кандыдатаў.

Чым наша балансіроўка адрознівалася ад балансіроўкі першага месца? Яны выкарыстоўвалі ітэратыўны падыход, бралі самы папулярны клас і памяншалі верагоднасці для гэтага класа на нейкі маленькі лік - да таго часу, пакуль гэты клас не станавіўся не самым папулярным. Бралі наступны самы папулярны клас. Так далей і паніжалі, пакуль колькасць усіх класаў не станавілася роўнай.

Усе выкарыстоўвалі плюс-мінус адзін падыход для навучання сетак, але не ўсе выкарыстоўвалі балансаванне. Выкарыстоўваючы балансаванне, вы маглі зайсці ў голд, а калі б пашанцавала, то і ў мані.

Як перадпрацэсіць дату? Усе перадпрацэсавалі дату плюс-мінус аднолькава — рабіла handcrafted-фічы, спрабавалі закадзіраваць таймінгі розным колерам рысак і г. д. Якраз пра гэта казаў Аляксей Ноздрын-Плотніцкі, які заняў 8 месца.

Класіфікацыя рукапісных рысункаў. Даклад у Яндэксе

Ён рабіў па-іншаму. Ён казаў, што ўсе гэтыя вашы handcrafted-фічы не працуюць, так рабіць не трэба, у вас сетка павінна сама ўсё гэта вывучваць. І замест гэтага ён прыдумаў навучэнцы модулі, якія рабілі перадапрацоўку вашых дадзеных. Ён у іх закідваў зыходныя дадзеныя без перадапрацоўкі - каардынаты кропак і таймінгі.

Далей па каардынатах ён браў рознасць, а па таймінгах гэта ўсё ўсярэдніваў. І ў яго атрымлівалася задаволеная доўгая матрыца. Да яе ён некалькі разоў ужываў 1D-згортку, каб атрымаць матрыцу памерам 64хn, дзе n – агульная колькасць кропак, а 64 зроблена для таго, каб падаць атрыманую матрыцу ўжо на пласт якой-небудзь скруткавай сеткі, якая прымае колькасць каналаў – 64. У яго атрымлівалася матрыца 64хn, далей з гэтага трэба было скласці тэнзар нейкага памеру, каб колькасць каналаў было роўна 64. Ён нармаваў усе кропкі Х, Y у дыяпазоне ад 0 да 32, каб скласці тэнзар памерам 32х32. Ня ведаю, чаму ён захацеў 32х32, так атрымалася. І ў гэтую каардынату ён клаў фрагмент гэтай матрыцы памерам 64хn. Такім чынам, ён проста атрымліваў тэнзар 32х32х64, які можна было пакласці далей у вашу згортачную нейронавую сетку. У мяне ўсё.

Крыніца: habr.com

Дадаць каментар