SNA Hackathon 2019

En februaro-marto 2019, konkurso estis okazigita por rangigi la socian retan nutradon SNA Hackathon 2019, en kiu nia teamo prenis la unuan lokon. En la artikolo mi parolos pri la organizo de la konkurso, la metodoj, kiujn ni provis, kaj la catboost-agordoj por trejnado pri grandaj datumoj.

SNA Hackathon 2019

SNA Hackathon

Ĉi tio estas la trian fojon, ke hakatono sub ĉi tiu nomo okazas. Ĝi estas organizita de la socia reto ok.ru, respektive, la tasko kaj datumoj rekte rilatas al ĉi tiu socia reto.
SNA (analizo de socia reto) ĉi-kaze estas pli ĝuste komprenata ne kiel analizo de socia grafikaĵo, sed prefere kiel analizo de socia reto.

  • En 2014, la tasko estis antaŭdiri la nombron da ŝatoj ricevus afiŝon.
  • En 2016 - la tasko VVZ (eble vi estas konata), pli proksima al la analizo de la socia grafikaĵo.
  • En 2019, rangigante la nutradon de la uzanto surbaze de la verŝajneco, ke la uzanto ŝatos la afiŝon.

Mi ne povas diri pri 2014, sed en 2016 kaj 2019, krom kapabloj pri datuma analizo, ankaŭ estis bezonataj kapabloj por labori kun grandaj datumoj. Mi pensas, ke ĝi estis la kombinaĵo de maŝinlernado kaj problemoj pri grandaj datumtraktado, kiu altiris min al ĉi tiuj konkursoj, kaj mia sperto en ĉi tiuj areoj helpis min venki.

mlbootcamp

En 2019, la konkurso estis organizita sur la platformo https://mlbootcamp.ru.

La konkurso komenciĝis interrete la 7-an de februaro kaj konsistis el 3 taskoj. Iu ajn povus registriĝi en la retejo, elŝuti bazlinio kaj ŝarĝu vian aŭton dum kelkaj horoj. Ĉe la fino de la reta stadio la 15-an de marto, la supraj 15 de ĉiu spektaklo-saltado estis invititaj al la oficejo Mail.ru por la eksterreta stadio, kiu okazis de la 30-a de marto ĝis la 1-a de aprilo.

Objektivo

La fontaj datumoj disponigas uzantidentojn (userId) kaj afiŝidentojn (objectId). Se al la uzanto estis montrita afiŝo, tiam la datumoj enhavas linion enhavantan userId, objectId, uzantreagojn al ĉi tiu afiŝo (religoj) kaj aron de diversaj funkcioj aŭ ligiloj al bildoj kaj tekstoj.

userId objectId posedantoId sugestoj bildoj
3555 22 5677 [ŝatis, klakis] [hash1]
12842 55 32144 [malŝatis] [hash2,hash3]
13145 35 5677 [klakita, dividita] [hash2]

La testa datumaro enhavas similan strukturon, sed la reagokampo mankas. La tasko estas antaŭdiri la ĉeeston de la "ŝatata" reago en la reagokampo.
La sendadosiero havas la jenan strukturon:

userId OrdigitaListo[objectId]
123 78,13,54,22
128 35,61,55
131 35,68,129,11

La metriko estas la averaĝa ROC AUC por uzantoj.

Pli detala priskribo de la datumoj troveblas ĉe retejo de la konsilio. Vi ankaŭ povas elŝuti datumojn tie, inkluzive de testoj kaj bildoj.

Enreta etapo

En la reta stadio, la tasko estis dividita en 3 partojn

  • Kunlabora sistemo — inkluzivas ĉiujn funkciojn krom bildoj kaj tekstoj;
  • Bildoj — inkluzivas nur informojn pri bildoj;
  • Tekstoj — inkluzivas informojn nur pri tekstoj.

Senreta etapo

En la eksterreta stadio, la datumoj inkludis ĉiujn funkciojn, dum tekstoj kaj bildoj estis malabundaj. Estis 1,5-oble pli da vicoj en la datumaro, el kiuj jam estis multaj.

La solvo de la problemo

Ĉar mi faras CV ĉe la laboro, mi komencis mian vojaĝon en ĉi tiu konkurso kun la tasko "Bildoj". La datumoj provizitaj estis userId, objectId, ownerId (la grupo en kiu la afiŝo estis publikigita), tempomarkoj por krei kaj montri la afiŝon, kaj, kompreneble, la bildo por ĉi tiu afiŝo.
Post generi plurajn funkciojn bazitajn sur tempomarkoj, la sekva ideo estis preni la antaŭlastan tavolon de la neŭrono antaŭtrejnita sur imagenet kaj sendi ĉi tiujn enkonstruaĵojn al akcelo.

SNA Hackathon 2019

La rezultoj ne estis impresaj. Enkonstruadoj de la imagenet-neŭrono estas sensignivaj, mi pensis, mi devas fari mian propran aŭtokodilon.

SNA Hackathon 2019

Necesis multe da tempo kaj la rezulto ne pliboniĝis.

Karakterizaĵa generacio

Labori kun bildoj prenas multan tempon, do mi decidis fari ion pli simplan.
Kiel vi povas tuj vidi, estas pluraj kategoriaj funkcioj en la datumaro, kaj por ne tro ĝeni, mi ĵus prenis catboost. La solvo estis bonega, sen iuj agordoj mi tuj alvenis al la unua linio de la gvidtabulo.

Estas sufiĉe multe da datumoj kaj ĝi estas aranĝita en pargeta formato, do sen pripensi dufoje, mi prenis scalan kaj komencis skribi ĉion en spark.

La plej simplaj trajtoj, kiuj donis pli da kresko ol bildaj enkonstruadoj:

  • kiom da fojoj objectId, userId kaj ownerId aperis en la datumoj (devus korelacii kun populareco);
  • kiom da afiŝoj userId vidis de ownerId (devus korelacii kun la intereso de la uzanto en la grupo);
  • kiom da unikaj uzantidentoj rigardis afiŝojn de ownerId (reflektas la grandecon de la spektantaro de la grupo).

El tempomarkoj eblis akiri la tagan horon, je kiu la uzanto spektis la nutradon (matene/posttagmeze/vespere/nokte). Kombinante ĉi tiujn kategoriojn, vi povas daŭre generi funkciojn:

  • kiom da fojoj userId ensalutinta vespere;
  • je kioma horo ĉi tiu afiŝo estas plej ofte montrata (objectId) ktp.

Ĉio ĉi iom post iom plibonigis la metrikojn. Sed la grandeco de la trejna datumaro estas ĉirkaŭ 20M rekordoj, do aldoni funkciojn multe malrapidigis la trejnadon.

Mi repensis mian aliron al uzado de datumoj. Kvankam la datumoj dependas de tempo, mi ne vidis evidentajn informojn "en la estonteco", tamen, ĉiaokaze, mi malkonstruis ĝin jene:

SNA Hackathon 2019

La trejnaro provizita al ni (februaro kaj 2 semajnoj de marto) estis dividita en 2 partojn.
La modelo estis trejnita laŭ datumoj de la lastaj N tagoj. La agregaĵoj priskribitaj supre estis konstruitaj sur ĉiuj datumoj, inkluzive de la testo. Samtempe aperis datumoj, sur kiuj eblas konstrui diversajn kodigojn de la cela variablo. La plej simpla aliro estas reuzi kodon, kiu jam kreas novajn funkciojn, kaj simple nutri al ĝi datumojn, pri kiuj ĝi ne estos trejnita kaj celo = 1.

Tiel, ni ricevis similajn funkciojn:

  • Kiom da fojoj userId vidis afiŝon en la grupo ownerId;
  • Kiom da fojoj userId ŝatis la afiŝon en grupposedantoId;
  • La procento de afiŝoj, kiujn userId ŝatis de ownerId.

Tio estas, ĝi rezultis signifas celkodigon sur parto de la datumaro por diversaj kombinaĵoj de kategoriaj trajtoj. Principe, catboost ankaŭ konstruas celkodigon kaj el ĉi tiu vidpunkto ne estas profito, sed, ekzemple, eblis kalkuli la nombron da unikaj uzantoj, kiuj ŝatis afiŝojn en ĉi tiu grupo. Samtempe, la ĉefa celo estis atingita - mia datumaro estis reduktita plurajn fojojn, kaj eblis daŭre generi funkciojn.

Dum catboost povas konstrui kodigon nur surbaze de la ŝatata reago, reagoj havas aliajn reagojn: redividita, malŝatita, malŝatita, klakita, ignorita, kodigoj por kiuj povas esti faritaj permane. Mi rekalkulis ĉiajn agregaĵojn kaj forigis funkciojn kun malalta graveco por ne ŝveligi la datumaron.

Tiam mi estis en la unua loko je larĝa marĝeno. La nura afero, kiu estis konfuza, estis ke bildaj enkonstruadoj preskaŭ ne montris kreskon. La ideo venis doni ĉion al catboost. Ni amasigas Kmeans-bildojn kaj ricevas novan kategoriecan bildon Cat.

Jen kelkaj klasoj post mana filtrado kaj kunfandado de aretoj akiritaj de KMeans.

SNA Hackathon 2019

Surbaze de imageCat ni generas:

  • Novaj kategoriaj trajtoj:
    • Kiu bildoKato estis plej ofte vidita de userId;
    • Kiu bildoKato plej ofte montras posedantoIdon;
    • Kiun bildoKato plej ofte ŝatis userId;
  • Diversaj nombriloj:
    • Kiom da unika imageCat rigardis userId;
    • Ĉirkaŭ 15 similaj funkcioj plus cela kodigo kiel priskribite supre.

Tekstoj

La rezultoj en la bilda konkurso konvenis al mi kaj mi decidis provi tekstojn. Mi ne multe laboris kun tekstoj antaŭe kaj, stulte, mi mortigis la tagon ĉe tf-idf kaj svd. Tiam mi vidis bazlinion kun doc2vec, kiu faras ĝuste tion, kion mi bezonas. Iomete ĝustiginte la doc2vec-parametrojn, mi ricevis tekstajn enkonstruojn.

Kaj tiam mi simple reuzis la kodon por la bildoj, en kiuj mi anstataŭigis la bildajn enmetaĵojn per tekstaj enmetaĵoj. Rezulte mi prenis la 2-an lokon en la tekstokonkurso.

Kunlabora sistemo

Restis unu konkurso, kiun mi ankoraŭ ne "pikis" per bastono, kaj se juĝante la AUC sur la gvidtabulo, la rezultoj de ĉi tiu speciala konkurso devus havi la plej grandan efikon sur la eksterreta scenejo.
Mi prenis ĉiujn funkciojn, kiuj estis en la fontaj datumoj, elektis kategoriajn kaj kalkulis la samajn agregaĵojn kiel por bildoj, krom ecoj bazitaj sur la bildoj mem. Nur meti ĉi tion en catboost kondukis min al la dua loko.

Unuaj paŝoj de catboost-optimumigo

Unu unua kaj du duaj lokoj plaĉis al mi, sed estis kompreno, ke mi faris nenion specialan, kio signifas, ke mi povus atendi perdon de pozicio.

La tasko de la konkurado estas rangigi afiŝojn ene de la uzanto, kaj dum ĉi tiu tempo mi solvis la klasifikproblemon, tio estas, optimumigante la malĝustan metrikon.

Mi donu al vi simplan ekzemplon:

userId objectId antaŭdiro grunda vero
1 10 0.9 1
1 11 0.8 1
1 12 0.7 1
1 13 0.6 1
1 14 0.5 0
2 15 0.4 0
2 16 0.3 1

Ni faru malgrandan rearanĝon

userId objectId antaŭdiro grunda vero
1 10 0.9 1
1 11 0.8 1
1 12 0.7 1
1 13 0.6 0
2 16 0.5 1
2 15 0.4 0
1 14 0.3 1

Ni ricevas la sekvajn rezultojn:

La modelo AUC Uzanto1 AUC Uzanto2 AUC signifas AUC
Eblo 1 0,8 1,0 0,0 0,5
Eblo 2 0,7 0,75 1,0 0,875

Kiel vi povas vidi, plibonigi la totalan AUC-metrikon ne signifas plibonigi la averaĝan AUC-metrikon ene de uzanto.

Catboost scias kiel optimumigi rangajn metrikojn el la skatolo. Mi legis pri rangaj metrikoj, sukcesaj rakontoj kiam vi uzas catboost kaj agordu YetiRankPairwise trejni dum la nokto. La rezulto ne estis impresa. Decidante, ke mi estas nesufiĉe trejnita, mi ŝanĝis la erarfunkcion al QueryRMSE, kiu, se juĝante laŭ la dokumentado de catboost, konverĝas pli rapide. Fine mi ricevis la samajn rezultojn kiel dum trejnado por klasifiko, sed la ensembloj de ĉi tiuj du modeloj donis bonan kreskon, kio alportis min al la unua loko en ĉiuj tri konkursoj.

5 minutojn antaŭ la fermo de la reta stadio de la konkurso "Kunlaboraj Sistemoj", Sergey Shalnov movis min al la dua loko. Ni kune marŝis la plian vojon.

Preparante por la eksterreta etapo

Ni estis garantiita venko en la reta stadio kun RTX 2080 TI videokarto, sed la ĉefa premio de 300 rubloj kaj, plej verŝajne, eĉ la fina unua loko devigis nin labori dum ĉi tiuj 000 semajnoj.

Kiel evidentiĝis, Sergey ankaŭ uzis catboost. Ni interŝanĝis ideojn kaj funkciojn, kaj mi eksciis pri tio raporto de Anna Veronica Dorogush kiu enhavis respondojn al multaj miaj demandoj, kaj eĉ tiujn, kiujn mi ĝis tiam ankoraŭ ne havis.

Vidado de la raporto kondukis min al la ideo, ke ni devas redoni ĉiujn parametrojn al la defaŭlta valoro, kaj fari la agordojn tre zorge kaj nur post fiksado de aro da funkcioj. Nun unu trejnado daŭris ĉirkaŭ 15 horojn, sed unu modelo sukcesis akiri pli bonan rapidon ol tiu akirita en la ensemblo kun ranking.

Karakterizaĵa generacio

En la Kunlaboraj Sistemoj-konkurado, granda nombro da ecoj estas taksitaj kiel gravaj por la modelo. Ekzemple, auditweights_spark_svd - la plej grava signo, sed ne estas informo pri tio, kion ĝi signifas. Mi pensis, ke indus nombri la diversajn agregaĵojn surbaze de gravaj trajtoj. Ekzemple, averaĝa auditweights_spark_svd laŭ uzanto, laŭ grupo, laŭ objekto. La sama povas esti kalkulita uzante datumoj sur kiuj neniu trejnado estas farita kaj celo = 1, tio estas, mezumo auditweights_spark_svd de uzanto per objektoj kiujn li ŝatis. Gravaj signoj krome auditweights_spark_svd, estis pluraj. Jen kelkaj el ili:

  • auditweightsCtrGender
  • auditweightsCtrHigh
  • userOwnerCounterCreateLikes

Ekzemple, la mezumo auditweightsCtrGender laŭ userId ĝi montriĝis grava trajto, same kiel la averaĝa valoro userOwnerCounterCreateLikes per userId+ownerId. Ĉi tio jam devus pensigi vin, ke vi devas kompreni la signifon de la kampoj.

Ankaŭ gravaj trajtoj estis auditweightsLikesCount и auditweightsShowsCount. Dividante unu per la alia, eĉ pli grava trajto estis akirita.

Datumfluoj

Konkurado kaj produktadmodelado estas tre malsamaj taskoj. Kiam vi preparas datumojn, estas tre malfacile konsideri ĉiujn detalojn kaj ne transdoni iujn ne-trivialajn informojn pri la cela variablo en la testo. Se ni kreas produktadsolvon, ni provos eviti uzi datumfluojn dum trejnado de la modelo. Sed se ni volas gajni la konkurson, tiam datumaj likoj estas la plej bonaj funkcioj.

Studinte la datumojn, vi povas vidi tion laŭ la valoroj de objectId auditweightsLikesCount и auditweightsShowsCount ŝanĝo, kio signifas, ke la proporcio de la maksimumaj valoroj de ĉi tiuj funkcioj reflektos la postkonverton multe pli bone ol la proporcio en la momento de montrado.

La unua liko, kiun ni trovis, estas auditweightsLikesCountMax/auditweightsShowsCountMax.
Sed kio se ni rigardas la datumojn pli detale? Ni ordigu laŭ spektaklodato kaj ricevu:

objectId userId auditweightsShowsCount auditweightsLikesCount celo (estas ŝatata)
1 1 12 3 verŝajne ne
1 2 15 3 eble jes
1 3 16 4

Estis surprize, kiam mi trovis la unuan tian ekzemplon kaj montriĝis, ke mia antaŭdiro ne realiĝis. Sed, konsiderante la fakton, ke la maksimumaj valoroj de ĉi tiuj trajtoj ene de la objekto pliigis, ni ne estis maldiligentaj kaj decidis trovi auditweightsShowsCountNext и auditweightsLikesCountNext, tio estas, la valoroj en la venonta momento en la tempo. Aldonante funkcion
(auditweightsShowsCountNext-auditweightsShowsCount)/(auditweightsShowsCount-auditweightsLikesCountNext) ni rapide faris akran salton.
Similaj likoj povus esti uzataj trovante la sekvajn valorojn por userOwnerCounterCreateLikes ene de userId+ownerId kaj, ekzemple, auditweightsCtrGender ene de objectId+userGender. Ni trovis 6 similajn kampojn kun likoj kaj ĉerpis tiom da informoj kiel eble el ili.

Antaŭ tiu tempo, ni elpremis kiel eble plej multe da informoj el kunlaboraj funkcioj, sed ne revenis al bildaj kaj tekstaj konkursoj. Mi havis bonegan ideon kontroli: kiom donas funkcioj rekte bazitaj sur bildoj aŭ tekstoj en koncernaj konkursoj?

Ne estis likoj en la bildaj kaj tekstaj konkursoj, sed tiam mi resendis la defaŭltajn catboost-parametrojn, purigis la kodon kaj aldonis kelkajn funkciojn. La totalo estis:

decido baldaŭ
Maksimumo kun bildoj 0.6411
Maksimume neniuj bildoj 0.6297
Dua loko rezulto 0.6295

decido baldaŭ
Maksimume kun tekstoj 0.666
Maksimumo sen tekstoj 0.660
Dua loko rezulto 0.656

decido baldaŭ
Maksimumo en kunlaborado 0.745
Dua loko rezulto 0.723

Evidentiĝis, ke ni verŝajne ne povos elpremi multon el tekstoj kaj bildoj, kaj post provi kelkajn el la plej interesaj ideoj, ni ĉesis labori kun ili.

Plia generacio de funkcioj en kunlaboraj sistemoj ne donis pliiĝon, kaj ni komencis klasifiki. En la reta stadio, la klasifika kaj rangiga ensemblo donis al mi malgrandan kreskon, ĉar evidentiĝis, ĉar mi subtrejnis la klasifikon. Neniu el la erarfunkcioj, inkluzive de YetiRanlPairwise, produktis ie proksime al la rezulto, kiun faris LogLoss (0,745 kontraŭ 0,725). Ekzistis ankoraŭ espero por QueryCrossEntropy, kiu ne povus esti lanĉita.

Senreta etapo

En la senreta stadio, la datumstrukturo restis la sama, sed estis malgrandaj ŝanĝoj:

  • identigiloj userId, objectId, ownerId estis rehazardigitaj;
  • pluraj signoj estis forigitaj kaj pluraj estis renomitaj;
  • la datumoj pliiĝis proksimume 1,5 fojojn.

Aldone al la listigitaj malfacilaĵoj, estis unu granda pluso: al la teamo estis asignita granda servilo kun RTX 2080TI. Mi ĝuis htop dum longa tempo.
SNA Hackathon 2019

Estis nur unu ideo - simple reprodukti tion, kio jam ekzistas. Post kelkaj horoj agordante la medion sur la servilo, ni iom post iom komencis kontroli, ke la rezultoj estas reprodukteblaj. La ĉefa problemo, kiun ni alfrontas, estas la pliiĝo de datumvolumo. Ni decidis iomete redukti la ŝarĝon kaj agordi la parametron catboost ctr_complexity=1. Ĉi tio iomete malaltigas la rapidon, sed mia modelo ekfunkciis, la rezulto estis bona - 0,733. Sergey, male al mi, ne dividis la datumojn en 2 partojn kaj trejnis pri ĉiuj datumoj, kvankam ĉi tio donis la plej bonajn rezultojn en la reta stadio, en la eksterreta stadio estis multaj malfacilaĵoj. Se ni prenus ĉiujn funkciojn, kiujn ni generis, kaj provus enŝovi ilin en catboost, tiam nenio funkcius en la reta stadio. Sergey faris tajpoptimumigon, ekzemple, konvertante float64-tipojn al float32. En ĉi tiu artikolo Vi povas trovi informojn pri memor-optimumigo en pandoj. Kiel rezulto, Sergey trejnis sur la CPU uzante ĉiujn datumojn kaj ricevis ĉirkaŭ 0,735.

Ĉi tiuj rezultoj estis sufiĉaj por venki, sed ni kaŝis nian veran rapidecon kaj ne povis esti certaj, ke aliaj teamoj ne faras la samon.

Batalu ĝis la lasta

Catboost-agordado

Nia solvo estis plene reproduktita, ni aldonis la funkciojn de tekstaj datumoj kaj bildoj, do restis nur agordi la parametrojn de catboost. Sergey trejnis sur la CPU kun malgranda nombro da ripetoj, kaj mi trejnis sur tiu kun ctr_complexity=1. Restis unu tago, kaj se vi nur aldonis ripetojn aŭ pliigis ctr_complexity, tiam antaŭ la mateno vi povus akiri eĉ pli bonan rapidecon kaj marŝi la tutan tagon.

Ĉe la eksterreta stadio, rapidecoj povus esti tre facile kaŝitaj simple elektante ne la plej bonan solvon en la retejo. Ni atendis drastajn ŝanĝojn en la gvidtabulo en la lastaj minutoj antaŭ ol la aliĝoj fermiĝis kaj decidis ne ĉesi.

De la video de Anna, mi lernis, ke por plibonigi la kvaliton de la modelo, estas plej bone elekti la jenajn parametrojn:

  • lerna_ritmo — La defaŭlta valoro estas kalkulita surbaze de la grandeco de la datumaro. Pliigi learning_rate postulas pliigi la nombron da ripetoj.
  • l2_folio_reg — Reguliga koeficiento, defaŭlta valoro 3, prefere elektu de 2 ĝis 30. Malkresko de la valoro kondukas al pliigo de trofikso.
  • bagging_temperature — aldonas hazardigon al la pezoj de objektoj en la specimeno. La defaŭlta valoro estas 1, kie la pezoj estas tiritaj de eksponenta distribuo. Malkresko de la valoro kondukas al pliigo de troa kapablo.
  • hazarda_forto — Influas la elekton de disiĝoj ĉe specifa ripeto. Ju pli alta estas random_strength, des pli alta estas la ebleco, ke malalta graveca disigo estu elektita. Ĉe ĉiu posta ripeto, la hazardo malpliiĝas. Malkresko de la valoro kondukas al pliigo de troa kapablo.

Aliaj parametroj havas multe pli malgrandan efikon al la fina rezulto, do mi ne provis elekti ilin. Unu ripeto de trejnado sur mia GPU-datumaro kun ctr_complexity=1 daŭris 20 minutojn, kaj la elektitaj parametroj sur la reduktita datumaro estis iomete malsamaj de la optimumaj sur la plena datumaro. Fine, mi faris ĉirkaŭ 30 ripetojn pri 10% de la datumoj, kaj poste ĉirkaŭ 10 pliajn ripetojn pri ĉiuj datumoj. Rezultis io kiel ĉi tio:

  • lerna_ritmo Mi pliiĝis je 40% de la defaŭlta;
  • l2_folio_reg lasis ĝin same;
  • bagging_temperature и hazarda_forto reduktita al 0,8.

Ni povas konkludi, ke la modelo estis subtrejnita kun la defaŭltaj parametroj.

Mi estis tre surprizita kiam mi vidis la rezulton sur la ĉeftabulo:

La modelo modelo 1 modelo 2 modelo 3 ensemblo
Sen agordado 0.7403 0.7404 0.7404 0.7407
Kun agordo 0.7406 0.7405 0.7406 0.7408

Mi mem konkludis, ke se ne necesas rapida apliko de la modelo, tiam estas pli bone anstataŭigi la elekton de parametroj per ensemblo de pluraj modeloj uzante ne-optimumigitajn parametrojn.

Sergey optimumigis la grandecon de la datumaro por funkcii ĝin sur la GPU. La plej simpla opcio estas fortranĉi parton de la datumoj, sed ĉi tio povas esti farita en pluraj manieroj:

  • iom post iom forigu la plej malnovajn datumojn (komence de februaro) ĝis la datumaro komencas konveni en memoron;
  • forigi funkciojn kun la plej malalta graveco;
  • forigi uzantidentojn por kiuj ekzistas nur unu eniro;
  • lasu nur la uzantidentojn kiuj estas en la testo.

Kaj finfine, faru ensemblon el ĉiuj ebloj.

La lasta ensemblo

Ĝis malfrua vespero de la lasta tago, ni aranĝis ensemblon de niaj modeloj, kiuj donis 0,742. Dum la nokto mi lanĉis mian modelon kun ctr_complexity=2 kaj anstataŭ 30 minutoj ĝi trejnis dum 5 horoj. Nur je la 4-a matene ĝi estis kalkulita, kaj mi faris la lastan ensemblon, kiu donis 0,7433 sur la publika estraro.

Pro malsamaj aliroj al solvi la problemon, niaj antaŭdiroj ne estis forte korelaciitaj, kio donis bonan pliiĝon en la ensemblo. Por akiri bonan ensemblon, estas pli bone uzi la krudmodelajn prognozojn predict(prediction_type='RawFormulaVal') kaj agordi scale_pos_weight=neg_count/pos_count.

SNA Hackathon 2019

En la retejo vi povas vidi finrezultoj sur la privata estraro.

Aliaj solvoj

Multaj teamoj sekvis la kanonojn de rekomendaj sistemaj algoritmoj. Mi, ne estante fakulo pri ĉi tiu kampo, ne povas taksi ilin, sed mi memoras 2 interesajn solvojn.

  • La solvo de Nikolao Anoĥin. Nikolay, estante dungito de Mail.ru, ne petis premiojn, do lia celo estis ne atingi maksimuman rapidecon, sed akiri facile skaleblan solvon.
  • Ĵurio-premio gajnanta teamo decido bazita sur ĉi tiu artikolo de fejsbuko, permesis tre bonan bildgrupon sen mana laboro.

konkludo

Kio plej restis en mia memoro:

  • Se estas kategoriaj trajtoj en la datumoj, kaj vi scias kiel fari celan kodigon ĝuste, estas ankoraŭ pli bone provi catboost.
  • Se vi partoprenas konkurson, vi ne malŝparu tempon elektante parametrojn krom lernado_ritmo kaj ripetoj. Pli rapida solvo estas fari ensemblon de pluraj modeloj.
  • Akceloj povas lerni sur la GPU. Catboost povas lerni tre rapide sur la GPU, sed ĝi manĝas multe da memoro.
  • Dum la disvolviĝo kaj testado de ideoj, estas pli bone agordi malgrandan rsm~=0.2 (nur CPU) kaj ctr_complexity=1.
  • Male al aliaj teamoj, la ensemblo de niaj modeloj donis grandan kreskon. Ni nur interŝanĝis ideojn kaj skribis en malsamaj lingvoj. Ni havis malsaman aliron al disigo de la datumoj kaj, mi pensas, ĉiu havis siajn proprajn erarojn.
  • Ne estas klare, kial rangiga optimumigo rezultis pli malbone ol klasifika optimumigo.
  • Mi akiris iom da sperto pri laboro kun tekstoj kaj komprenon pri kiel oni faras rekomendajn sistemojn.

SNA Hackathon 2019

Dankon al la organizantoj pro la emocioj, scio kaj premioj ricevitaj.

fonto: www.habr.com

Aldoni komenton