Tf-idf — metoda liczenia wagi terminów w oparciu o ich częstość w dokumencie (tf, term frequency) oraz ich rozkład w całym korpusie (idf, inverse document frequency). Wagi Tf-idf faworyzują słowa występujące w niewielu dokumentach, ponieważ mają większą siłę dyskryminacyjną.
In [1]:
import pylab
import numpy as np
params = {'legend.fontsize': 'x-large',
'figure.figsize': (15, 5),
'axes.labelsize': 'x-large',
'axes.titlesize':'x-large',
'xtick.labelsize':'x-large',
'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)
x = np.linspace(1, 1000, 100000)
y = np.log(1000/x)
pylab.plot(x, y)
print("Wartość idf w zależności od liczby dokumentów, w których dany termin występuje, dla kolekcji 1000 dokumentów.")
Wartość idf w zależności od liczby dokumentów, w których dany termin występuje, dla kolekcji 1000 dokumentów.
Czym rzadsze wystąpienie terminu w dokumentach, tym wartość idf będzie większa
Wektoryzacja¶
In [2]:
from sklearn.feature_extraction.text import TfidfVectorizer
In [3]:
texts = [
"kot pije mleko",
"kot rozlał mleko i poszedł do dzieci",
"pies i kot bawią się razem",
"dzieci, kot i pies bawią się razem",
"tato rozlał mleko i poszedł do sklepu po kawę",
"tato poszedł po dzieci",
"tato pije kawę"
]
In [4]:
# reprezentacja wektorowa (normalizacja)
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(texts)
for row in X.toarray():
print(["%.3f" % col if col > 0 else '0 ' for col in row])
['0 ', '0 ', '0 ', '0 ', '0.491', '0.566', '0 ', '0.662', '0 ', '0 ', '0 ', '0 ', '0 ', '0 ', '0 '] ['0 ', '0.459', '0.392', '0 ', '0.341', '0.392', '0 ', '0 ', '0 ', '0.392', '0 ', '0.459', '0 ', '0 ', '0 '] ['0.469', '0 ', '0 ', '0 ', '0.348', '0 ', '0.469', '0 ', '0 ', '0 ', '0.469', '0 ', '0.469', '0 ', '0 '] ['0.435', '0 ', '0.372', '0 ', '0.323', '0 ', '0.435', '0 ', '0 ', '0 ', '0.435', '0 ', '0.435', '0 ', '0 '] ['0 ', '0.362', '0 ', '0.362', '0 ', '0.309', '0 ', '0 ', '0.362', '0.309', '0 ', '0.362', '0 ', '0.436', '0.309'] ['0 ', '0 ', '0.478', '0 ', '0 ', '0 ', '0 ', '0 ', '0.560', '0.478', '0 ', '0 ', '0 ', '0 ', '0.478'] ['0 ', '0 ', '0 ', '0.605', '0 ', '0 ', '0 ', '0.605', '0 ', '0 ', '0 ', '0 ', '0 ', '0 ', '0.517']
In [5]:
# wartości idf przypisane do wszystkich terminów (termin "sklepu" ma najwyższa wartość idf, ponieważ wystąpił najmniej razy (1 raz))
for idf, word in sorted(zip(vectorizer.idf_, vectorizer.get_feature_names()), reverse=True):
print("%0.3f %s" % (idf, word))
2.386 sklepu 1.981 się 1.981 rozlał 1.981 razem 1.981 po 1.981 pije 1.981 pies 1.981 kawę 1.981 do 1.981 bawią 1.693 tato 1.693 poszedł 1.693 mleko 1.693 dzieci 1.470 kot
Podobieństwo (TfidfVectorizer)¶
In [6]:
from sklearn.metrics.pairwise import cosine_similarity
In [7]:
sim_matrix = cosine_similarity(X, X)
sim_matrix
Out[7]:
array([[1. , 0.38955224, 0.17092473, 0.15866193, 0.17496919, 0. , 0.40065615], [0.38955224, 1. , 0.11854768, 0.25602938, 0.57489391, 0.37557201, 0. ], [0.17092473, 0.11854768, 1. , 0.92825614, 0. , 0. , 0. ], [0.15866193, 0.25602938, 0.92825614, 1. , 0. , 0.17795049, 0. ], [0.17496919, 0.57489391, 0. , 0. , 1. , 0.49830619, 0.37882224], [0. , 0.37557201, 0. , 0.17795049, 0.49830619, 1. , 0.2474805 ], [0.40065615, 0. , 0. , 0. , 0.37882224, 0.2474805 , 1. ]])
In [8]:
# oblicz, które dokumenty sa do siebie najbardziej podobne
sim_text = zip([sim_matrix[0][n] for n in range(0, len(texts))], texts)
for sim, text in sorted(sim_text, reverse=True):
print(f"{sim:<7.04} {text[:50]}")
1.0 kot pije mleko 0.4007 tato pije kawę 0.3896 kot rozlał mleko i poszedł do dzieci 0.175 tato rozlał mleko i poszedł do sklepu po kawę 0.1709 pies i kot bawią się razem 0.1587 dzieci, kot i pies bawią się razem 0.0 tato poszedł po dzieci
Porównanie z CountVectorizer¶
In [9]:
from sklearn.feature_extraction.text import CountVectorizer
count_vectorizer = CountVectorizer()
count_X = count_vectorizer.fit_transform(texts)
count_sim_matrix = cosine_similarity(count_X, count_X)
count_sim_matrix
Out[9]:
array([[1. , 0.47140452, 0.25819889, 0.23570226, 0.20412415, 0. , 0.33333333], [0.47140452, 1. , 0.18257419, 0.33333333, 0.57735027, 0.40824829, 0. ], [0.25819889, 0.18257419, 1. , 0.91287093, 0. , 0. , 0. ], [0.23570226, 0.33333333, 0.91287093, 1. , 0. , 0.20412415, 0. ], [0.20412415, 0.57735027, 0. , 0. , 1. , 0.53033009, 0.40824829], [0. , 0.40824829, 0. , 0.20412415, 0.53033009, 1. , 0.28867513], [0.33333333, 0. , 0. , 0. , 0.40824829, 0.28867513, 1. ]])
In [10]:
sim_text = zip([count_sim_matrix[0][n] for n in range(0, len(texts))], texts)
for sim, text in sorted(sim_text, reverse=True):
print(f"{sim:<7.04} {text[:50]}")
1.0 kot pije mleko 0.4714 kot rozlał mleko i poszedł do dzieci 0.3333 tato pije kawę 0.2582 pies i kot bawią się razem 0.2357 dzieci, kot i pies bawią się razem 0.2041 tato rozlał mleko i poszedł do sklepu po kawę 0.0 tato poszedł po dzieci