【问题标题】:Find top n terms with highest TF-IDF score per class查找每类 TF-IDF 得分最高的前 n 个术语
【发布时间】:2019-11-04 07:02:32
【问题描述】:

假设我在pandas 中有一个包含两列的数据框,类似于以下内容:

    text                                label
0   This restaurant was amazing         Positive
1   The food was served cold            Negative
2   The waiter was a bit rude           Negative
3   I love the view from its balcony    Positive

然后我在这个数据集上使用来自sklearnTfidfVectorizer

就每个班级的 TF-IDF 分数词汇而言,找到前 n 名的最有效方法是什么?

显然,我的实际数据框包含的数据行比上面的 4 行多。

我的帖子的重点是找到适用于任何类似于上述数据帧的代码; 4 行数据帧或 1M 行数据帧。

我认为我的帖子与以下帖子有很大关系:

【问题讨论】:

  • 除非您明确删除 hapaxes,否则根据 TFxIDF 定义,输入文档中的唯一词将获得最高分。如果你有超过几十个单词,“前 3 个”将毫无意义,因为所有前 n 个单词的最高分都相同,而且通常根本不是什么特别好的指标。
  • @tripleee,感谢您的评论。但是,我认为/认为数据框只是一个小样本数据框非常明显。我的实际数据框由大约 100k 的数据行数组成。我的帖子的重点是找到适用于任何此类数据框的代码; 4 行数据帧或 1M 行数据帧。这同样适用于它应该是前 3 名还是前 100 名或其他任何东西。因此,让我们把注意力集中在问题上,即只说明显的言论。
  • 但是(确实,显而易见的)您的问题的答案是“仅在单个样本中出现的任何内容”。一个更有用的问题是例如“哪些令牌在一组中具有高 DF(即低 IDF},而在另一组中没有”但您不是在问这个问题,而且我们无法从您的帖子中猜测这是否真的是您真正想要的。
  • 哈哈@tripleee 我的问题不是一般来说哪个是每节课的前 n 个(就 TF-IDF 分数而言)词汇,因为答案很明显,而且它就是你所说的。我的问题是使用什么代码来有效地找到sklearnTfidfVectorizer 中每个班级的前 n 个(就 TF-IDF 而言)得分词汇。所以我需要代码而不是明显的文本答案。
  • 如果我明白你想要什么,我可能会发布一个答案。这些是希望让您澄清您要完成的任务的 cmets。所以你真的不是在寻找前 3 个最两极分化的术语吗?

标签: python python-3.x scikit-learn tfidfvectorizer


【解决方案1】:

在下面,您可以找到我三年多前为类似目的编写的一段代码。我不确定这是否是你将要做的最有效的方法,但据我记得,它对我有用。

# X: data points
# y: targets (data points` label)
# vectorizer: TFIDF vectorizer created by sklearn
# n: number of features that we want to list for each class
# target_list: the list of all unique labels (for example, in my case I have two labels: 1 and -1 and target_list = [1, -1])
# --------------------------------------------
# splitting X vectors based on target classes
for label in target_list:
    # listing the most important words in each class
    indices = []
    current_dict = {}

    # finding indices the of rows (data points) for the current class
    for i in range(0, len(X.toarray())):
        if y[i] == label:
            indices.append(i)

    # get rows of the current class from tf-idf vectors matrix and calculating the mean of features values
    vectors = np.mean(X[indices, :], axis=0)

    # creating a dictionary of features with their corresponding values
    for i in range(0, X.shape[1]):
        current_dict[X.indices[i]] = vectors.item((0, i))

    # sorting the dictionary based on values
    sorted_dict = sorted(current_dict.items(), key=operator.itemgetter(1), reverse=True)

    # printing the features textual and numeric values
    index = 1
    for element in sorted_dict:
        for key_, value_ in vectorizer.vocabulary_.items():
            if element[0] == value_:
                print(str(index) + "\t" + str(key_) + "\t" + str(element[1]))
                index += 1
                if index == n:
                    break
        else:
            continue
        break

【讨论】:

  • 好的,谢谢(赞成)!这是一个好的开始。我认为其他人可能会想出一个更有效的版本。
【解决方案2】:

以下代码将完成工作(感谢Mariia Havrylovych)。

假设我们有一个输入数据框 df,与您的结构对齐。

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

# override scikit's tfidf-vectorizer in order to return dataframe with feature names as columns
class DenseTfIdf(TfidfVectorizer):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        for k, v in kwargs.items():
            setattr(self, k, v)

    def transform(self, x, y=None) -> pd.DataFrame:
        res = super().transform(x)
        df = pd.DataFrame(res.toarray(), columns=self.get_feature_names())
        return df

    def fit_transform(self, x, y=None) -> pd.DataFrame:
        # run sklearn's fit_transform
        res = super().fit_transform(x, y=y)
        # convert the returned sparse documents-terms matrix into a dataframe to further manipulations
        df = pd.DataFrame(res.toarray(), columns=self.get_feature_names(), index=x.index)
        return df

用法:

# assume texts are stored in column 'text' within a dataframe
texts = df['text']
df_docs_terms_corpus = DenseTfIdf(sublinear_tf=True,
                 max_df=0.5,
                 min_df=2,
                 encoding='ascii',
                 ngram_range=(1, 2),
                 lowercase=True,
                 max_features=1000,
                 stop_words='english'
                ).fit_transform(texts)


# Need to keep alignment of indexes between the original dataframe and the resulted documents-terms dataframe
df_class = df[df["label"] == "Class XX"]
df_docs_terms_class = df_docs_terms_corpus.iloc[df_class.index]
# sum by columns and get the top n keywords
df_docs_terms_class.sum(axis=0).nlargest(n=50)

【讨论】:

    【解决方案3】:
    top_terms = pd.DataFrame(columns = range(1,6))
    
    for i in term_doc_mat.index:
        top_terms.loc[len(top_terms)] = term_doc_mat.loc[i].sort_values(ascending = False)[0:5].index
    
    

    这将为您提供每个文档的前 5 个术语。根据需要进行调整。

    【讨论】:

      猜你喜欢
      • 2016-03-17
      • 2019-11-04
      • 2019-06-09
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 2018-03-23
      相关资源
      最近更新 更多