koodinimi "Uudelleenjärjestäjä"

1. Johdanto

Kvantitatiivisen käyttäjäpalautteen huomioimiseksi kehitetään toista koneoppimismallia "Uudelleenjärjestäjää" joka pohjautuu palautteeseen, ja joka tullaan liittämään nykyisten suosittelijamallien kylkeen. Tausta-ajatuksena on mahdollistaa sen, että ajan myötä pystytään löytämään ja nostamaan esiin ne relevantit palvelut (tiettyyn hakuun liittyen) jotka ei suosittelijamallit (3x10D / tekstisuosittelija) sellaisenaan kykene löytämään. Tämä tapahtuu huomioimalla käyttäjien aikaisemmat interaktiot; tässä tapauksessa mitä suositeltuja palveluita on aikaisemmin klikattu.  

Malliksi valittiin Learning-to-rank - menetelmään perustuvan algoritmin (kts https://en.wikipedia.org/wiki/Learning_to_rank). Menetelmä muistuttaa perinteistä ohjatun oppimisen mallia, esimerkiksi luokittelijaa, jossa opetusdataksi tarvitaan selittäviä taustamuuttujia ja riippuva muuttuja jota mallin on tarkoitus oppia ennustamaan. Merkittävänä erona on se, että opetusdatan luomisessa jokainen suosittelijan palauttama ryhmä tuloksia ryhmitellään erikseen, ja malli pyrkii ennustamaan jokaiselle palvelulle sellaisen arvon, joka johtaa jokaisen ryhmän sisällä uudelleenjärjestämisen jälkeen johtaa toivottuun järjestykseen. Täten myös mallin jokaiselle palvelulle antama arvo ei ole absoluuttisena numerona tärkeä - loppujen lopuksi vain jokaisen kyselyn tulosten uudella järjestyksellä on merkitys.

Malli pyrkii siis oppimaan palveluihin ja kyselyihin pohjautuvista taustamuuttujista klikkeihin johtavat lainalaisuudet, jotta se voi uusia suosituksia nähdessä asettaa palveluille paremmuusarvot ja järjestää nämä uuteen järjestykseen siten että todennäköisimmin klikattavat palvelut näytetään tuloksissa ensimmäisinä.

Huomioitava asia: uudelleenjärjestäjä ajetaan aina suosittelijan jälkeen, käyttäen suosittelijan palauttamia tuloksia pohjana, ja järjestää ne uudelleen. Uusia suosituksia malli ei siis keksi, vaan on riippuvainen sille palautetuista suosituksista.

2. Tekninen toteutus

Algoritmi

Malliksi valittiin monissa käyttökonteksteissa toimivaksi todettu päätöspuupohjainen Xgboost (kts. https://xgboost.readthedocs.io/en/stable/tutorials/model.html). Mallin hyötynä on skaalautuvuus myös hyvin kompleksisiin lainalaisuuksiin, mahdollisuus antaa ennusteen vaikka taustamuuttujissa esiintyy puuttuvia arvoja, sekä että malli soveltuu suoraan käytettäväksi learning-to-rank-menetelmän mukaisella tavalla. Lisäksi m.m. mallin opettamiseen käytettävä palvelujen metadata sisältää paljon tekstiä ja luokkamuuttujia, joiden käyttö kategoriakoodauksen avulla hyötyy päätöspuupohjaisesta struktuurista.

Mallia ajetaan scikit-learn-APIn mukaisesti XGBRanker-luokkaa ja "rank:pairwise"-objektiivifunktiota käyttäen (https://xgboost.readthedocs.io/en/stable/python/python_api.html#xgboost.XGBRanker). Opetusdatan jaossa (60% treeni- ja 40% testidata) pidetään ryhmät ehjänä ja suositukset syötetään mallille ryhmiteltyinä. Kategoriakoodauksessa encoder opetetaan myös treenidatalla overfitin välttämiseksi.

Synteettinen opetusaineisto

Mallia on kehitetty ja sen toimintaa on validoitu huhtikuussa 2022 historiallisilla 3x10D-suosituksilla, joihin on lisätty synteettisiä klikkejä simuloimaan oikeata käyttäytymistä. (kts https://vrk-bitbucket-01.eden.csc.fi/projects/AAI/repos/aurora-ai-data-science/browse/aai-713-klikkipalautteen-testiaineiston-luonti) Tiivistettynä; kahden eri sovelluksen kautta tulleille kyselyille lisättiin satunnaisesti klikkejä siten että yhden sovelluksen suosituksissa klikkejä annettiin palveluille parin PTV:n alapalveluluokan mukaisesti, ja toisen sovelluksen suosituksissa vastaavasti parin eri PTV:n alapalveluluokan mukaisesti.

Taustamuuttujina käytettiin kategoriamuuttujia kutsuvaa sovellusta sekä palvelun alapalveluluokkia, kategoriakoodattuina. Kokeiluissa malli onnistui poimimaan esiin nämä lainalaisuudet, ja toivottu kupla-ajattelu luonnistui siten että yhden sovelluksen kautta klikatuilla palveluilla ilmenevä käyttökonteksti ja intentio ei sekoita toisen sovelluksen vastaavia - ellei datassa sitten esiinny tarpeeksi klikkejä jotka eivät riipu sovelluksesta.

Opetusdatan rivejä on noin 4000, joista 600 olivat klikkejä.

Suorituskyvyn mittari

Mallin suorituskyvyn mittaamiseksi käytettiin NDCG:tä (Normalized Discounted Cumulative Gain, kts https://en.wikipedia.org/wiki/Discounted_cumulative_gain) joka on hakukoneiden kehityksessä yleinen tehokkuutta mittaava arvo. Ensiksi lasketaan ryhmittäin DCG-arvo joka rankaisee kovemmin relevantteja tuloksia jotka näkyvät alempana tuloksissa, ja jaetaan se ideaalisen vastaavan arvon kanssa, jolloin saadaan ryhmittäin NDCG joka on välillä (0 .. 1). Uudelleenjärjestäjän suorituskykyä arvioidaan testidatan NDCG-keskiarvolla.

NDCG-arvoa laskettaessa päätettiin jättää pois harhaanjohtava osa tuloksista ja huomioida pelkästään ryhmät joissa esiintyy riippuvan muuttujan molemmat arvot. T.s. ei huomioida suosituksia joissa palautettiin vain yksi palvelu, eikä suosituksia joissa ei yksikään palvelu saanut klikkiä.

Muita huomioita

Havaittu haittapuoli binäärisen riippuvan muuttujan (targetin) suhteen: kun uudelleenjärjestetään suosituksia pelkästään 0/1-sarakkeen avulla, lopputulos on karkeahko eikä yhtä tarkka kuin jos selitettävä muuttuja olisi kvalitatiivinen ja esimerkiksi asteikolla (0 .. 5). Ehdotetaan kuitenkin että hyväksytään tämä haittapuoli, koska datankeruu on tällä tavalla huomattavasti helpompaa kuin ihmisen tekemä suositusten käsinleimaaminen laajemmalla asteikolla.

Muistin käyttö

Malli sinänsä on kevyt ja vie hyvin vähän muistia. Lisäksi tarvitaan muistiin python-kirjastot xgboost ja scikit-learn, sekä reaaliaikaisten luokkamuuttujien tekemistä varten tarvitaan services.json.

Muut mahdolliset muuttujat (feature engineering)

Muuttujat voivat liittyä pelkästään kyselyyn, pelkästään haettavaan palveluun (metadatat yms), tai yhdistelmään näistä.

  • Muut palvelujen metadatat (ontologiatermit, avainsanat jne)
  • Käyttäjien peukut
  • Käytössä olleet rajaukset
  • Suosittelijan palauttama similariteettiarvo
  • Suosittelijalle lähetetyn aineiston rivimäärä (t.s. miten rajattu kysely oli), mahdollisesti suhteessa aineiston maksimimäärään
  • Kyselystä johdetut tiedot (harkiten, ettei muuttujamäärät paisu). 3x10D-tapauksessa voidaan mahdollisesti käyttää koko kyselyä, 10 saraketta. Tekstisuosittelijalla koko upotuksen mukaanotto ei suositeltavaa.
  • Mahdolliset käyttäjäprofiilin kautta saadut tiedot

3. Kehitysideat

  • (Voidaan lisätä fallback suosittelijan palauttamaan järjestykseen, mikäli uudelleenjärjestäjän erottelukyky (arvojen hajonta) on tietyn kynnyksen alapuolella)
  • Seuraa esiintyykö "click-position bias" - onko hyvin usein ensimmäinen tulos se eniten klikatuin, muttei kuitenkaan se jota käyttäjät hakivat?
  • Voidaanko lisätä satunnaisesti nostettuja palvelusuosituksia mukaan näytettyihin tuloksiin? esimerkiksi, jos annettu limit=5, ja suosittelijalta viedään palautemallille 3*limit=15 suositusta, ja palautemalli uudelleenjärjestää nämä - niin näytetäänkö palautemallin palauttamat parhaat 1-4 ja nro 5 otetaan satunnaisesti lopusta 15kpl ryhmästä? "Melkein hyvin vastaavat" palvelut saattavatkin olla hyviä ehdotuksia, mutteivät koskaan saa klikkejä jos niitä ei näytetä.
  • Voiko seurata yleisiä ja harvinaisia hakuja erikseen? kts https://www.aboutwayfair.com/2018/10/how-we-use-machine-learning-and-natural-language-processing-to-empower-search/ jossa haettu kvalitatiivisista asiakaspalautteista harvinaiset toiveet jotka ei malli havaitse pienestä määrästä johtuen. Sitten ovat koonneet eri kannan näille ja näyttävät sen mallin suosituksia tiettyjen avainsanojen perusteella.
  • Kyselystä johdetut tiedot (harkiten, ettei muuttujamäärät paisu). 3x10D-tapauksessa voidaan mahdollisesti käyttää koko kyselyä, 10 saraketta. Tekstisuosittelijalla koko upotuksen mukaanotto ei suositeltavaa.
  • On todennäköistä että taustamuuttujien luomisessa turvaudutaan lähes täysin kategoriakoodaukseen - piileekö tässä overfit-riski? Onko muita vaihtoehtoja hoitaa luokkamuuttujat?

"Kuntamonistaja": Käsinleimatun 3x10D-aineiston koneellinen laajentaminen

1. Johdanto

Kuntamonistajan tarkoitus on laajentaa suppean käsinleimatun 3x10D-aineiston (noin 180 kunnallisen palvelun leimaa, Turku / Oulu / Mikkeli) koneellisesti käyttäen PTV:n metatietoja hyväksi, jolloin saadaan aineistosta enemmän hyötyä myös muihin kuntiin. Alustavasti jokaiseen maan kuntaan saadaan ainakin yksi palvelu monistettua. Käsinleimatussa aineistossa ei kuitenkaan ole esimerkiksi kaikkia alapalveluluokkia (eikä tietenkään kaikkia PTV:n palvelujen nimiä) eli tämä on rajoittava tekijä. Nykymuodossaan 3x10D-aineistolla monistaja löytää täsmäävän 3x10D-vektorin noin 7800 kunnalliselle palvelulle (yhteensä noin 20000 uniikkia palvelua olemassa marraskuussa 2021).

Kuntamonistaja on riippuvainen PTV:n metatietostruktuurista: palveluiden nimistä, pohjakuvaus-id:stä sekä ontologiatermeistä ja alapalveluluokista. Jatkossa voidaan käyttää samaa logiikkaa monistamaan muitakin kuin 3x10D-leimoja.

2. Tekninen toteutus

Vertauslogiikka käyttää kolmea pääsääntöä:

  1. "Name"-kentän tarkka vertailu
  2. "generalDescriptionid"-kentän tarkka vertailu
  3. Metatietokenttien mätsäys kentillä "ontologyTerm" ja "serviceClass"; ontologiatermit ja alapalveluluokat

Lopullinen 3x10d-vektori yksittäiselle palvelulle on painotettu keskiarvo kaikista säännöistä jotka sille palvelulle täsmäsivät. Tällä hetkellä annetaan suuri painoarvo nimelle sekä pohjakuvaus-id:lle. Mikäli näitä ei löydy, niin käytetään ontologiatermejä ja alapalveluluokkia siten että korkeampi painoarvo annetaan jos palvelu mätsää suuremmalla määrällä ontologiatermejä ja/tai alapalveluluokilla.

PoCin lopputulos on käsinleimattua lähdeaineistoa vastaava Excel-tiedosto, jossa "X"-kirjainten sijasta numeroita välillä [0, 1]. Tämä ladataan S3-bucketiin ja päivitetään data-loader-komponentti käyttämään sitä. Monistustoimenpide on toistaiseksi manuaalinen - myöhemmin se voidaan esimerkiksi rakentaa osaa data-loaderia jolloin saadaan aina edellisen päivän tuoreimman tiedon pohjalta tehdyt monistukset.

3. Iterointi palautteen avulla

2022-03-30 saadun palautteen avulla pystyttiin validoimaan kuntamonistajan toimintaa, sekä lisätä saadut uudet leimat lähdeaineistoon.

Essoten palauttama Excel-aineisto oli ryhmitelty "huomioidaan: kyllä/ehkä/ei".

  • "Ehkä"-ryhmä on epäselvä, eikä huomioida tässä käyttötarkoituksessa toistaiseksi
  • "Ei"-ryhmä on Essoten näkökulmasta ajateltu enemmän poisrajaamiseen, joka ei suoraan hyödytä kuntamonistajaa → ei huomioida tässä käyttötarkoituksessa
  • "Kyllä"-ryhmä sisältää sekä ihan uusia leimoja että "hyväksyttyjä" alkuperäisiä tai kuntamonistajan tuottamia leimoja → lisätään lähdeaineistoon

Ryhmittely:

Yhteensä 238 riviä, joista:

125 riviä joissa ei muutoksia leimoihin
- näistä on 27kpl "HUOMIOIDAANKO = KYLLÄ" -> lisätään lähdeaineistoon

113 riviä eri leimoilla (muutoksia tehty)
- 44 riviä joilla "HUOMIOIDAANKO = EI" -> leimat tyhjennetty, ei käytetä
- 6 riviä joilla "HUOMOIDAANKO = EHKÄ" mutta tyhjää leimaa (ei käytetä)
- 63 riviä joille lisätty leimat -> lisätään lähdeaineistoon

2022-04-06 ajettu kuntamonistaja uudelleen näillä lisäyksillä

  • Tulee noin 300 lisäleimaa verrattuna aikaisempaan
  • Käytetty Essoten "Huomioidaan = Kyllä"-rivejä vertailuun, pysyvätkö miten samanlaisina kun ajettu kuntamonistajan läpi. Laatu ylipäätään hyvä, mutta tietyissä rajatapauksissa pohjakuvaukseen perustuvat monistussäännöt ajaa ontologiatermeihin ja palveluluokkiin perustuviin monistussääntöjen yli ja huonontaa leimojen laatua → vähennetty pohjakuvauksen painotusta.

4. Kehitysideoita

  • Jatkossa kun on tiedossa "hyväksyttyjä" leimoja eri toimijoilta, kuntamonistajan painotusparametrit (ontologiatermit+palveluluokat / nimi / pohjakuvaus) voidaan nähdä hyperparametri-optimointiongelmana. Silloin voidaan ajaa koneellinen optimointi löydetään sopivat kuntamonistajan parametrit jotta minimoidaan ero kuntamonistettujen leimojen ja toimijoiden hyväksyttyjen leimojen välillä.



  • No labels