RareBot – Souboj umělých inteligencí
Odhalte všechny anomálie v přístupech do sítě

Vše o soutěži RareBot

Výsledky soutěže

Děkujeme všem zúčastněným týmům za nasazení, čas a nápady, které do soutěže vložili. První ročník soutěže RareBot pro Fakultu informatiky Masarykovy univerzity je za námi a přinášíme vám závěrečné výsledky.

Výsledková tabulka
Název týmu F-míra (větší, lepší) Poznámka
None 0.321465 Odevzdáno několik hodin po deadline
Mel Gibson’s Nipples 0.317748 Oficiální vítěz
01_50 0.193476
ukázkový skript 0.157968 hlásí náhodně anomálie o víkendu
L. Indra + M. Křivánek 0.330885 Mimo soutěž (nejsou studenti); čas na predikci přesáhl tolerované limity
M. Křivánek + L. Indra 0.014004 Mimo soutěž (nejsou studenti)
Záznamy z vyhodnocovacího skriptu
  1. None (Jan Karásek)
  2. Mel Gibson´s Nipples (Filip Široký, Josef Šamánek, Patrik Sterčo)
  3. 01_50 (Marek Grác, Ondrej Mulár)
  4. baseline (anomalies on weekends)
  5. mimosoutěžní tým (Ladislav Indra, Martin Křivánek)
  6. mimosoutěžní tým (Martin Křivánek, Ladislav Indra)
Oficiální výsledky
  • Gratulujeme trojici Filip Široký, Josef Šamánek, Patrik Sterčo k prvnímu místu. Tým Mel Gibson’s Nipples vyhrává stipendium ve výši 20 000 Kč sponzorované firmou RaRe Technologies s.r.o.
  • Čestné uznání patří Janu Karáskovi (tým None) za nejlepší výsledek, který však odevzdal několik hodin po deadlinu soutěže.
  • A děkujeme Martinovi Křivánkovi a Ladislavu Indrovi za účast bez nároku na výhru (ani jeden není student FI MU).

RareBot

RareBot je programátorská soutěž, které se mohou zúčastnit 1–4 členné týmy, z nichž aspoň jeden musí být student z FI MUNI.

Soutěž pořádá průmyslový partner FI RaRe Technologies s.r.o. a pro vítězný tým připravil odměnu 20 000 Kč ve formě stipendia.

První ročník je na téma Odhalování podezřelého chování uživatelů.

Při programování umělé inteligence budete pracovat s reálnými daty z průmyslu.

  • Celá soutěž trvá 30 dní od 1. 3. 18:00 do 31. 3. 18:00. Ano, výsledky budou na apríla.
  • Strategie mohou být vytvořeny v následujících jazycích: Python, C, C++, Java (nebo jiném JVM jazyce), JavaScript, PHP, Bash, Ruby.
  • Úkolem je rozpoznat anomálie v chování uživatelů.
  • Strategie, která dovede rozpoznávat co nejvíce anomálií s co nejméně falešnými poplachy (měřeno pomocí F-míry), vyhrává.

Váš program zpracuje logy aktivit uživatelů a vytvoří si model jejich standardního chování. Data (logy aktivit) reprezentují dosavadní poznatky o přístupu zaměstnance k firemním zdrojům. Záznamy jsou anonymizované a vypadají následovně (JSON), je jich ale řádově více:

{"category": "eta", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452093112, "safe_connection": 1, "user": "Ronald"}
{"category": "zeta", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452118847, "safe_connection": 1, "user": "Ronald"}
{"category": "eta", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452118908, "safe_connection": 1, "user": "Susanne"}

Po učící fázi (ve které máte všechna data k dispozici naráz) je vaším úkolem odhalit anomálie (útoky na systém) v nových aktivitách uživatelů (online systém):

  1. Ze stdin čtete nový záznam: {"id": 1, "category": "zeta", "unix_timestamp": 1452118847, "user": "Susanne", ...}
  2. Máte dvě sekundy na výpočty a update vašich interní predikčních modelů.
  3. Když jste připravení na další záznam, napíšete na stdout okn
  4. Čtete další záznam: {"id": 2, "category": "gamma", "unix_timestamp": 1452121141, "user": "Ronald", ...}
  5. Váš model říká, že pokud Ronald přistupuje k datům kategorie gamma, je to na 15 % anomálie (nikdy to nedělá). Updatujete interní model.
  6. Napíšete okn pro další záznam
  7. Čtete další záznam: {"id": 3, "category": "gamma", "unix_timestamp": 1452121142, "user": "Ronald", ...}
  8. Váš model říká, že pokud Ronald opět přistupuje k datům kategorie gamma, je to už na 75 % anomálie. Updatujete model.
  9. Nahlásíte zpětně obě anomálie pomocí jejich id a řeknete si o další záznam: 2n, 3n a okn, nebo zkráceně 2n3nokn
  10. Čtete další záznam…


Novinky

  • 15. 3. Průběžné výsledky:
    • Organizátorský naivní skript: F-míra 0.121366
    • Tým 01_50: F-míra 0.121366
    • Tým None: F-míra 0.007943
  • 13. 3. Ostrá testovací a trénovací data pro první vyhodnocení jsou k dispozici.
  • 27. 2. Finální formát dat: před spuštěním soutěže byl zjednodušen formát dat tak, aby pole, která jsou na sobě závislá, byla sjednocena.

Registrované týmy

  • Mel Gibson´s Nipples (Filip Široký, Josef Šamánek, Patrik Sterčo)
  • 01_50 (Marek Grác, Ondrej Mulár)
  • None (Jan Karásek)

Harmonogram

  • od 22. února 2016 jsou otevřeny registrace týmů: na e-mail jimmy@rare-technologies.com zašlete název týmu, seznam členů (jméno, příjmení, učo).
  • od. 22. února 2016 jsou na adrese https://rare-technologies.com/competitions/rarebot zveřejněna učící a testovací data použitá pro vyhodnocení a ladění.
  • 13. března 2016 nejpozději v 18:00 budou na adrese https://rare-technologies.com/competitions/rarebot zveřejněna první část ostrých dat pro vyhodnocení.
  • posun na 24. března 2016 23:59 pro ukončení registrace
  • do 14. 3. 18:00:00 každý tým vytvoří predikce pro všechna ostrá data a zašle je na mail jimmy@rare-technologies.com
  • během 15. 3. budou k dispozici průběžné výsledky soutěžících týmů
  • do 30. 3. 23:59:59 každý tým odevzdá finální verzi své implementaci umělé inteligence
  • nejpozději od 31. 3. 06:00:00 bude k dispozici ke stažení zbytek ostrých dat pro vyhodnocení
  • do 31. 3. 18:00:00 každý tým vytvoří predikce pro všechna ostrá data a nahraje je do systému
  • během 1. 4. budou vyhlášeny výsledky


Data

Skripty ke stažení (vyžadují Python2.7) a testovací data:

Na následujícím obrázku (doporučujeme otevřít si v novém okně a zvětšit) je vidět aktivita zaměstnanců v grafu. Osa x je čas a osa y je log_10(1 + počet aktivit zaměstnance v časovém okně 30 minut).
Anomálie jsou v grafu znázorněny červenou výplní úseku, ve kterém k anomálii došlo, a současně je pod tímto úsekem červený obdélník.

example_data

Jak vše vyzkoušet:

pokud se váš skript pouští bez parametrů: ./evaluator.py --log short_test.log --script ./example.py
s parametry: ./evaluator.py --log short_test.log --script './example.py -r -f -t -u -l '
na windows: C:\python.exe evaluator.py --log short_test.log --script "C:\python.exe example.py"


Podmínky účasti, etický kodex a registrace

  • Soutěž je určena pro 1 až 4členné týmy.
  • Alespoň jeden ze členů týmů musí být student (včetně doktorandů) Fakulty informatiky Masarykovy univerzity.
  • Jedna osoba může být členem nejvýše jednoho týmu.
  • Registrace probíhá do konce 14. března. Registrace po tomto datu nejsou možné.
  • Není povoleno spolupracovat s jinými týmy ani s lidmi mimo tým. Je zakázáno poskytovat jiným týmům rady, své řešení nebo kódy.
  • Přihlášením se do soutěže účastníci souhlasí s tím, aby jejich kódy a algoritmy byly použity pro vyhodnocení soutěže a po ukončení soutěže veřejně dostupné v archivu soutěže.

Spoléháme na fair play všech účastníků. Řešení, která budou porušovat pravidla, zneužívat chyby v rozhraní, či využívat skuliny v pravidlech, budou ze soutěže vyřazena. Není nijak povoleno manipulovat s vyhodnocovacími skripty.

Pokud si nejste jisti korektností vašeho řešení, ozvěte se nám.

Abyste se registrovali, zašlete na e-mailovou adresu jimmy@rare-technologies.com zprávu s předmětem RareBot ve tvaru:

[a-zA-Z0-9NAZEV_TYMU]+
(jméno příjmení učo/název školy a stupeň studian){1,4}

např.

GreatIntelligence
Petra Pythonová 10014
Adam Java FIT VUT bakalářské studium
Gabriel Scala MFF UK doktorské studium
Jana Manažerová 48235

RaRe Technologies s.r.o. si vyhrazuje právo vyloučit ze soutěže týmy, které se účastní proti duchu fair play, nebo nesplňují podmínky registrace.
Též si vyhrazuje právo soutěž zrušit bez vyhlášení vítězů v případě malého počtu soutěžících.


Pravidla

  • Dělba kořisti
    Tým, jenž dosáhne nejvyššího celkového skóre, získá odměnu 20 000 Kč, která bude vyplacena rovnoměrně rozdělena formou stipendia studentům FI (případná redistribuce je v režii týmu).
    V případě, že by více týmů dosáhlo maximálního skóre, se výhra rovným dílem dělí mezi všechny vítězné týmy.
  • Programovací jazyk
    K implementaci vaší strategie můžete použít jeden či více programovacích jazyků z následujícího seznamu: Python, C, C++, Java, JavaScript, Golang, PHP, Bash, Ruby (ideálně Python).
  • Knihovny třetích stran
    Součástí implementace vaší umělé inteligence mohou být všechny komerčně volně přístupné knihovny třetích stran — nelze tedy použít placený software, ke kterému máte školní licenci, nebo knihovny, které lze zdarma použít pouze pro nekomerční účely. Knihovny vyžadující, aby vzniklý software byl open-source, jsou v pořádku.
  • Spustitelnost vašeho řešení
    Váš kód musí být spustitelný na Ubuntu (nebo Linux Mint) po instalaci prerekvizit. Prerekvizity uveďte jako seznam knihoven k instalaci (apt-get install knihovna1 knihovna2). Pokud nezískáte od nás souhlas, musí být knihovny součástí repozitáře Ubuntu nebo Linux Mint.
    Knihovny třetích stran nahrejte spolu s vaším kódem.
  • Replikovatelnost výsledků, pozor na náhodu
    Pro stejný vstup musí dva běhy vaší strategie vždy vrátit zcela stejný výstup. Tím máme možnost ověřit, že výsledky, které prezentujete, program opravdu vrátil. Pokud využíváte náhodu (přímo nebo v knihovnách), nastavte seed pro generátor náhodných čísel.
  • Vyhodnocení úspěšnosti
    Samotné vyhodnocení vaší strategie provádíte sami pomocí našeho skriptu. Nutnou podmínkou pro vítězství a udělení ceny je, abychom dokázali implementaci otestovat na Linuxu a dosáhli stejných výsledků jako vy pro stejnou kombinaci učících a testovacích dat.
    Je zakázáno jakkoliv editovat nebo zneužívat vyhodnocovací skript. Pokud v něm narazíte na chybu či chování neodpovídající zadání, nahlašte to prosím.
  • Přístup k datům
    Od 1. března máte k dispozici logy aktivit několika skutečných uživatelů (trénovací soubory pro vaše učení a vyhodnocovací skript s testovacími soubory).

    Od 13. března budou ke stažení logy aktivit několika dalších skutečných uživatelů (trénovací soubory pro vaše učení a vyhodnocovací skript s testovacími soubory). Po zpracování druhé části dat nám každý tým zašle výstup svého finálního skriptu na e-mail jako přílohu. V předmětu e-mailu bude název týmu. Půjde o nácvik finálního odevzdávání, navíc získáte přehled, jak se vám daří oproti konkurenci. Zaslání výsledků je povinné a nestihnutí termínu může vést k diskvalifikaci týmu.

    Od 31. března půjde stáhnout finální logy aktivit několika skutečných uživatelů (trénovací soubory pro vaše učení a vyhodnocovací skript s testovacími soubory). Po zpracování finální části dat nahrajte vaše výsledky do systému.

  • Nahrání vašeho kódu, po něm nelze již kód měnit
    Do 31. března musí každý tým nahrát svoji finální implementaci (bude upřesněno, jak a kam). Finální implementace musí zahrnovat všechny soubory kromě učících a testovacích dat a vyhodnocovacího skriptu. Finální implementace pak bez jakékoliv změny bude použita na vyhodnocení vašeho řešení.
  • Provedení vyhodnocení: samoobsluha
    Do 18:00 31. března 2016 každý tým spustí vyhodnocovací skript s použitím své zmražené finální implementace a zašle nám výstup svého finálního skriptu na e-mail jako přílohu. V předmětu e-mailu bude název týmu.
  • Omezené zdroje při úvodním učení
    Učení klasifikátoru pro trénovací soubor nesmí přesáhnout 4 hodiny s použitím jednoho vlákna a max 4 GB RAM v jednu chvíli. Na testování lze použít např. stroje nymfe. Limit je úmyslně nadhodnocený, mějte rezervu.
  • Omezené zdroje při testování (online učení a detekce anomálií)
    Vyhodnocení klasifikátoru pro testovací data nesmí přesáhnout 100 sekund s použitím jednoho vlákna a max 4 GB RAM paměti v jednu chvíli. Na testování lze použít např. stroje nymfe.


Data, rozhraní a formáty

Učící data

Učící data reprezentují dosavadní poznatky o přístupu zaměstnance k firemním zdrojům. Neobsahují anomálie.
Jsou dostupná jako textový soubor, jehož každý řádek odpovídá jedné aktivitě zaměstnance – jeden JSON záznam:

  • Učící data neobsahují informace o anomáliích a anomálie v nich nejsou.
  • Jeden soubor obsahuje informace o více zaměstnancích.
  • Soubor je seřazen od nejstarší události po nejnovější (v případě shody času náhodně).
  • Aktivity zaměstnanců spolu mohou, ale nemusí souviset.

Obsah JSON záznamu (čas je udáván ve tvaru YYYY-MM-DD HH:II:SS):

{
    "id": [0-9]+,  # unikátní ID události
    "category": "(alpha|beta|gamma|delta|epsilon|zeta|eta)",  # klasifikace dat podle kategorie
    "behaviour": "(brown|blue|orange)",  # existují tři základní chování uživatele podle přístupu k datům
    "connection": "[A-Z][a-z ]*[STATE_GROUP ]?-[A-Z][a-z ]*[STATE OR AREA]?-[A-Z][a-z ]*[CITY]?",
    "safe_connection": (1|0),  # 1 ~ připojení k Internetu považujeme za bezpečné, 0 ~ uživatel se připojuje z neautorizované sítě
    "unix_timestamp": "[0-9]+",  # čas události v sekundách
    "user": "[A-Z][a-z]+"  # unikátní jméno uživatele
}

Příklad učících dat:

{"id": 200, "category": "epsilon", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452118312, "safe_connection": 1, "user": "Ronald"}
{"id": 201, "category": "zeta", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452118847, "safe_connection": 1, "user": "Freya"}
{"id": 202, "category": "epsilon", "behaviour": "brown", "connection": null, "unix_timestamp": 1452118842, "safe_connection": 0, "user": "Peter"}
{"id": 203, "category": "gamma", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452118855, "safe_connection": 1, "user": "Alice"}
{"id": 204, "category": "gamma", "behaviour": "brown", "connection": "West Europe-Germany-Munich", "unix_timestamp": 1452547000, "safe_connection": 1, "user": "Ronald"}
{"id": 205, "category": "gamma", "behaviour": "brown", "connection": "West Europe-France-Paris", "unix_timestamp": 1452547058, "safe_connection": 1, "user": "Fred"}
{"id": 206, "category": "gamma", "behaviour": "brown", "connection": "Australia-New South Wales-Sydney", "unix_timestamp": 1452547117, "safe_connection": 0, "user": "Fred"}

category:
Povaha dat, ke kterým uživatel přistupuje v rámci dané události. Relativní (ale i absolutní) četnost jednotlivých hodnot pro daného uživatele může souviset s výkonem jeho práce. Některé kategorie mohou být obecně rozšířenější než jiné.

connection:
Místo připojení se skládá ze tří složek (skupina států/stát, oblast, město). Lokace jsou anonymizované (každý stát je nahrazen jiným státem, oblast jinou oblastí a město jiným městem). Anonymizace nahrazuje jedna ku jedné, tedy pokud jsou dvě připojení z jednoho města, i originální události se připojovaly z jednoho města. Neberte však v potaz skutečné hodnoty, připojení z Ukrajiny je stejně (ne)bezpečné jako připojení z Washingtonu.
Tedy např. Western Europe-France-Paris a Western Europe-Germany-Munich jsou ze stejného státu/skupiny států, ale z jiné oblasti a města.

safe connection:
Informace o tom, zda se jedná o připojení z autorizované sítě (od smluvního partnera, ze zaměstnání) – hodnota 1, či nikoliv – hodnota 0.

Testovací data

Testovací data jsou k dispozici pro vyhodnocovací skript, váš kód k nim nesmí přistupovat. Jediná povolená interakce s testovacími daty
je skrze rozhraní testovacího skriptu.

V testovacích datech jsou jen ti zaměstnanci (pole user), kteří se vyskytli v učících datech. Přestože v testovacích datech jsou anomálie označeny ("is_anomaly": 1), váš skript tuto informaci neobdrží.

API

Vstup skriptu: zpracování testovacích dat
Váš skript čte ze standardního vstupu. Každý načtený řádek může být dvojího typu:

  • Záznam o jedné aktivitě ve formátu JSON jako řetězec s koncem řádku
  • Řetězec exitn značící, že žádný další záznam již nepřijde, a je poslední možnost nahlásit anomálie.

Když se ve standardním vstupu objeví záznam nové události (nemusí být vámi přečten), posune se tím aktuální interní čas vyhodnocovacího skriptu. Aktuální čas je vždy časová známka (unix_timestamp) z předposledního záznamu poslaného vyhodnocovacím skriptem do standardního vstupu.

Pokud vyhodnocovací skript poslal vašemu skriptu tři následující záznamy:

{'id': 1, 'unix_timestamp': 1420139738, ...}  # 2015-01-01 20:15:38
{'id': 2, 'unix_timestamp': 1420179072, ...}  # 2015-01-02 07:11:12
{'id': 3, 'unix_timestamp': 1420182965, ...}  # 2015-01-02 08:16:05

interní čas systému je 1420182965(2015-01-02 07:11:12). Čas tedy není spojitý, ale kopíruje časy logů aktivit.

Standardně se ve standardním vstupu objeví jeden záznam na začátku a pak po každém vašem zápisu na standardní výstup ve tvaru okn. Pokud však více jak dvě sekundy nedáte na standardní výstup okn, přibude do standardního vstupu další záznam, jako byste okn zapsali.

Výstup skriptu
Váš skript píše na standardní výstup (nezapomeňte po každém zápisu zavolat flush, aby výstup nezůstal v mezipaměti):

  • Výstup okn signalizuje, že může přijít další záznam.
  • Výstup okn po obdržení exitn dává svolení k ukončení vyhodnocování.
  • Výstup [0-9]+n nahlásí událost s tímto id jako anomálii. Chcete-li nahlásit anomálii pro událost s id=3, vypíšete id záznamu aktivity jako přirozené číslo s ukončením řádku, v tomto případě tedy 3n. Anomálii musíte nahlásit do hodinu od času, kdy daná událost nastala. Řídíme se interním aktuálním časem ve vyhodnocovacím skriptu. Tj. pokud přečtete ze stdin událost s časovou známkou “T”, máte poslední možnost vypsat na stdout jako anomálii id události s časovou známkou “T – 1h”.

Od vložení záznamu do standardního vstupu do vašeho zapsání okn do standardního výstupu nesmí uběhnout více jak 2 sekundy, jinak se posune interní čítač. Před výpisem okn můžete vypsat libovolně mnoho hlášení anomálií.

Příklad korektní sekvence (> značí vstup, < značí výstup, před symbolem je interní čas):

0000-00-00 00:00:00 > {‘id’: 1, ‘unix_timestamp’: 1420179010, …}
0000-00-00 00:00:00 < ok
2015-01-02 07:10:10 > {‘id’: 2, ‘unix_timestamp’: 1420179072, …}
2015-01-02 07:10:10 < 1
2015-01-02 07:10:10 < 2
2015-01-02 07:10:10 < ok
2015-01-02 07:11:12 > {‘id’: 3, ‘unix_timestamp’: 1420182965, …}
2015-01-02 07:11:12 < ok
2015-01-02 08:16:05 > {‘id’: 4, ‘unix_timestamp’: 1420183103, …}
2015-01-02 08:16:05 < 4
2015-01-02 08:16:05 < ok
2015-01-02 08:18:23 > {‘id’: 5, ‘unix_timestamp’: 1420258621, …}
2015-01-02 08:18:23 < ok
2015-01-02 08:18:23 > exit
2015-01-02 08:18:23 < 5
2015-01-02 08:18:23 < ok

V příkladu výše nahlásíme záznamy 1, 2, 4 a 5 jako anomálie, záznam 2 a 4 hned po zpracování 2 a 4, záznam 1 až po zpracování i 2 a záznam 5 po dočtení vstupu. Lze tedy prohlásit záznam za anomálii i po přečtení dalších záznamů, nesmí však nikdy uběhnout více jak hodina interního času: pokud je na vstupu událost s časem T, je poslední šance hlásit anomálie pro události s časem menším či rovným T – 1 hodina.

Příklady špatných výstupů
Následuje log běhu vyhodnocovacího skriptu (https://github.com/RaRe-Technologies/rarebot/blob/master/evaluator.py) s testovacím algoritmem (https://github.com/RaRe-Technologies/rarebot/blob/master/example.py) a testovacími daty (https://github.com/RaRe-Technologies/rarebot/blob/master/data/short_test.log).

Standardní vstup je značen >, standardní výstup < a popis chyby !. Čas se v logu používá z vyhodnocovacího skriptu:

running ./evaluator.py -s ./example.py -l -f -u -r -t -l data/short_test.log
preparing simulation
0000-00-00 00:00:00 start of simulation
0000-00-00 00:00:00 > {"category": "gamma", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-British Columbia-Niriirsibk", "user": "Venessa", "unix_timestamp": 1442682585, "id": 0}
0000-00-00 00:00:00 < 0
0000-00-00 00:00:00 < ok
2015-09-19 19:09:45 > {"category": "beta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442808578, "id": 1}
2015-09-19 19:09:45 < ok
2015-09-21 06:09:38 > {"category": "beta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442808591, "id": 2}
2015-09-21 06:09:38 < ok
2015-09-21 06:09:51 > {"category": "beta", "behaviour": "download_file", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442808599, "id": 3}
2015-09-21 06:09:51 < 3
2015-09-21 06:09:51 < 3
2015-09-21 06:09:51 ! you have already reported event n. 3
2015-09-21 06:09:51 < ok
2015-09-21 06:09:59 > {"category": "gamma", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Parabcknny", "user": "Venessa", "unix_timestamp": 1442861057, "id": 4}
2015-09-21 06:09:59 < ok
2015-09-21 20:44:17 > {"category": "gamma", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Parabcknny", "user": "Venessa", "unix_timestamp": 1442861058, "id": 5}
2015-09-21 20:44:17 < ok
2015-09-21 20:44:18 > {"category": "gamma", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Parabcknny", "user": "Venessa", "unix_timestamp": 1442861518, "id": 6}
2015-09-21 20:44:18 < ok
2015-09-21 20:51:58 > {"category": "zeta", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Parabcknny", "user": "Venessa", "unix_timestamp": 1442861525, "id": 7}
2015-09-21 20:51:58 < EVENT 0
2015-09-21 20:51:58 ! `EVENT 0` can't be parsed, int is required
2015-09-21 20:51:58 < ok
2015-09-21 20:52:05 > {"category": "gamma", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Parabcknny", "user": "Venessa", "unix_timestamp": 1442864853, "id": 8}
2015-09-21 20:52:05 < ok
2015-09-21 21:47:33 > {"category": "beta", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442867969, "id": 9}
2015-09-21 21:47:33 < ok
2015-09-21 22:39:29 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442871067, "id": 10}
2015-09-21 22:39:29 ! 10: no answer
2015-09-21 23:31:07 > {"category": "beta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442879712, "id": 11}
2015-09-21 23:31:07 < ok
2015-09-22 01:55:12 > {"category": "beta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442879736, "id": 12}
2015-09-22 01:55:12 < ok
2015-09-22 01:55:36 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442880272, "id": 13}
2015-09-22 01:55:36 < 4
2015-09-22 01:55:36 ! late event 4 reporting (event: 2015-09-21 20:44:17, you already read events: 2015-09-22 01:55:36 and 2015-09-22 02:04:32)
2015-09-22 01:55:36 < ok
2015-09-22 02:04:32 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442880372, "id": 14}
2015-09-22 02:04:32 < ok
2015-09-22 02:06:12 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442880775, "id": 15}
2015-09-22 02:06:12 < 17
2015-09-22 02:06:12 ! you are forbidden to predict event 17 that you haven't seen yet
2015-09-22 02:06:12 < ok
2015-09-22 02:12:55 > {"category": "beta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442880966, "id": 16}
2015-09-22 02:12:55 < ok
2015-09-22 02:16:06 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442881015, "id": 17}
2015-09-22 02:16:06 < ok
2015-09-22 02:16:55 > {"category": "beta", "behaviour": "download_file", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442881019, "id": 18}
2015-09-22 02:16:55 < ok
2015-09-22 02:16:59 > {"category": "beta", "behaviour": "download_file", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442881054, "id": 19}
2015-09-22 02:16:59 < ok
2015-09-22 02:17:34 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442881372, "id": 20}
2015-09-22 02:17:34 < ok
2015-09-22 02:22:52 > {"category": "gamma", "behaviour": "download_file", "safe_connection": 0, "connection": null, "user": "Angelica", "unix_timestamp": 1442881399, "id": 21}
2015-09-22 02:22:52 < ok
2015-09-22 02:23:19 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442881479, "id": 22}
2015-09-22 02:23:19 < ok
2015-09-22 02:24:39 > {"category": "zeta", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Denny", "unix_timestamp": 1442881577, "id": 23}
2015-09-22 02:24:39 < ok
2015-09-22 02:26:17 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442881594, "id": 24}
2015-09-22 02:26:17 < ok
2015-09-22 02:26:34 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442881620, "id": 25}
2015-09-22 02:26:34 < 25
2015-09-22 02:26:34 < ok
2015-09-22 02:27:00 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442881646, "id": 26}
2015-09-22 02:27:00 < ok
2015-09-22 02:27:26 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442881666, "id": 27}
2015-09-22 02:27:26 < ok
2015-09-22 02:27:46 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442882624, "id": 28}
2015-09-22 02:27:46 < ok
2015-09-22 02:43:44 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442882627, "id": 29}
2015-09-22 02:43:44 < ok
2015-09-22 02:43:47 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442882633, "id": 30}
2015-09-22 02:43:47 < ok
2015-09-22 02:43:53 > {"category": "zeta", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Denny", "unix_timestamp": 1442882650, "id": 31}
2015-09-22 02:43:53 < ok
2015-09-22 02:44:10 > {"category": "beta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442883433, "id": 32}
2015-09-22 02:44:10 < ok
2015-09-22 02:57:13 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442888827, "id": 33}
2015-09-22 02:57:13 < ok
2015-09-22 04:27:07 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442890115, "id": 34}
2015-09-22 04:27:07 < ok
2015-09-22 04:48:35 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442890725, "id": 35}
2015-09-22 04:48:35 < ok
2015-09-22 04:58:45 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442890761, "id": 36}
2015-09-22 04:58:45 < ok
2015-09-22 04:59:21 > {"category": "zeta", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Denny", "unix_timestamp": 1442891036, "id": 37}
2015-09-22 04:59:21 < ok
2015-09-22 05:03:56 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Eniiseaazc", "user": "Venessa", "unix_timestamp": 1442891594, "id": 38}
2015-09-22 05:03:56 < ok
2015-09-22 05:13:14 > {"category": "beta", "behaviour": "download_file", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Beth", "unix_timestamp": 1442892711, "id": 39}
2015-09-22 05:13:14 < ok
2015-09-22 05:31:51 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Eniiseaazc", "user": "Denny", "unix_timestamp": 1442893914, "id": 40}
2015-09-22 05:31:51 < ok
2015-09-22 05:51:54 > {"category": "epsilon", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Eniiseaazc", "user": "Venessa", "unix_timestamp": 1442895758, "id": 41}
2015-09-22 05:51:54 < ok
2015-09-22 06:22:38 > {"category": "epsilon", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Venessa", "unix_timestamp": 1442896364, "id": 42}
2015-09-22 06:22:38 < ok
2015-09-22 06:32:44 > {"category": "epsilon", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Venessa", "unix_timestamp": 1442896427, "id": 43}
2015-09-22 06:32:44 < ok
2015-09-22 06:33:47 > {"category": "epsilon", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Venessa", "unix_timestamp": 1442897263, "id": 44}
2015-09-22 06:33:47 < ok
2015-09-22 06:47:43 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442954007, "id": 45}
2015-09-22 06:47:43 < ok
2015-09-22 22:33:27 > {"category": "epsilon", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Venessa", "unix_timestamp": 1442957957, "id": 46}
2015-09-22 22:33:27 < ok
2015-09-22 23:39:17 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442958550, "id": 47}
2015-09-22 23:39:17 < ok
2015-09-22 23:49:10 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442958588, "id": 48}
2015-09-22 23:49:10 < ok
2015-09-22 23:49:48 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442958589, "id": 49}
2015-09-22 23:49:48 < ok
2015-09-22 23:49:49 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442958589, "id": 50}
2015-09-22 23:49:49 < ok
2015-09-22 23:49:49 > {"category": "gamma", "behaviour": "brown", "safe_connection": 1, "connection": "Canada-Ontario-Kcpckbsssk", "user": "Angelica", "unix_timestamp": 1442958590, "id": 51}
2015-09-22 23:49:49 < ok
2015-09-22 23:49:50 > {"category": "epsilon", "behaviour": "brown", "safe_connection": 0, "connection": null, "user": "Venessa", "unix_timestamp": 1442960497, "id": 52}
2015-09-22 23:49:50 < ok
2015-09-23 00:21:37 > {"category": "zeta", "behaviour": "brown", "safe_connection": 0, "connection": "Canada-Ontario-Zapnkcncca", "user": "Denny", "unix_timestamp": 1442983223, "id": 53}
2015-09-23 00:21:37 < ok
2015-09-23 00:21:37 last opportunity to report anomalies
2015-09-23 00:21:37 < 53
2015-09-23 00:21:37 end of simulation

Příklad umělé inteligence v jazyce Python
Následuje příklad jednoduchého skriptu, který pracuje se vstupem a výstupem (nepoužívá žádný model naučený na učících datech). Váš program, ať už napsaný v libovolném jazyce, by měl fungovat pod stejným API, byť logika detekce anomálií bude (doufejme) sofistikovanější.

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
import os
import sys
import json
import datetime
import time


date_format = "%Y-%m-%d %H:%M:%S"


def main(
        simulate_late_report=True, simulate_format_error=True, simulate_unseen_error=True,
        simulate_repeted_error=True, simulate_timeout_error=True):
    """
    Read from stdin and write to stdout.
    """
    line_counter = -1
    while True:  # repeat until empty line
        line_counter += 1
        line = sys.stdin.readline()  # read line from stdin (including n character)
        # count your time
        loop_start_time = time.time()

        if not line or line.strip() == 'exit':  # if line is empty or exit string, break loop
            # +----------------------------------------------------+
            # | before the end of script, you can report anomalies |
            # +----------------------------------------------------+
            if line_counter > 1:
                # report last line as anomaly to demonstrate functionality
                sys.stdout.write('%in' % (line_counter - 1))
                sys.stdout.flush()
            # write `okn` for system not to wait for another output
            sys.stdout.write('okn')
            sys.stdout.flush()
            # +----------------------------------------------------+
            # break to end infinite loop
            break

        # convert JSON serialized string to object (Python dict)
        activity_log = json.loads(line)

        # timestamp of event
        timestamp = datetime.datetime.strftime(datetime.datetime.fromtimestamp(
            int(activity_log["unix_timestamp"])), date_format)


        # +----------------------------------------------------+
        # | report this or older events before writing `okn`  |
        # +----------------------------------------------------+
        is_alarm = False
        if timestamp.isoweekday() > 4:
            # alarm for all events on Fri, Sat and Sun
            is_alarm = True
        if timestamp.second == 0:
            # alarm for all events occurring with 0 seconds timestamps
            is_alarm = True
        if is_alarm:
            sys.stdout.write(str(activity_log['id']) + 'n')
            sys.stdout.flush()
        # +----------------------------------------------------+
        # write `okn` to continue loop (only if we didn't exceed time limit)
        if time.time() - loop_start_time < 2:
            sys.stdout.write('okn')
            # don't forget to flush stdout
            sys.stdout.flush()


if __name__ == '__main__':
    main()

Příklad umělé inteligence načítající naučený model uživatelů v jazyce Python:

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
import os
import sys
import json
import datetime
import time
import pickle


date_format = "%Y-%m-%d %H:%M:%S"


def main():
    """Read from stdin and write to stdout using pickled model."""
    with open('trained_model.pickle', 'rb') as handle:
        model = pickle.load(handle)

    while True:  # repeat until exit
        line = sys.stdin.readline()  # read line from stdin (including n character)        
        loop_start_time = time.time()  # count your time

        if not line or line.strip() == 'exit':  # if line is empty or exit string, break loop
            # +----------------------------------------------------+
            # | before the end of script, you can report anomalies |
            # +----------------------------------------------------+            
            for report_id in model.get_final_reports():
                sys.stdout.write(str(report_id) + 'n')
                sys.stdout.flush()
            sys.stdout.write('okn')
            sys.stdout.flush()
            # break to end infinite loop
            break
        activity_log = json.loads(line)
        timestamp = datetime.datetime.strptime(activity_log["unix_timestamp"], date_format)
        model.online_learning(timestamp, activity_log)
        # +----------------------------------------------------+
        # | report this or older events before writing `okn`  |
        # +----------------------------------------------------+
        for report_id in model.get_reports():
            sys.stdout.write(str(report_id) + 'n')
            sys.stdout.flush()        
        # +----------------------------------------------------+
        # write `okn` to continue loop (only if we didn't exceed time limit)
        if time.time() - loop_start_time < 2:
            sys.stdout.write('okn')
            # don't forget to flush stdout
            sys.stdout.flush()


if __name__ == '__main__':
    main()

Požadavky na soubory

Formát odevzdaných souborů

Všechny vaše soubory musí být v jedné složce, která se jmenuje stejně jako váš tým (pouze anglické znaky a čísla, ostatní znaky nahraďte podtržítkem).

Složka musí obsahovat spustitelný soubor train.[extension], který voláním train.extension competition_train.log vytvoří všechna potřebná data pro spuštění následujícího skriptu. Tento soubor může pracovat pouze se souborem competition_train.log, který obsahuje záznamy aktivit.

Složka též musí obsahovat spustitelný soubor test.[extension] takový, aby volání ./evaluator.py --logs competition_test.log --script "./test.extension" proběhlo korektně.

Můžete tedy při učení s train.extension vytvořit pomocné soubory, které pak bude skript test.extension využívat. Nesmíte se však nikdy přistupovat k souboru competition_test.log.

Učení ani testování nesmí použít více jak 4 GB RAM a musí běžet v jednom vlákně. Časový limit na učení z trénovacího souboru je 4 hodiny.

Vyhodnocení: skóre

F-míra
Kvalitu predikce jednoho uživatele definujeme pomocí tzv. F-míry:

F1(user) = 2 × precision × recall / (precision + recall)

Celkové skóre pak je průměrem F-mír pro jednotlivé zaměstnance v logu:
Average(F1(user) for user in all_users)


Kontakt

V případě dotazů k pravidlům, implementaci apod. se můžete ptát na tematickém diskuzním fóru v IS:
https://is.muni.cz/df/rarebot/ (do fóra lze psát i bez univerzitního účtu).
Pokud byste dotazem prozradili důvěrné informace, nikdo by vám na fóru neodpověděl, nebo byste neradi psali na fórum,
obraťte se e-mailem na Honzu Rygla jimmy@rare-technologies.com.

Mnoho zdaru!