Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Kartais, norint išspręsti problemą, tereikia pažvelgti į ją kitu kampu. Net jei per pastaruosius 10 metų panašios problemos buvo sprendžiamos vienodai su skirtingais efektais, tai nėra faktas, kad šis metodas yra vienintelis.

Yra tokia tema kaip klientų susitraukimas. Tai neišvengiama, nes bet kurios įmonės klientai dėl daugelio priežasčių gali nustoti naudotis jos produktais ar paslaugomis. Žinoma, įmonei supylimas yra natūralus, bet ne pats geidžiamiausias veiksmas, todėl visi stengiasi šį susitraukimą sumažinti iki minimumo. Dar geriau, numatykite tam tikros kategorijos naudotojų ar konkretaus naudotojo atšaukimo tikimybę ir pasiūlykite keletą veiksmų, kaip juos išlaikyti.

Būtina analizuoti ir stengtis išlaikyti klientą, jei įmanoma, dėl bent šių priežasčių:

  • naujų klientų pritraukimas yra brangesnis nei išlaikymo procedūros. Norint pritraukti naujų klientų, paprastai reikia išleisti šiek tiek pinigų (reklamai), o esamus klientus galima suaktyvinti specialiu pasiūlymu su specialiomis sąlygomis;
  • Norint tobulinti produktus ir paslaugas, svarbu suprasti priežastis, kodėl klientai išvyksta.

Yra standartinių metodų, skirtų prognozuoti mažėjimą. Tačiau viename iš AI čempionatų nusprendėme išbandyti Weibull paskirstymą. Jis dažniausiai naudojamas išgyvenamumo analizei, orų prognozavimui, stichinių nelaimių analizei, pramonės inžinerijai ir panašiai. Weibull skirstinys yra speciali paskirstymo funkcija, parametrizuojama dviem parametrais Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės и Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės.

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės
Vikipedija

Apskritai tai įdomus dalykas, bet prognozuojant nutekėjimą ir apskritai fintech jis nenaudojamas taip dažnai. Žemiau papasakosime, kaip mes (Data Mining Laboratory) tai padarėme, kartu laimėdami auksą Dirbtinio intelekto čempionate kategorijoje „AI bankuose“.

Apie churną apskritai

Supraskime šiek tiek, kas yra klientų susitraukimas ir kodėl jis toks svarbus. Klientų bazė verslui yra svarbi. Į šią bazę ateina nauji klientai, pavyzdžiui, sužinoję apie prekę ar paslaugą iš reklamos, kurį laiką gyvena (aktyviai naudojasi prekėmis) ir po kurio laiko nustoja ja naudotis. Šis laikotarpis vadinamas „kliento gyvavimo ciklu“ – tai terminas, apibūdinantis etapus, kuriuos klientas pereina, kai sužino apie produktą, priima sprendimą pirkti, sumoka, naudoja, tampa lojaliu vartotoju ir galiausiai nustoja naudoti produktą. dėl vienokių ar kitokių priežasčių. Atitinkamai, churn yra paskutinis kliento gyvenimo ciklo etapas, kai klientas nustoja naudotis paslaugomis, o verslui tai reiškia, kad klientas nustojo nešti pelną ar iš viso neduoda jokios naudos.

Kiekvienas banko klientas yra konkretus žmogus, kuris pasirenka vieną ar kitą banko kortelę būtent pagal savo poreikius. Jei dažnai keliaujate, kortelė su myliomis pravers. Perka daug – labas, cashback kortelė. Jis daug perka konkrečiose parduotuvėse – tam jau yra specialus partneris plastikas. Žinoma, kartais kortelė parenkama pagal „Pigiausios paslaugos“ kriterijų. Apskritai čia yra pakankamai kintamųjų.

Ir žmogus renkasi ir patį banką – ar yra prasmė rinktis kortelę iš banko, kurio skyriai yra tik Maskvoje ir regione, kai esi iš Chabarovsko? Net jei tokio banko kortelė yra bent 2 kartus pelningesnė, banko skyrių buvimas šalia vis tiek yra svarbus kriterijus. Taip, 2019-ieji jau atėjo ir mums viskas yra skaitmeninis, tačiau nemažai problemų su kai kuriais bankais galima išspręsti tik padalinyje. Be to, vėlgi, dalis gyventojų fiziniu banku pasitiki kur kas labiau nei programa išmaniajame telefone, į tai taip pat reikia atsižvelgti.

Dėl to asmuo gali turėti daug priežasčių atsisakyti banko produktų (ar paties banko). Pakeičiau darbą, o kortelių tarifas iš atlyginimo pasikeitė į „Paprastiems mirtingiesiems“, o tai yra mažiau pelninga. Išsikrausčiau gyventi į kitą miestą, kuriame nėra banko skyrių. Man nepatiko bendravimas su nekvalifikuotu operatoriumi filiale. Tai yra, gali būti net daugiau priežasčių uždaryti paskyrą nei naudoti produktą.

O klientas gali ne tik aiškiai išreikšti savo ketinimą – ateiti į banką ir parašyti pareiškimą, bet tiesiog nebenaudoti produktų nenutraukęs sutarties. Tokioms problemoms suprasti buvo nuspręsta panaudoti mašininį mokymąsi ir AI.

Be to, klientų nutrūkimas gali įvykti bet kurioje pramonės šakoje (telekomunikacijų, interneto tiekėjų, draudimo bendrovių, apskritai, kur yra klientų bazė ir periodinės operacijos).

Ką mes padarėme

Pirmiausia reikėjo apibūdinti aiškią ribą – nuo ​​kurio laiko pradedame laikyti klientą išvykusiu. Banko, pateikusio mums duomenis mūsų darbui, požiūriu, kliento veiklos būsena buvo dvejetainė – jis arba aktyvus, arba ne. Lentelėje „Activity“ buvo žyma ACTIVE_FLAG, kurios reikšmė galėjo būti „0“ arba „1“ (atitinkamai „Neaktyvus“ ir „Aktyvus“). Ir viskas būtų gerai, bet žmogus yra toks, kad gali kurį laiką aktyviai juo naudotis, o paskui mėnesiui iškristi iš aktyvių sąrašo – susirgo, išvyko į kitą šalį atostogauti ar net išvažiavo pasitikrinti. kortelė iš kito banko. O gal po ilgo neveiklumo vėl pradėkite naudotis banko paslaugomis

Todėl nusprendėme neveiklumo periodu pavadinti tam tikrą nuolatinį laikotarpį, per kurį jo vėliavėlė buvo nustatyta į „0“.

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Po įvairaus trukmės neveiklumo laikotarpių klientai pereina iš neaktyvių į aktyvius. Turime galimybę apskaičiuoti empirinės vertės „neaktyvumo laikotarpių patikimumo“ laipsnį – tai yra tikimybę, kad asmuo po laikino neveiklumo vėl pradės naudotis banko produktais.

Pavyzdžiui, ši diagrama rodo klientų veiklos atnaujinimą (ACTIVE_FLAG=1) po kelių mėnesių neveiklumo (ACTIVE_FLAG=0).

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Čia mes šiek tiek paaiškinsime duomenų rinkinį, su kuriuo pradėjome dirbti. Taigi bankas pateikė apibendrintą informaciją už 19 mėnesių šiose lentelėse:

  • „Veikla“ - mėnesinės klientų operacijos (kortelėmis, internetinėje bankininkystėje ir mobiliojoje bankininkystėje), įskaitant darbo užmokestį ir informaciją apie apyvartą.
  • „Kortelės“ - duomenys apie visas kliento turimas korteles su išsamiu tarifų grafiku.
  • „Sutartys“ - informacija apie kliento sutartis (tiek atviras, tiek uždaras): paskolas, indėlius ir kt., nurodant kiekvieno parametrus.
  • „Klientai“ - demografinių duomenų rinkinys (lytis ir amžius) ir kontaktinės informacijos prieinamumas.

Darbui mums reikėjo visų lentelių, išskyrus „Žemėlapį“.

Čia buvo dar vienas sunkumas – šiuose duomenyse bankas nenurodė, kokia veikla kortelėse vyko. Tai yra, mes galėjome suprasti, ar buvo sandorių, ar ne, bet nebegalėjome nustatyti jų tipo. Todėl buvo neaišku, ar klientas išsiėmė grynuosius, gauna atlyginimą, ar pinigus išleidžia pirkiniams. Taip pat neturėjome duomenų apie sąskaitų likučius, kurie būtų buvę naudingi.

Pati imtis buvo nešališka – šioje imtyje bankas per 19 mėnesių nebandė išlaikyti klientų ir sumažinti nutekėjimą.

Taigi, apie neveiklumo laikotarpius.

Norint suformuluoti churn apibrėžimą, reikia pasirinkti neveiklumo laikotarpį. Norėdami sukurti slinkimo prognozę tam tikru momentu Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės, turite turėti bent 3 mėnesių klientų istoriją Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės. Mūsų istorija buvo apribota iki 19 mėnesių, todėl nusprendėme imtis 6 mėnesių neveiklumo laikotarpio, jei įmanoma. O minimaliam kokybiškos prognozės laikotarpiui užtrukome 3 mėnesius. 3 ir 6 mėnesių duomenis paėmėme empiriškai, remdamiesi klientų duomenų elgesio analize.

Mes suformulavome churn apibrėžimą taip: kliento nebuvimo mėnuo Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės tai pirmas mėnuo su ACTIVE_FLAG=0, kai nuo šio mėnesio lauke ACTIVE_FLAG yra mažiausiai šeši nuliai iš eilės, kitaip tariant, mėnuo, nuo kurio klientas buvo neaktyvus 6 mėnesius.

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės
Išvykusių klientų skaičius

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės
Likusių klientų skaičius

Kaip apskaičiuojamas atlygis?

Tokiose varžybose ir apskritai praktikoje nutekėjimas dažnai prognozuojamas taip. Klientas prekes ir paslaugas naudoja skirtingais laikotarpiais, duomenys apie sąveiką su juo pateikiami kaip fiksuoto ilgio n požymių vektorius. Dažniausiai ši informacija apima:

  • Vartotoją charakterizuojantys duomenys (demografiniai duomenys, rinkodaros segmentas).
  • Banko produktų ir paslaugų naudojimo istorija (tai klientų veiksmai, kurie visada yra susieti su konkrečiu mums reikalingo intervalo laiku ar periodu).
  • Išoriniai duomenys, jei buvo įmanoma juos gauti - pavyzdžiui, atsiliepimai iš socialinių tinklų.

Ir po to jie gauna churn apibrėžimą, skirtingą kiekvienai užduočiai. Tada jie naudoja mašininio mokymosi algoritmą, kuris numato kliento pasitraukimo tikimybę Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės remiantis veiksnių vektoriumi Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės. Algoritmui išmokyti naudojama viena iš gerai žinomų sprendimų medžių ansamblių kūrimo schemų, XGBoost, LightGBM, „CatBoost“ arba jų modifikacijas.

Pats algoritmas nėra blogas, tačiau jis turi keletą rimtų trūkumų, kai reikia nuspėti churn.

  • Jis neturi vadinamosios „atminties“. Modelio įvestis yra nurodytas funkcijų skaičius, atitinkantis esamą laiko momentą. Norint išsaugoti informaciją apie parametrų pasikeitimų istoriją, reikia apskaičiuoti specialius požymius, apibūdinančius parametrų pokyčius laikui bėgant, pavyzdžiui, banko operacijų skaičių ar sumą per paskutinius 1,2,3, XNUMX, XNUMX mėnesius. Šis požiūris gali tik iš dalies atspindėti laikinų pokyčių pobūdį.
  • Fiksuotas prognozavimo horizontas. Modelis gali numatyti tik iš anksto nustatytą laiko tarpą, pavyzdžiui, prognozę prieš mėnesį, klientų atsitraukimą. Jei prognozė reikalinga kitokiam laikotarpiui, pavyzdžiui, trims mėnesiams, tuomet reikia iš naujo sudaryti mokymo komplektą ir permokyti naują modelį.

Mūsų požiūris

Iš karto nusprendėme, kad standartinių metodų nenaudosime. Be mūsų, čempionate užsiregistravo dar 497 žmonės, kurių kiekvienas turėjo nemažą patirtį. Taigi bandyti kažką daryti pagal standartinę schemą tokiomis sąlygomis nėra gera mintis.

Ir mes pradėjome spręsti problemas, su kuriomis susiduria dvejetainis klasifikavimo modelis, numatydami klientų pasitraukimo laiko pasiskirstymą. Galima pastebėti panašų požiūrį čia, tai leidžia lanksčiau prognozuoti srauto sumažėjimą ir patikrinti sudėtingesnes hipotezes nei taikant klasikinį metodą. Kaip paskirstymų šeimą, modeliuojančią ištekėjimo laiką, pasirinkome paskirstymą Weibull dėl plataus naudojimo išgyvenamumo analizėje. Į kliento elgesį galima žiūrėti kaip į savotišką išgyvenimą.

Čia pateikiami Weibull tikimybių tankio pasiskirstymo pavyzdžiai, priklausomai nuo parametrų Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės и Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės:

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Tai yra trijų skirtingų klientų pasitraukimo laikui bėgant tikimybės tankio funkcija. Laikas pateikiamas mėnesiais. Kitaip tariant, ši diagrama rodo, kada klientas greičiausiai atsitrauks per ateinančius du mėnesius. Kaip matote, klientas, turintis paskirstymą, turi didesnį potencialą išvykti anksčiau nei klientai, turintys Weibull(2, 0.5) ir Weibull (3,1) skirstiniai.

Rezultatas – modelis, tinkantis kiekvienam klientui
mėnuo numato Weibull skirstinio parametrus, kurie geriausiai atspindi nutekėjimo tikimybės atsiradimą laikui bėgant. Išsamiau:

  • Tikslinės mokymo rinkinio funkcijos yra laikas, likęs iki konkretaus kliento mėnesio pabaigos.
  • Jei klientui nenurodytas atšaukimo rodiklis, darome prielaidą, kad atsitraukimo laikas yra didesnis nei mėnesių skaičius nuo einamojo mėnesio iki mūsų turimos istorijos pabaigos.
  • Naudojamas modelis: pasikartojantis neuroninis tinklas su LSTM sluoksniu.
  • Kaip nuostolių funkciją, mes naudojame neigiamą log-tikimybės funkciją Weibull paskirstymui.

Štai šio metodo pranašumai:

  • Tikimybių skirstymas, be akivaizdžios dvejetainės klasifikacijos galimybės, leidžia lanksčiai numatyti įvairius įvykius, pavyzdžiui, ar klientas per 3 mėnesius nustos naudotis banko paslaugomis. Taip pat, jei reikia, per šį skirstinį galima apskaičiuoti įvairių metrikų vidurkį.
  • LSTM pasikartojantis neuroninis tinklas turi atmintį ir efektyviai naudoja visą turimą istoriją. Kai istorija plečiama ar tobulinama, tikslumas didėja.
  • Metodas gali būti lengvai keičiamas skirstant laiko periodus į mažesnius (pavyzdžiui, dalijant mėnesius į savaites).

Tačiau neužtenka sukurti gerą modelį, reikia tinkamai įvertinti ir jo kokybę.

Kaip buvo vertinama kokybė?

Kaip metriką pasirinkome kėlimo kreivę. Tokiais atvejais jis naudojamas versle dėl aiškios interpretacijos, gerai aprašytas čia и čia. Jei apibūdintumėte šios metrikos reikšmę vienu sakiniu, jis būtų toks: „Kiek kartų algoritmas geriausiai numato pirmąjį Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės% nei atsitiktinai“.

Treniruočių modeliai

Konkurso sąlygose nebuvo nustatyta konkreti kokybės metrika, pagal kurią būtų galima palyginti skirtingus modelius ir metodus. Be to, churn apibrėžimas gali būti skirtingas ir gali priklausyti nuo problemos teiginio, kurį, savo ruožtu, lemia verslo tikslai. Todėl, norėdami suprasti, kuris metodas yra geresnis, apmokėme du modelius:

  1. Dažniausiai naudojamas dvejetainis klasifikavimo metodas, naudojant ansamblio sprendimų medžio mašininio mokymosi algoritmą (LightGBM);
  2. Weibull-LSTM modelis

Testų rinkinį sudarė 500 iš anksto atrinktų klientų, kurių nebuvo mokymo rinkinyje. Hiperparametrai modeliui buvo pasirinkti naudojant kryžminį patvirtinimą, suskirstyti pagal klientą. Kiekvienam modeliui mokyti buvo naudojami tie patys funkcijų rinkiniai.

Dėl to, kad modelis neturi atminties, jam buvo paimtos specialios funkcijos, rodančios vieno mėnesio parametrų pokyčių santykį su vidutine parametrų verte per pastaruosius tris mėnesius. Kas apibūdino verčių kitimo greitį per pastaruosius tris mėnesius. Be to, Random Forest pagrįstas modelis būtų nepalankesnis, palyginti su Weibull-LSTM.

Kodėl LSTM su Weibull paskirstymu yra geresnis nei ansamblio sprendimų medžio metodas

Čia viskas aišku tik keliose nuotraukose.

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės
Klasikinio algoritmo ir Weibull-LSTM kėlimo kreivės palyginimas

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės
Klasikinio algoritmo ir Weibull-LSTM kėlimo kreivės metrikos palyginimas pagal mėnesius

Apskritai LSTM beveik visais atvejais yra pranašesnis už klasikinį algoritmą.

Krypties prognozė

Modelis, pagrįstas pasikartojančiu neuroniniu tinklu su LSTM ląstelėmis su Weibull paskirstymu, gali iš anksto numatyti klientų trūkumą, pavyzdžiui, per ateinančius n mėnesių. Apsvarstykite atvejį, kai n = 3. Šiuo atveju kiekvieną mėnesį neuroninis tinklas turi teisingai nustatyti, ar klientas išeis, pradedant nuo kito mėnesio ir iki n-to mėnesio. Kitaip tariant, turi teisingai nustatyti, ar klientas liks po n mėnesių. Tai galima laikyti prognoze iš anksto: nuspėti momentą, kai klientas tik pradėjo galvoti apie išvykimą.

Palyginkime Weibull-LSTM kėlimo kreivę 1, 2 ir 3 mėnesius prieš ištekėjimą:

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Aukščiau jau rašėme, kad svarbios ir prognozės, daromos kurį laiką neaktyviems klientams. Todėl čia į pavyzdį įtrauksime tokius atvejus, kai išvykęs klientas jau buvo neaktyvus vieną ar du mėnesius, ir patikrinsime, ar Weibull-LSTM tokius atvejus teisingai priskiria prie churn. Kadangi pavyzdyje tokių atvejų buvo, tikimės, kad tinklas juos gerai tvarkys:

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Klientų išlaikymas

Tiesą sakant, tai yra pagrindinis dalykas, kurį galima padaryti, turint informaciją, kad tokie ir tokie klientai ruošiasi nebenaudoti produkto. Kalbant apie modelio, kuris galėtų pasiūlyti kažką naudingo klientams, siekiant juos išlaikyti, kūrimą, to negalima padaryti, jei neturite panašių bandymų, kurie baigtųsi gerai.

Mes tokios istorijos neturėjome, todėl nusprendėme taip.

  1. Kuriame modelį, kuris kiekvienam klientui identifikuoja įdomius produktus.
  2. Kiekvieną mėnesį vykdome klasifikatorių ir nustatome potencialiai paliekančius klientus.
  3. Kai kuriems klientams siūlome prekę pagal modelį iš 1 punkto ir prisimename savo veiksmus.
  4. Po kelių mėnesių žiūrime, kurie iš šių potencialiai paliekančių klientų išvyko, o kurie liko. Taigi sudarome mokymo pavyzdį.
  5. Mes apmokome modelį naudodami istoriją, gautą 4 veiksme.
  6. Pasirinktinai pakartojame procedūrą, 1 veiksmo modelį pakeisdami modeliu, gautu 5 veiksme.

Tokio išlaikymo kokybės testą galima atlikti reguliariai atliekant A/B testavimą – potencialiai išvykstančius klientus skirstome į dvi grupes. Vienam siūlome produktus pagal savo išlaikymo modelį, o kitam nieko nesiūlome. Jau mūsų pavyzdžio 1 punkte nusprendėme parengti modelį, kuris gali būti naudingas.

Norėjome, kad segmentavimas būtų kuo labiau interpretuojamas. Tam pasirinkome keletą lengvai interpretuojamų ypatybių: bendras operacijų skaičius, darbo užmokestis, bendra sąskaitos apyvarta, amžius, lytis. Į ypatybes iš lentelės „Žemėlapiai“ nebuvo atsižvelgta kaip į neinformatyvias, o į 3 lentelės „Sutartys“ ypatybes nebuvo atsižvelgta dėl apdorojimo sudėtingumo, kad būtų išvengta duomenų nutekėjimo tarp patvirtinimo rinkinio ir mokymo rinkinio.

Klasterizavimas buvo atliktas naudojant Gauso mišinio modelius. Akaike informacijos kriterijus leido mums nustatyti 2 optimalus. Pirmasis optimalus atitinka 1 klasterį. Antrasis optimalus, mažiau ryškus, atitinka 80 klasterių. Remdamiesi šiuo rezultatu galime padaryti tokią išvadą: labai sunku suskirstyti duomenis į grupes be a priori pateiktos informacijos. Norint geriau suskirstyti į grupes, jums reikia duomenų, kurie išsamiai apibūdina kiekvieną klientą.

Todėl, siekiant kiekvienam klientui pasiūlyti skirtingą produktą, buvo svarstoma prižiūrimo mokymosi problema. Buvo svarstomi šie produktai: „Terminas indėlis“, „Kredito kortelė“, „Overdraftas“, „Vartojimo paskola“, „Paskola automobiliui“, „Hipoteka“.

Duomenys apėmė dar vieną produkto tipą: „Einamosios sąskaitos“. Tačiau mes to nesvarstėme dėl mažo informacijos turinio. Vartotojams, kurie yra banko klientai, t.y. nenustojo naudoti savo gaminių, buvo sukurtas modelis, numatantis, kuris produktas gali juos sudominti. Logistinė regresija buvo pasirinkta kaip modelis, o pirmųjų 10 procentilių padidėjimo vertė buvo naudojama kaip kokybės vertinimo metrika.

Modelio kokybę galima įvertinti paveikslėlyje.

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės
Produktų rekomendacijų modelio rezultatai klientams

Visas

Šis požiūris atnešė mums pirmąją vietą „AI bankuose“ kategorijoje RAIF-Challenge 2017 AI čempionate.

Kaip mes numatėme birumą, artėdami prie jo kaip prie stichinės nelaimės

Matyt, svarbiausia buvo pažvelgti į problemą mažiau pažįstamu kampu ir naudoti metodą, kuris paprastai naudojamas kitose situacijose.

Nors didžiulis vartotojų nutekėjimas gali būti stichinė nelaimė paslaugoms.

Į šį metodą galima atsižvelgti ne tik bankuose, bet ir bet kurioje kitoje srityje, kur svarbu atsižvelgti į nutekėjimą. Pavyzdžiui, mes naudojome jį norėdami apskaičiuoti savo nutekėjimą - „Rostelecom“ Sibiro ir Sankt Peterburgo filialuose.

Įmonės "Duomenų gavybos laboratorija" "Paieškos portalas "Sputnik"

Šaltinis: www.habr.com

Добавить комментарий