Frequência do termo × frequência inversa nos documentos: à mão, no scikit-learn, num buscador e onde ele falha
Uma lista de stop words resolve o primeiro problema, para uma língua e só para as palavras que alguém lembrou de listar.
Spärck Jones (1972): um termo que aparece em muitos documentos é um jeito ruim de distinguir documentos, então deve contar menos.
Salton & Buckley (1988), comparando muitos esquemas de peso, fizeram do tf × idf com normalização de comprimento o padrão da recuperação de informação.
\(n\) documentos, dos quais \(\text{df}(t)\) contêm \(t\). Depois, cada linha é dividida pelo seu comprimento (norm='l2').
smooth_idf=True: como se um documento extra contivesse cada palavra uma vez. Nada de divisão por zero.
uma palavra presente em todo documento fica com peso 1, não 0: descontada, não apagada.
"filioque", em 2 posts: idf 9,2
"the", em quase todos: idf 1,18
| cachorro | comeu | do | dorme | gato | peixe | ração | sonha | |
|---|---|---|---|---|---|---|---|---|
| d1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
| d2 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 |
| d3 | 0 | 0 | 0 | 1 | 2 | 0 | 0 | 1 |
as contagens da página de bag-of-words: "O gato comeu o peixe.", "O cachorro comeu a ração do gato.", "Gato dorme, gato sonha."
d1 = "gato comeu peixe", cada palavra uma vez.
| gato | comeu | peixe | |
|---|---|---|---|
| 1. tf × idf | 1 | 1,2877 | 1,6931 |
| 2. comprimento | \(\sqrt{1^2 + 1{,}2877^2 + 1{,}6931^2} = \sqrt{5{,}5249} = 2{,}3505\) | ||
| 3. dividir por ele | 0,4254 | 0,5478 | 0,7203 |
tfidf = TfidfVectorizer() # padrões: smooth_idf=True, norm='l2', sublinear_tf=False
T = tfidf.fit_transform(docs)
cachorro comeu do dorme gato peixe ração sonha
d1 0.0000 0.5478 0.0000 0.0000 0.4254 0.7203 0.0000 0.0000
d2 0.5046 0.3838 0.5046 0.0000 0.2980 0.0000 0.5046 0.0000
d3 0.0000 0.0000 0.0000 0.5427 0.6411 0.0000 0.0000 0.5427
same idf as by hand: True
A linha d1 bate com a conta à mão até a quarta casa decimal. O TfidfVectorizer é o CountVectorizer seguido deste mesmo peso.
| opção | dorme | gato | sonha |
|---|---|---|---|
| padrão | 0,5427 | 0,6411 | 0,5427 |
smooth_idf=False | 0,5864 | 0,5588 | 0,5864 |
sublinear_tf=True | 0,5774 | 0,5774 | 0,5774 |
norm=None | 1,6931 | 2 | 1,6931 |
smooth_idf=False: \(\ln(n/\text{df}) + 1\); as palavras raras recebem \(\ln 3 + 1 = 2{,}0986\) e passam à frente de "gato".sublinear_tf=True: contagem → \(1 + \ln(\text{tf})\); os dois "gato" contam \(1{,}6931\), igual ao idf das raras por coincidência.norm=None: produtos brutos; documentos mais longos têm vetores maiores (importa para a distância euclidiana, não para o cosseno).As linhas do TF-IDF têm comprimento 1, então o cosseno é só o produto escalar delas. d1 e d2 compartilham comeu e gato:
\[ \cos(d_1, d_2) = 0{,}5478 \times 0{,}3838 + 0{,}4254 \times 0{,}2980 = 0{,}2102 + 0{,}1268 = 0{,}337 \]d1 e d3 compartilham só gato: \(0{,}4254 \times 0{,}6411 = 0{,}273\).
d1 d2 d3
d1 1.000 0.516 0.471
d2 0.516 1.000 0.365
d3 0.471 0.365 1.000
d1 d2 d3
d1 1.000 0.337 0.273
d2 0.337 1.000 0.191
d3 0.273 0.191 1.000
Um FAQ de central de ajuda com dez perguntas. A consulta vira vetor com o mesmo vetorizador ajustado e as perguntas são ordenadas pelo cosseno.
| consulta | escore | melhor resultado | palavras usadas |
|---|---|---|---|
| esqueci minha senha | 0,35 | FAQ 0: trocar a senha… | senha |
| erro 0x80004005 | 0,53 | FAQ 9: o erro 0x80004005… | erro, 0x80004005 |
| quero contestar a correção do exame | 0,51 | FAQ 0: trocar a senha… | do |
| onde almoçar no sábado | 0,37 | FAQ 2: segunda via do boleto… | onde |
| perdi a fatura | 0,00 | FAQ 0 (a primeira, por padrão) | — |
quero contestar a correção do exame best score 0.00
onde almoçar no sábado best score 0.00
2.097 posts de quatro newsgroups, reduzidos com uma SVD (decomposição em valores singulares) truncada e desenhados com t-SNE (a cor é o newsgroup). Os 5 vizinhos mais próximos do mesmo newsgroup: contagens 46%, TF-IDF 81% (ao acaso: cerca de 25%).
Cada palavra é um eixo próprio, ortogonal a todas as outras.
| par | cosseno | palavras em comum |
|---|---|---|
| sinônimos: o carro é rápido / o automóvel é veloz | 0,00 | nenhuma |
| ordem: o cachorro mordeu o homem / o homem mordeu o cachorro | 1,00 | cachorro, homem, mordeu |
| dois sentidos: a manga da camisa rasgou / comi uma manga madura | 0,14 | manga |
| mesmo sentido: a manga da camisa rasgou / o punho da blusa descosturou | 0,14 | da |
'o cachorro latiu' non-zeros: 1 {'cachorro': 1.0}
'um felino adormeceu' non-zeros: 0 {}
Uma frase sobre um gato dormindo, ao lado de documentos sobre gatos dormindo, com similaridade 0 com todos eles.
Preveja. No preset aula, desmarque smooth_idf: o idf das palavras raras sobe ou desce? Depois teste o preset sinônimos.