Robotas irgi žmogus

Iš pažiūros duomenų analizė yra labai nešališkas ir objektyvus reikalas: paimi krūvą duomenų, perleidi per sudėtingą statistinių algoritmų mėsmalę ir gauni kažkokias įžvalgas. Mūsų produktą labiau mėgsta Marijampolėje, brangesnius produktus moterys perka savaitgaliais, socialiniuose tinkluose sekantys veikėją X skaito portalą Y, bent tris kartus gavę labai didelę mėnesinę sąskaitą yra linkę perbėgti pas konkurentus. Su regresijomis (ar sudėtingesnėmis analizėmis) ginčytis sunku, nes duomenys lyg ir kalba už save. Nebereikia spėlioti ir remtis dažnai mus pavedančia intuicija. Bet algoritmai nėra jau tokie neutralūs: jie klysta visai kaip žmonės, nes jie mokosi iš tų pačių žmonių jiems pateiktų duomenų. Tad aklai pasitikėti algoritmų sprendimais nereikėtų.

Vienas to pavyzdys yra JAV naudojamas algoritmas, sprendžiantis apie nuteisto nusikaltėlio polinkį dar kartą nusikalsti. Neseniai buvo pastebėta, jog šis algoritmas turėjo rasistinių polinkių: jeigu esi juodaodis, jo nuomone, tavo recidyvizmo tikimybė didesnė. Kadangi tokiais algoritmais naudojamasi sprendžiant, kokio dydžio bausmę skirti, juodaodžiai už tokius pat pažeidimus automatiškai baudžiami stipriau nei visiškai toks pats baltasis kaimynas, kuris gyvena beveik identiškomis socialinėmis sąlygomis. Su panašiomis diskriminacinėmis problemomis susiduria ir moterys: algoritmai mano, kad jos turi žymiai mažesnę tikimybę uždirbti aukštesnę algą, todėl net joms net nerodo gerų darbo pasiūlymų. Jei tik keliolika procentų vadovų yra moterys, tai net neverta švaistyti lėšų joms rodant vadovų darbo skelbimus.

Tokią algoritmo klaidą ištaisyti nėra taip paprasta, kaip gali pasirodyti. Net jei įstatymais uždrausi kuriant algoritmą atsižvelgti į žmogaus lytį ar odos spalvą, yra daug kitų su šiais dalykais koreliuojančių faktorių. Jei 82% namų ūkių su nepilnamečiais ir tik vienu suaugusiuoju sudaro vieniša mama su vaikais, tai iš šeimos sudėties nesunku atspėti suaugusiojo lytį. Juodaodžius galima atskirti pagal vardus, o Lietuvos atveju, tautybę tikriausiai nesunku suprasti pagal pavardę. Žmogaus gyvenamosios vietos pašto indeksas irgi labai daug ką pasako.

Dirbtinio intelekto algoritmai yra kaip vaikai, kurie mokydamiesi iš aplinkos pradeda suvokti ryšius tarp kintamųjų. Lygiai taip, kaip svarbu, jog vaikas bendrautų su tinkamais žmonėmis ir augtų ne asocialioje aplinkoje, taip ir algoritmo negalima lengvabūdiškai tiesiog paleisti mokytis į platųjį pasaulį. Tai pernai suprato Microsoft, paleidusi savaime besimokantį Twitterio botą Tay, kuris per kelias valandas iš interneto vartotojų išmoko daug rasistinių frazių ir tapo piktu keikūnu. Net ir akylai prižiūrint dirbtinio intelekto mokymosi procesą, mokymosi pavyzdžių imtis turi gerai atitikti realaus pasaulio proporcijas (o tai nevisada lengva pasiekti). 2015-aisiais Google išleistas atpažįstantis objektus nuotraukose algoritmas sukėlė skandalą, mat juodaodžių nuotraukas klaidingai klasifikuodavo kaip beždžiones: jis mokėsi daugiausiai iš baltųjų nuotraukų. Panašiai, kaip Delfi žino apie automobilius tik tiek, kad jie dažnai patenka į avarijas.

Galų gale net jei ir labai atsargiai suformuosi duomenų imtį algoritmo mokymuisi ir atidžiai prižiūrėsi visą procesą, mūsų visuomenėje yra tam tikrų stereotipų ar šališkumų, kurie atsispindės duomenyse. Jei dirbtinio intelekto algoritmą mokysi naudodamasis 1870-ųjų studentų duomenų baze, tikėtina, jog jis į magistro programą siūlys priimti beveik vien tik vyrus. Jeigu algoritmas išmoksta tavo keistumus ir atsižvelgdamas į tavo iškreiptą pasaulio vaizdą tau siūlo skaityti tik straipsnius apie konspiracijos teorijas, tai tik padidina tavo tikėjimą jomis – algoritmai ne tik kad nepadeda objektyviau suvokti pasaulį, bet vis labiau jį iškreipia. Klaidingi įsitikinimai sustiprinami ir daromos vis didesnės klaidos.

Ar yra išeitis iš šios spiralės? Vargu, ar visiškai įmanoma sukurti idealius algoritmus, nes jie tėra mūsų visuomenės atspindys. Kritinis mąstymas ir skeptiškumas tampa labai svarbiais įrankiais atskiriant tiesą nuo melagingų naujienų, tik šiais hiperaktyviais laikais, kai dėmesį gali sukaupti tik kelioms sekundėms, tai tampa brangu ir nemadinga.

Zylių stebykla

Man patinka vis ką nors naujo išmokti, o mokytis geriausia ką nors darant. Taip visai netyčia užgimė Rube Goldbergiško stiliaus zylių stebėjimo projektas, kuris savyje sujungė norą išsibandyti python kalbos bibliotekas konvoliuciniams neuroniniams tinklams su idėja viską padaryti Amazon AWS debesies infrastruktūroje be jokių dedikuotų serverių vien tik su Lambda funkcijomis. Suprantu, kad tiems, kas su tokiais dalykais nesusiduria tai skamba lygiai tiek pat įdomiai kiek man skambėtų nauja variklio vožtuvo modifikacija paskutiniame BMW modelyje (tikiuosi nesuklydau, kad vožtuvai kažkaip susiję su varikliais, non?), bet trumpai tariant, projektas tapo sudėtingas dėl to, kad norėjosi prie lesyklos atskridusias zyles registruoti automatiškai, o tam vien judesio daviklio neužtenka: kartais dėl didelio vėjo juda pati lesykla, kartais užfiksuojama pravažiuojanti mašina, o kartais vaizdas pasikeičia, nes atidarius balkoną aprasoja stiklas. Taigi, reikėjo sistemą „išmokyti“ nuspręsti, ar kadre šiuo metu yra zylė. Tiesa, pati sudėtingiausia dalis pasirodė esanti zylių atpažinimo funkcijų perkėlimas į debesį: nes juk kam daryti viską įprastai, jeigu galima kuo sudėtingiau. Bet rezultatas mane džiugina: gal ne tiek dėl to, kiek kasdieną priskaičiuoju zylių, o dėl įgytų žinių ir patirties. Apie Amazono debesį ir kaip apeiti jo ribotumus sužinojau tikrai daug.

Keletas detalių tiems, kam jos įdomios: balkone, prie zylių lesyklos, stovi Orange Pi kompiuteris su web kamera, kurioje sukasi motion, o jis veikia kaip judesio daviklis. Atsiradus judesiui, daromos jpg nuotraukos ir siunčiamos į Amazon S3 kibirą, o čia yra trigerinama lambda funkcija, kuri išima iš paveiksliuko jo foną (faktiškai yra paskaičiuojamas skirtumas tarp apdorojamo paveiksliuko ir foninio paveiksliuko, kuriame tikrai nėra zylės). Taip paruoštas ir sumažintas paveikliukas per Amazono SNS servisą atiduodamas kitai lambda funkcijai, kuri perleidžia paruoštą paveiksliuką per ištreniruotą neuroninį tinklą ir išspjauna atsakymą, kiek, jo nuomone, paveiksliuke yra zylių. Šie atsakymai kaupiami SQS eilėje iki tol, kol motion mano, kad judesys baigėsi ir į S3 kibirą įkelia viso judesio vaizdą. Tai trigerina trečią lambda funkciją, kuri paskaičiuoja vidutinį zylių skaičių SQS eilėje, ir, jei jis gana didelis, statinėje svetainėje apie tai padaro naują įrašą. Eilė išvaloma ir viskas prasidės iš naujo tada kai tik bus užfiksuojamas naujas judesys.

Zylių stebėjimo sistema per Amazon debesį

Vilniaus viešojo transporto duomenys

Niekada iki šiol nenaudojau dplyr R paketo, tad norėjau pasižiūrėti, kaip jis veikia (o veikia jis tikrai patogiai!). Kadangi neseniai buvo paviešinti Vilniaus Viešojo Transporto vėlavimų duomenys, tai kaip tik šis duomenų rinkinys pasirodė tinkamas pasižaidimui. Kadangi tai labiau techninis galimybių bandymas, tai didelių įžvalgų ir neieškojau, nors visgi radau, kad privatūs vežėjai vėluoja žymiai rečiau nei VVT, troleibusai yra patikimesni nei autobusai, o savaitgaliais viešasis transportas yra punktualesnis (kuo nereiktų stebėtis – juk eismo mažiau).

Nevėluojančių reisų dalis
Nevėluojančių reisų dalis

Detaliau ir techniškiau, su visu kodu: Notebook: Transportas-vėlavimai

Telefonas žino, kada tu nuėjai miegoti

Iš anksto įspėju: tai techniškas įrašas, kuris bus įdomus tik stiprokai užkietėjusiems duomenų analitikams, kurių negąsdina R ar Ruby. Jei šie dalykai jus nelabai domina, štai trumpa įrašo santrauka: jūsų telefonas gali kaupti daug įdomios informacijos apie jūsų judėjimą, mat jis moka būti ir žingsniamačiu. Tuos duomenis galima išsitraukti ir pribraižyti visokių gudrių grafikų, kurie parodo, kad kažkodėl antradieniais ir ketvirtadieniais jūs keliatės valandą anksčiau nei įprastai, 2015 metų gegužę kelias savaites praleidote kitoje Atlanto pusėje ar bent jau panašioje laiko zonoje, o tų pačių metų rugsėjo pradžioje buvote vakarėlyje, iš kurio grįžote apie 2 valandą ryto.

Išsitraukti duomenis iš iPhone telefono nesudėtinga: keli mygtukų paspaudimai, keletas minučių laukimo, ir sugeneruojamas nemažas XML archyvas. Jame yra ne vien tik nueiti žingsniai ir kilometrai, bet ir visi kiti Health programėlės duomenys: gal ten kada vedėtės savo svorį, gal dar koks Runkeeper ten saugojo bėgimo rezultatus ar panašiai – viskas bus viename archyve. Duomenų nemažokai: per pusantrų metų vien žingsniamačio duomenų buvo virš 130 tūkstančių įrašų. Iki 2015 kovo pabaigos, kai Apple išleido Apple Watch ir atnaujino žingsniamačio programinę įrangą, telefonas per dieną jų sugeneruodavo po kelis tūkstančius eilučių. Vos tik stabteli ir atsiranda naujas įrašas: per paskutinės keturias sekundes nuėjai 3,5 metro. Vėliau jau duomenys užrašinėjami ne tokiu jautrumu, tad duomenų mažiau, ir jie nebe tokie smulkūs (nors suminis nueitų žingsnių/kilometrų kiekis nepakito).

XML su Ruby konvertavau į CSV:

require 'nokogiri'
puts "start,end,source,dist"
doc = File.open('export.xml') { |f| Nokogiri.XML(f) }
doc.xpath("//Record[@type='HKQuantityTypeIdentifierDistanceWalkingRunning']").each do |record|
  puts "#{record['startDate']},#{record['endDate']},#{record['sourceName']},#{record['value']}"
end

Tada su R po nedidelių duomenų pakeitimų (tais atvejais, kai judėjimas tęsiasi per vidurnaktį, reikėjo įrašą išskaidyti į du segmentus: iki vidurnakčio ir po jo) sudėjau visus duomenis ant vieno grafiko. Aišku, kai duomenų eilučių šimtas tūkstančių, tai jis labiau primena baltąjį triukšmą, nors kai kurie dalykai visgi matosi: tarkim, galima matyti, jog 2015 gegužę judėjimo ir ramybės laikas ryškiai pasistūmęs, nes tuo metu buvau už Atlanto.

library(lubridate)
library(ggplot2)
library(data.table)

foo = read.csv("distances.csv")
foo$start_hour = hour(foo$start) + minute(foo$start)/60 + second(foo$start)/3600
foo$end_hour = hour(foo$end) + minute(foo$end)/60 + second(foo$end)/3600

foo_overlap = foo[end_hour < start_hour]
foo_overlap[end_hour < start_hour, start_hour := 0]
foo_overlap[end_hour < start_hour, start := end]
foo$end_hour = ifelse(foo$end_hour < foo$start_hour, 24, foo$end_hour)
foo_awesome = rbind(foo, foo_overlap)

ggplot(foo_awesome) + 
  geom_segment( 
    aes(
      x    = start_hour,
      xend = end_hour,
      y    = as.Date(start),
      yend = as.Date(start)
    ),
    size=0.7) +
  xlab("Paros laikas") + ylab("Data") + 
  scale_x_continuous(breaks=c(0,2,4,6,8,10,12,14,16,18,20,22,24), limits=c(0,24), expand=c(0,0)) + 
  scale_y_date(expand=c(0,0), date_breaks="2 month", date_labels = "%Y %b") + 
  guides(colour=FALSE)
Visi duomenys yra beveik kaip baltas triukšmas
Kai sudedi visus duomenis į vieną grafiką gauni beveik tik triukšmą

Akivaizdu, kad norint pamatyti ką nors gudresnio, reikia duomenis kaip nors pjaustyti ar grupuoti. Parą galima suskaidyti į intervalus po 10 minučių, ir kiekviename šių intervalų pažymėti ar buvo judama ar ne: duomenų kiekis sumažėja ir juos galima žymiai lengviau analizuoti. Grupuojant pagal savaitės dienas grafikas žymiai iškalbingesnis.

Mano aktyvumas pagal savaitės dienas
Mano aktyvumas pagal savaitės dienas: žalia – neaktyvu, kuo raudoniau/balčiau tuo daugiau judėjimo

Čia aiškiai matosi, kad antradieniais ir ketvirtadieniais keliuosi anksčiau, mat nuo 8 ryto einu į baseiną. Darbo dienomis apie 10 valandą būna mažokai judėjimo – tuo metu skaitau elektroninį paštą bei geriu kavą, kaip ir mažiau judėjimo apie 14-15 valandą, kai dirbu produktyviausiai. Savaitgaliais miegu dar ilgiau, o sekmadieniais iš lovos išlipu 9.30. Šeštadienis – aktyviausia diena, o sekmadienio vakaras tingus jau nuo pat 18-19 valandos.

Ką išmokau, būdamas duomenų analitiku

Praėję metai buvo įdomūs tuo, kad beveik visus juos praleidau dirbdamas kiek kitokį, nei man įprastą darbą – ne knaisiojausi po finansinius įmonių modelius, bandydamas suprasti, kas galėtų būti geros bendrovės investicijoms, o analizavau nemažus duomenų kiekius daugiausiai investicijų pritraukusiame lietuviškame startuolyje (ar tai iš vis yra teisingas žodis?) Vinted. Patirtis buvo labai įdomi, juolab, kad visada norėjau padirbėti ne vien su finansiniais modeliais, bet ir pamatyti kaip viskas atrodo iš realaus verslo pusės. O ir duomenų kiekiai Vinted įspūdingi: analizuoti keleto milijonų vartojojų duomenis labai įdomu. Ypač dar ir dėl to, jog Vinted kultūra yra labai stipriai paremta duomenų analize: verslo sprendimams duomenys yra pats svarbiausiais argumentas.

Analizuojant duomenis geriausiai išmokau dvi pamokas: 1) duomenys dažniausiai yra netobuli ir 2) duomenys nebūtinai reiškia tai, ką tu galvoji, kad jie reiškia. Tikriausiai dažnai dirbantys su duomenimis atlaidžiai palinguos galvą ir palaikys mane nepatyrusiu naivuoliu, bet iki realaus darbo su duomenimis niekada nebuvau pagalvojęs, jog didžioji duomenų analitiko darbo dalis yra duomenų paruošimas. Dažniausiai jie būna ne tokiame formate, kaip tau jų reikia, dalies duomenų trūksta, dalį duomenų reikia išsitraukti iš kitų duomenų bazių, dalį duomenų reikia atmesti dėl nepatikimumo, dalis duomenų būna svarais vietoje eurų, o dalis romėniškais skaitmenimis arabiška abėcėle. Tam, kad duomenis būtų galima sušerti kokiams nors modeliui arba patogiai jais naudotis, paskiriama iki 90 (taip, devyniasdešimt!) procentų duomenų analitiko darbo laiko. O aš iki tol galvojau, jog sunkiausia dalis – sugalvoti kaip ką su kuo kaip palyginti ar modeliuoti.

Antra pamoka: duomenys dažnai reiškia visai ne tai, ką tu galvoji, kad jie reiškia. Kažkurią savaitę krito vartotojų aktyvumas? Gal kaltos moksleivių atostogos, gal itin geras oras, o gal Vokietijoje prastėja ekonominė situacija. Gali būti, jog kažkas pakito svetainėje ir žmonės nebenori taip dažnai joje lankytis. Prielaidų gali būti labai įvairių, ir vien žiūrėdamas į plikus duomenis ne visada ką nors protingo išpeši. Visai gali būti, jog tiesiog tą savaitę buvo įvelta kokia nors klaida programiniame kode ir dalis duomenų buvo tiesiog prarasta – o to negalėtum atspėti, jeigu nepasiklaustum draugiškų programuotojų. Trumpai tariant: vien duomenų analizė kartais irgi būna bejėgė, reikia labai gerai žinoti visą kontekstą, kad galėtum suprasti, ką tie duomenys tau gali papasakoti.

Kita vertus, jeigu analitikai įdeda daug kruopštaus darbo į duomenų valymą, jų rinkimą ir gali būti tikri jų patikimumu, jeigu tikrai gerai išmano, ką tie duomenys gali reikšti, analizė gali papasakoti daug labai įdomių dalykų: nuo to, kuo skiriasi skirtingų vartotojų segmentų elgsena iki to, kaip vartotojus veikia vienas ar kitas tavo produkto pakeitimas. Kas smagiausia, jog turint daug vartotojų, visa tai galima stebėti ir daryti išvadas kone realiu laiku, o tai reiškia, jog galima operatyviai reaguoti ir daryti savo produkto korekcijas. Lyginant su ketvirtinėmis finansinėmis ataskaitomybėmis ar mėnesinėmis/savaitinėmis pardavimų ataskaitomis tai kosminis šviesos greitis. Tik visgi galioja tie esminiai „jeigu“: be kruopštaus darbo ir gero suvokimo pliki dideli duomenys savaime stogą nunešančių įžvalgų neatneš. Big data is hard, ok?.

Ar veikia slankieji vidurkiai? Bandymas pasiknaisioti su programavimo kalba R

Įspėjimas: tai labai techniškas ir programiškas dienoraščio įrašas, toks, kokio jau nebuvo gerus septynetą metų. Bet net ir programuotojams jo vertė ribota, nes dar tik mokausi susigyventi su programavimo kalba R, bet jau jaučiu, kad mano programavimo įgūdžiai ganėtinai atšipę ir užrūdiję. Jeigu ir toliau esate pasiryžę imti ir gaišti laiką skaitant ką prirašiau, nesiskųskite, jog nebuvote įspėti.

Skaitykite toliau

CNN: Lietuviai turi daugiausiai laisvų dienų pasaulyje

Nežinau, kaip čia tiksliai CNN paskaičiavo, bet jie teigia, jog lietuviai ir brazilai turi daugiausiai laisvų dienų pasaulyje. Jei brazilai man iš tiesų asocijuojasi su saule, samba ir gyvenimu per daug sau nesukant galvos, tai lietuviai šioje kompanijoje gana sunkiai pritampa. Matyt čia tų laisvadienių Lietuvoje tiek daug dėl jau nebegaliojančio įstatymo, kuriuo būdavo perkėlinėjamos savaitgalį išpuolančios šventės į kitas darbo dienas. Visgi, mano nuomone, šis faktas apie lietuvių „darbštumą“ iškalbingas: kai tiek daug atostogaujama, vertė nekuriama – lietuvių darbo produktyvumas yra vienas mažiausių Europos Sąjungoje.

Įdomu, kaip darbo produktyvumo statistika pasikeis po šios krizės: ar ko nors išmoksime? Euforiško ekonomikos augimo metu buvome pratę kasmet iš darbdavio reikalauti vis daugiau, nors abejotina, ar mūsų sukuriama pridėtinė vertė augo proporcingai mūsų reikalavimams. Darbdaviui nebuvo kur dėtis: naujos darbo jėgos neprisišauksi, nes jos trūko. Dabar lazda apsisuko kitu galu, bet, kaip prieš beveik metus rašė buvęs kolega Algimantas Variakojis, vis dar atrodo, lyg krizės nėra. O gal pokyčiai jau matomi?

PHP programuotojų susitikimas

Vakar dalyvavau PHP prijaučiančių susibėgime. Sakau, jog prijaučiančių, nes tarp programuotojų šmėstelėjo keletas merginų, o ir šiaip nemažai senųjų PHP programuotojų užsiima jau visai kitais reikalais, nelabai susijusiais su PHP ir netgi programavimu. Kalbų buvo nemažai – geru žodžiu neminėjom smartweb, taipogi pakeiksnojom PHP vystymą (dėl to, kad ištaisytos klaidos PHP5 nebackportinamos į PHP4, o kartu ir dėl to, jog vystymą kontroliuoja Zend‘as). Buvo sugalvota idėja duoti visiems pasukti smegenis ir pabandyti optimizuoti vieną SQL užklausą, ties kuria ABLomas jau ilgokai užstrigęs.

Vėliau, jau likus tik kokiai dešimčiai žmonių, buvo kalbama apie tai, jog reikėtų bendros svetainės, kurioje butų galima dėti visus programuotojų nusiskundimus savo darbdaviais – šiek tiek specializuotas skundai.lt variantas, labiau orientuotas į freelancer‘ius programuotojus ir dizainerius. Ši idėja kilo, nes kolegos programuotojai buvo pasibaisėję Gauminos darbo sąlygomis. Be to, diskutavome ir apie tai, kokia yra Lietuvoje teisinė situacija su turinio cenzūra: t.y. ką daryti, jeigu kas nors yra nepatenkintas svetainės turiniu ir reikalauja jį pakeisti grasindamas teisinėmis priemonėmis. Nesu tikras, bet mano nuomonė visgi ta, jog tokie reikalavimai dažniausiai būna tušti, nebent yra pažeidžiamos autorinės teisės ar panašiai. Nuomonės skleidimas juk neturėtų būti cenzūruojamas.

Vėliau persikėlėme į Mano klubą, kur žaidėme Jenga, ragavau sambuko, ir galų gale išsiskirstėm namo. Vienas keisčiausių nutikimų — visos sąskaitos buvo sumokėtos, pinigų joms nepritrūko, kaip tik atvirkščiai, jų buvo per daug.

Nuotraukas įdėsiu šiek tiek vėliau. Apie susitikimą dar rašo ir scooox.

Kokia jūsų didžiausia programavimo klaida?

Andy Lester, vienas iš pasaulinio lygio Perl programuotojų užduoda klausimą „kokia buvo tavo didžiausia su programavimu ar sistemų administravimu susijusi klaida?“ ir svarbiausia, ko ji tavęs išmokė? Nors jau pats nebeužsiimu programavimais ir administravimais, bet vis dar pamenu vieną pamoką, kurią išmokau kažką ne taip pakeitęs serverio konfigūracijoje: po to teko praleisti vos ne pusę nakties atstatinėjant duomenis ir taisant klaidą. Dabar prieš lendant prie serverio ar tvarkant kokį nors seniai matytą kodą visada užduodu sau klausimą, kas bus, jeigu mano pertvarkymai ką nors sugadins – ar turiu atsargines duomenų kopijas, ar sugebėsiu jas greitai ir efektyviai atstatyti ir ar iš viso esu įsitikinęs, jog žinau ką darau. Kartais šias pamokas galima pritaikyti ir ne vien programavime, bet ir kitose gyvenimo srityse :)