как значения TFIDF преобразуются - PullRequest
0 голосов
/ 03 марта 2019

Я новичок в НЛП, пожалуйста, уточните, как значения TFIDF преобразуются с помощью fit_transform.

Ниже приведена формула для расчета IDF, отлично работает, log (общее количество документов + 1 / количество появлений терминов+ 1) + 1

EG: значение IDF для термина «This» в документе 1 («это строка» равно 1.91629073

После применения fit_transform значения для всех терминовизменено, какая формула \ логика используется для преобразования

TFID = TF * IDF

EG: значение TFIDF для термина «This» в документе 1 («это строка»)) 0,61366674

Как получено это значение, 0,61366674?

from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd

d = pd.Series(['This is a string','This is another string',
               'TFIDF Computation Calculation','TFIDF is the product of TF and IDF'])


df = pd.DataFrame(d)

tfidf_vectorizer = TfidfVectorizer()

tfidf = tfidf_vectorizer.fit_transform(df[0])


print (tfidf_vectorizer.idf_)

#output
#[1.91629073 1.91629073 1.91629073 1.91629073 1.91629073 1.22314355 1.91629073 
#1.91629073 1.51082562 1.91629073 1.51082562 1.91629073 1.51082562]

##-------------------------------------------------

##how the above values are getting transformed here 

##-------------------------------------------------


print (tfidf.toarray())


#[[0.         0.         0.         0.         0.         0.49681612  0.         
#0.         0.61366674 0.         0.         0.     0.61366674]
# [0.         0.61422608 0.         0.         0.         0.39205255
#  0.         0.         0.4842629  0.         0.         0.  0.4842629 ]
# [0.         0.         0.61761437 0.61761437 0.         0.
#  0.         0.         0.         0.         0.48693426 0.  0.        ]
# [0.37718389 0.         0.         0.         0.37718389 0.24075159
#  0.37718389 0.37718389 0.         0.37718389 0.29737611 0.37718389  0.        ]]

1 Ответ

0 голосов
/ 04 марта 2019

Это нормированные векторы TF-IDF, потому что по умолчанию norm='l2' согласно документации .Таким образом, при выводе tfidf.toarray() каждый элемент на уровне 0 / строка массива представляет документ, а каждый элемент уровня 1 / столбец представляет уникальное слово с суммой квадратов векторных элементов для каждого документа, равной 1, чтоВы можете проверить, напечатав print([sum([word ** 2 for word in doc]) for doc in tfidf.toarray()]).

norm: 'l1', 'l2' или None, необязательно (по умолчанию = 'l2'). Каждая выходная строка будет иметь единичную норму, либо: * 'l2 ': сумма квадратов векторных элементов равна 1. Сходство косинусов между двумя векторами является их точечным произведением, когда применяется норма l2.* 'l1': сумма абсолютных значений векторных элементов равна 1. См. preprocessing.normalize

print(tfidf) #the same values you find in tfidf.toarray() but more readable
output: ([index of document on array lvl 0 / row], [index of unique word on array lvl 1 / column]) normed TF-IDF value
(0, 12) 0.6136667440107333  #1st word in 1st sentence: 'This'
(0, 5)  0.4968161174826459  #'is'
(0, 8)  0.6136667440107333  #'string', see that word 'a' is missing
(1, 12) 0.48426290003607125 #'This'
(1, 5)  0.3920525532545391  #'is'
(1, 8)  0.48426290003607125 #'string'
(1, 1)  0.6142260844216119  #'another'
(2, 10) 0.48693426407352264 #'TFIDF'
(2, 3)  0.6176143709756019  #'Computation'
(2, 2)  0.6176143709756019  #'Calculation'
(3, 5)  0.2407515909314943  #'is'
(3, 10) 0.2973761110467491  #'TFIDF'
(3, 11) 0.37718388973255157 #'the'
(3, 7)  0.37718388973255157 #'product'
(3, 6)  0.37718388973255157 #'of'
(3, 9)  0.37718388973255157 #'TF'
(3, 0)  0.37718388973255157 #'and'
(3, 4)  0.37718388973255157 #'IDF'

Поскольку это нормированные значения TF-IDF, сумма квадратов векторных элементов будет равна 1Например, для первого документа с индексом 0 сумма квадратов векторных элементов будет равна 1: sum([0.6136667440107333 ** 2, 0.4968161174826459 ** 2, 0.6136667440107333 ** 2])

Вы можете отключить это преобразование, установив norm=None.

print(TfidfVectorizer(norm=None).fit_transform(df[0])) #the same values you find in TfidfVectorizer(norm=None).fit_transform(df[0]).toarray(), but more readable
output: ([index of document on array lvl 0 / row], [index of unique word on array lvl 1 / column]) TF-IDF value
(0, 12) 1.5108256237659907 #1st word in 1st sentence: 'This'
(0, 5)  1.2231435513142097 #'is'
(0, 8)  1.5108256237659907 #'string', see that word 'a' is missing
(1, 12) 1.5108256237659907 #'This'
(1, 5)  1.2231435513142097 #'is'
(1, 8)  1.5108256237659907 #'string'
(1, 1)  1.916290731874155  #'another'
(2, 10) 1.5108256237659907 #'TFIDF'
(2, 3)  1.916290731874155  #'Computation'
(2, 2)  1.916290731874155  #'Calculation'
(3, 5)  1.2231435513142097 #'is'
(3, 10) 1.5108256237659907 #'TFIDF'
(3, 11) 1.916290731874155  #'the'
(3, 7)  1.916290731874155  #'product'
(3, 6)  1.916290731874155  #'of'
(3, 9)  1.916290731874155  #'TF'
(3, 0)  1.916290731874155  #'and'
(3, 4)  1.916290731874155  #'IDF'

Поскольку каждое слово в каждом документе встречается только один раз, значения TF-IDF являются значениями IDF каждого слова, умноженного на 1:

tfidf_vectorizer = TfidfVectorizer(norm=None)
tfidf = tfidf_vectorizer.fit_transform(df[0])
print(tfidf_vectorizer.idf_)
output: Smoothed IDF-values
[1.91629073 1.91629073 1.91629073 1.91629073 1.91629073 1.22314355
 1.91629073 1.91629073 1.51082562 1.91629073 1.51082562 1.91629073
 1.51082562]

Надеюсь, приведенное выше полезно для вас.

К сожалению, я не могу воспроизвести преобразование, потому что

Сходство косинусов между двумя векторами является их точечным произведением, когда применяется норма l2.

кажетсядополнительный шаг.Поскольку значения TF-IDF будут зависеть от количества слов в каждом документе, когда вы используете настройку по умолчанию norm='l2', я просто отключил бы эту настройку с помощью norm=None.Я понял, что вы не можете просто выполнить преобразование, используя:

tfidf_norm_calculated = [
    [(word/sum(doc))**0.5 for word in doc]
    for doc in TfidfVectorizer(norm=None).fit_transform(df[0]).toarray()]
print(tfidf_norm_calculated)
print('Sum of squares of vector elements is 1: ', [sum([word**2 for word in doc]) for doc in tfidf_norm_calculated])
print('Compare to:', TfidfVectorizer().fit_transform(df[0]).toarray())
...