Рассчитать Tf-Idf баллы в пандах?

1

Я хочу рассчитать tf и idf отдельно из приведенных ниже документов. Я использую python и pandas.

import pandas as pd
df = pd.DataFrame({'docId': [1,2,3], 
               'sent': ['This is the first sentence','This is the second sentence', 'This is the third sentence']})

Я хочу рассчитать, используя формулу для Tf-Idf, не используя библиотеку Sklearn.

После токенизации я использовал это для расчета TF:

tf = df.sent.apply(pd.value_counts).fillna(0) 

но это дает мне счет, но мне нужно соотношение (count/total number of words).

Для Idf: df[df['sent'] > 0]/(1 + len(df['sent'])

но, похоже, это не работает. Я хочу, чтобы и Tf, и Idf представляли собой формат серии pandas.

редактировать

для токенизации я использовал df['sent'] = df['sent'].apply(word_tokenize) Я получил idf-баллы как:

tfidf = TfidfVectorizer()
feature_array = tfidf.fit_transform(df['sent'])
d=(dict(zip(tfidf.get_feature_names(), tfidf.idf_)))

Как я могу получить оценки tf отдельно?

  • 0
    Пожалуйста, объясните, как вы токенизированы. Кроме того, вы рассматриваете каждое предложение своим собственным документом?
  • 1
    @ T.Ray проверь мой отредактированный вопрос. Я рассчитал баллы IDF. Все, что я хочу получить за каждое слово токена.
Показать ещё 1 комментарий
Теги:
pandas
python-3.x
tfidfvectorizer
tf-idf

3 ответа

1

Вам нужно будет сделать еще немного работы, чтобы вычислить это.

import numpy as np

df = pd.DataFrame({'docId': [1,2,3], 
               'sent': ['This is the first sentence', 
                        'This is the second sentence',
                        'This is the third sentence']})

# Tokenize and generate count vectors
word_vec = df.sent.apply(str.split).apply(pd.value_counts).fillna(0)

# Compute term frequencies
tf = word_vec.divide(np.sum(word_vec, axis=1), axis=0)

# Compute inverse document frequencies
idf = np.log10(len(tf) / word_vec[word_vec > 0].count()) 

# Compute TF-IDF vectors
tfidf = np.multiply(tf, idf.to_frame().T)

print(tfidf)

    is  the     first  This  sentence    second     third
0  0.0  0.0  0.095424   0.0       0.0  0.000000  0.000000
1  0.0  0.0  0.000000   0.0       0.0  0.095424  0.000000
2  0.0  0.0  0.000000   0.0       0.0  0.000000  0.095424

В зависимости от вашей ситуации вы можете нормализовать:

# L2 (Euclidean) normalization
l2_norm = np.sum(np.sqrt(tfidf), axis=1)

# Normalized TF-IDF vectors
tfidf_norm = (tfidf.T / l2_norm).T

print(tfidf_norm)

    is  the     first  This  sentence    second     third
0  0.0  0.0  0.308908   0.0       0.0  0.000000  0.000000
1  0.0  0.0  0.000000   0.0       0.0  0.308908  0.000000
2  0.0  0.0  0.000000   0.0       0.0  0.000000  0.308908
1

Вот мое решение:

сначала tokenize, для удобства как отдельный столбец:

df['tokens'] = [x.lower().split() for x in df.sent.values] 

затем TF, как вы, но с нормализацией параметра (по техническим причинам вам нужна функция лямбда):

tf = df.tokens.apply(lambda x: pd.Series(x).value_counts(normalize=True)).fillna(0)

затем IDF (по одному на слово в лексике):

idf = pd.Series([np.log10(float(df.shape[0])/len([x for x in df.tokens.values if token in x])) for token in tf.columns])
idf.index = tf.columns

тогда, если вы хотите TFIDF:

tfidf = tf.copy()
for col in tfidf.columns:
    tfidf[col] = tfidf[col]*idf[col]
0

Я думаю, у меня была такая же проблема, как и вы.

Я хотел использовать TfIdfVectorizer, но их определение tf-idf по умолчанию не является стандартным (tf-idf = tf + tf*idf вместо обычного tf-idf = tf*idf)

TF = термин "частота" обычно используется для обозначения счета. Для этого вы можете использовать CountVectorizer() из sklearn. Необходимо лог преобразовать и нормализовать, если необходимо.

Опция с использованием numpy была намного больше времени обработки (> 50 раз медленнее).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню