Klasifikace textu pomocí nástroje fastText

Představte si, že máte jednoduchý web s recepty. Každý návštěvník vašeho webu bude moci přidat svůj recept a vy byste mu rádi doporučili, do kterých kategorií by ho mohl přiřadit. Jakým způsobem to provedeme automaticky? Jedná se o standardní klasifikační úlohu, při které nějaký objekt, v tomto případě text, přiřazujeme do jedné nebo více z N tříd (kategorie receptů).

Tuto úlohu dokážeme s menším či větším úspěchem vyřešit hned několika přístupy. Nabízí se mít například databázi klíčových slov a k nim přiřazenou kategorii. Pokud pak v textu najdeme dané slovo, zkusíme tuto kategorii navrhnout jako kandidáta uživateli. S hledáním významných slov v textu nám pomůže třeba metoda TF-IDF a pokud bychom chtěli tento přístup vylepšit, můžeme každé kategorii, která je přiřazena nějakému slovu, přiřadit pravděpodobnost.

Což na to jít ale trošku chytřeji a využít nějaký z nástrojů strojového učení?

fastText je jednoduchý nástroj pro klasifikaci textu a vektorizaci slov, který je založen na významových vektorech (word embeddings). Významové vektory, jak už toto pojmenování napovídá, v sobě kódují informaci o slovech nebo celých větách. Pro jednoduchost si můžeme vzít jako příklad slovo "skákal". Počítači, narozdíl od člověka, toto slovo nic neřekne, ale pokud bychom měli vektor, ve kterém by jednotlivé dimenze a jejich číselné hodnoty reprezentovaly vlastnosti slova, jako "je sloveso?", "čas", "směr" apod., tak bychom byli schopni slova matematicky zkoumat. Takto vzniklé body v prostoru totiž dokážeme například oddělit nějakou rovinou a tudíž je klasifikovat nebo třeba vypočítat podobnost slov na základě prostorové vzdálenosti jejich vektorové reprezentace.

Příprava trénovacích dat

Příprava trénovacích dat je snadná. Stačí nám vytvořit textový soubor, ve kterém bude každá položka trénovací sady na samostatném řádku ve formátu:

__label__egg Včera jsem si udělal vaječnou omeletu s cibulí a paprikou. Byla to vynikající snídaně.
__label__milk Mám rád cereálie zalité studeným mlékem. Je to skvělý způsob, jak začít den.
__label__butter Na své toustovém chlebu používám vždy kvalitní máslo. Jeho krémová chuť je nepřekonatelná.

fastText očekává, že každý řádek bude začínat identifikátorem kategorie, do které text patří. Tento identifikátor musí začínat prefixem __label__ a těchto "labelů" může být víc za sebou. Pro příklad níže využijeme tato trénovací data.

Učení fastText modelu

fastText se dá spouštět jak z konzole, tak za pomocí python wrapperu. My zkusíme rovnou cestu Pythonu a Jupyter notebooku.

!poetry add fasttext
import fasttext
model = fasttext.train_supervised("recepty.txt")
print(model.labels)

Trénování modelu by mělo být velice rychlé. Na novějším počítači by se mělo jednat v případě tohoto datasetu spíše o milisekundy (prostě fastText 🙂). Po vytištění seznamu model.labels si můžeme zkontrolovat, že model našel a využil všechny anotace, které jsme položkám trénovací sady přiřadili.

💡 Při trénování jakéhokoliv modelu platí, že je důležitá velikost trénovacího datasetu. Čím víc trénovacích dat, tím lépe. V rámci většího množství dat se jednak "ztratí" chybně přiřazené anotace textům, protože jich bude menšina, a zároveň se v takové sadě bude vyskytovat "větší rozmanitost" situací, ve kterých se daná slova a věty mohou nacházet.

Natrénovaný model můžeme snadno exportovat a sdílet:

model.save_model("recepty.bin")

Evaluace fastText modelu

model.predict("Po pečení buchty mažu máslem", k=3)
(('__label__butter', '__label__milk', '__label__beef'),
 array([0.1666922 , 0.16668415, 0.16668031]))

Parametrem k při volání funkce predict jsme si řekli o 3 nejpravděpodobnější kategorie, do kterých text patří. V tomto případě je na prvním místě label butter s pravděpodobností zhruba 17 %, což je sice správně, ale určitě nemůžeme říct, že si je model kdo ví jak jistý. Jedná se o důsledek malé trénovací sady, ve které vypadají texty pro všechny třídy dost podobně. U větší trénovací sady bychom pravděpodobně už nezískali takto rovnoměrné rozdělení. Ještě jednou se tedy sluší připomenout, že na velikosti trénovacího datasetu záleží - čím větší je a čím pečlivěji anotovaná data máme, tím lépe.

Úroveň znalostí
Začátečník