02 · Dane · 4 min czytania · Interaktywne · aktualizacja
Czym jest TF-IDF i jak zamienić tekst na liczby dla modelu?
W skrócie
TF-IDF zamienia tekst na wektor wag słów: słowo jest ważne, gdy często pada w dokumencie, a rzadko w całym zbiorze. Prosty, mocny start dla klasyfikacji.
Co to jest
Worek słów (ang. bag of words) to reprezentacja tekstu jako wektora zliczeń: każda pozycja odpowiada jednemu słowu ze słownika, a wartość mówi, ile razy słowo wystąpiło w dokumencie. Kolejność słów znika — zostaje tylko ich skład. TF-IDF (term frequency – inverse document frequency) to ważenie tych zliczeń: słowo dostaje dużą wagę, gdy często występuje w danym dokumencie (TF), ale rzadko w całym zbiorze dokumentów (IDF).
Pomysł odwrotnej częstości dokumentowej pochodzi od Karen Spärck Jones (1972); TF-IDF stał się standardem wyszukiwania informacji, a w uczeniu maszynowym to wciąż mocny punkt odniesienia dla klasyfikacji tekstów, wykrywania spamu czy grupowania dokumentów.
Intuicja: słowo „na” pojawia się prawie wszędzie, więc nic nie mówi o temacie tekstu. Słowo „kardiomiopatia” pojawia się rzadko — jeśli jest w dokumencie, prawie na pewno mówi, o czym on jest.
Mechanizm — dlaczego tak działa
Model potrzebuje wektorów o stałej długości, a teksty mają różną długość. Worek słów rozwiązuje to, budując słownik wszystkich słów w zbiorze treningowym; każdy dokument staje się wektorem o długości słownika, w większości wypełnionym zerami (macierz rzadka).
Same zliczenia mają wadę: dominują w nich najczęstsze słowa — spójniki, przyimki, zaimki — które występują we wszystkich dokumentach. Częstości słów w języku są skrajnie nierówne (prawo Zipfa), więc kilka słów funkcyjnych zagłusza resztę. IDF to naprawia: idf(t) = log(N / df(t)), gdzie N to liczba dokumentów, a df(t) — liczba dokumentów zawierających słowo t. Słowo obecne wszędzie dostaje wagę bliską zera, słowo rzadkie — dużą. Waga końcowa to tf · idf, a wektor dokumentu normalizuje się do długości 1, by długie teksty nie miały przewagi.
Podobieństwo dokumentów mierzy się wtedy cosinusem kąta między wektorami. Dwa teksty są bliskie, gdy dzielą słowa, i to głównie słowa rzadkie, charakterystyczne.
Ograniczenia: TF-IDF nie zna znaczenia ani kolejności. „Pies ugryzł człowieka” i „człowiek ugryzł psa” mają podobne wektory, a „samochód” i „auto” są dla niego zupełnie różnymi słowami. Częściowo pomagają n-gramy (pary i trójki słów), a w polszczyźnie — lematyzacja, bo „kot”, „kota” i „kotem” to inne tokeny. Zanurzenia słów i modele językowe rozwiązują te problemy, ale TF-IDF z regresją logistyczną bywa zaskakująco trudny do pobicia na małych zbiorach i jest w pełni przejrzysty: wagi da się przeczytać.
Na przykładzie
Trzy krótkie dokumenty: „kot śpi na macie”, „pies śpi na trawie”, „kot goni mysz na trawie”. Słownik ma 8 słów. W domyślnej wersji scikit-learn idf(t) = ln((1 + N) / (1 + df(t))) + 1, więc słowo „na”, obecne we wszystkich trzech dokumentach, dostaje idf = 1,0, słowa obecne w dwóch („kot”, „śpi”, „trawie”) — 1,288, a słowa z jednego dokumentu („macie”, „pies”, „goni”, „mysz”) — 1,693. Po normalizacji w pierwszym dokumencie „macie” waży 0,632, „kot” i „śpi” po 0,48, a „na” tylko 0,373.
Podobieństwo cosinusowe dokumentów 1 i 2 na surowych zliczeniach wynosi 0,5 — połowę tej zgodności daje wspólne „na”. Po ważeniu TF-IDF spada do 0,37: wspólne słowo funkcyjne liczy się mniej, a różniące się słowa treściowe bardziej. W prawdziwym korpusie, gdzie słów funkcyjnych są dziesiątki, efekt jest znacznie silniejszy.
W praktyce
TfidfVectorizerw scikit-learn łączy tokenizację, zliczanie i ważenie;CountVectorizerdaje surowe zliczenia.- Ważne parametry:
ngram_range=(1, 2),min_df(usuwa słowa zbyt rzadkie),max_df(zbyt częste),sublinear_tf=True(log z TF),stop_words. - Wektoryzator dopasowuj tylko na danych treningowych — IDF liczony na teście to wyciek.
- Dobre pary modeli:
LogisticRegression,LinearSVC,MultinomialNB; dobrze radzą sobie z rzadkimi, wysokowymiarowymi wektorami. - Dla polskiego rozważ lematyzację lub n-gramy znakowe (
analyzer='char_wb'), bo fleksja rozbija słowa na wiele tokenów. - Typowy błąd: zamiana macierzy rzadkiej na gęstą (
.toarray()) przy dużym słowniku — zabraknie pamięci.
Najczęstsze pytania
- Czy TF-IDF jest jeszcze potrzebny w erze modeli językowych?
- Tak, jako szybki i interpretowalny punkt odniesienia, w wyszukiwaniu słów kluczowych (np. BM25, jego następca) oraz tam, gdzie danych jest mało, a obliczenia mają być tanie. Często służy też jako jedna z metod w wyszukiwaniu hybrydowym.
- Dlaczego logarytm w IDF?
- Bez logarytmu słowo występujące w jednym dokumencie na milion dostałoby wagę milion razy większą niż słowo obecne wszędzie, co zdominowałoby wszystko. Logarytm spłaszcza tę skalę, zachowując kolejność.
- Czym różni się worek słów od zanurzeń słów?
- W worku słów każde słowo to osobny wymiar i wszystkie słowa są od siebie jednakowo odległe. Zanurzenia przypisują słowom gęste wektory, w których słowa o podobnym znaczeniu leżą blisko siebie.
Źródła
- Spärck Jones K. (1972). „A statistical interpretation of term specificity and its application in retrieval”. Journal of Documentation, 28(1), 11–21.
- Salton G., Buckley C. (1988). „Term-weighting approaches in automatic text retrieval”. Information Processing & Management, 24(5), 513–523.
- Manning C. D., Raghavan P., Schütze H. „Introduction to Information Retrieval”. Cambridge University Press, 2008, rozdz. 6.
- Jurafsky D., Martin J. H. „Speech and Language Processing”, 3rd ed. (wersja robocza), rozdz. „Vector Semantics and Embeddings”.
- Dokumentacja scikit-learn: Text feature extraction, https://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction