Datawhale AI夏令营笔记-TF-IDF方法

发布于:2025-07-21 ⋅ 阅读:(13) ⋅ 点赞:(0)

一、TF-IDF 的核心作用是什么?

用一句话说:

TF-IDF 把“词语的出现”变成“词语的重要性”

它不是单纯数词频(TF),而是结合了词语的稀有程度(IDF),最终输出一个数值,告诉我们:

  • 这个词 在这篇文本中是否重要

  • 它是否 可以用来区分这篇文档和别的文档


二、为什么 TF-IDF 这样计算很合理?

回顾公式(略简化):

在这里插入图片描述

含义 为什么合理
TF 词在文档中出现频率 出现越多,越有可能是这篇文档的重要内容
IDF 词在整个语料中是否罕见 如果所有文档都有这个词,它就不具区分力

举个具体例子

假设你有 3 条评论:
Doc1: 我 喜欢 看 电影

Doc2: 他 也 喜欢 看 电影

Doc3: 我 不 喜欢 电影

我们想知道这些词在每条评论中有多重要。


第一步:统计词频(TF)

我们先看每篇文档中,每个词出现的次数占比:

Doc1 Doc2 Doc3
1/4 = 0.25 0 1/4 = 0.25
喜欢 1/4 = 0.25 1/5 = 0.2 1/4 = 0.25
1/4 = 0.25 1/5 = 0.2 0
电影 1/4 = 0.25 1/5 = 0.2 1/4 = 0.25
0 1/5 = 0.2 0
0 1/5 = 0.2 0
0 0 1/4 = 0.25

第二步:IDF值

出现在哪些文档 DF IDF值(近似)
电影 Doc1,2,3 3 log(3 / (1+3)) ≈ -0.12 (出现太多,价值低)
喜欢 Doc1,2,3 3 ≈ -0.12
Doc1,2 2 ≈ log(3/3) = 0.0
Doc2 1 ≈ log(3/2) ≈ 0.18
Doc2 1 ≈ 0.18
Doc3 1 ≈ 0.18
Doc1,3 2 ≈ 0.0

第三步:TF × IDF 得到最终值

比如词“他”在 Doc2 中:

  • TF = 1/5 = 0.2

  • IDF ≈ 0.18

  • TF-IDF = 0.2 × 0.18 ≈ 0.036 是一个正数,分数不错,现实意义就是doc2其实就是描述“他”特点的

而“喜欢”在 Doc2 中:

  • TF = 0.2

  • IDF ≈ -0.12(在所有的文档中都很常见)——喜欢这个词,注定无法成为重要的词,在所有里面都出现了

  • TF-IDF ≈ 0.2 × -0.12 = -0.024

举个例子理解这个逻辑

  • 比如:“电影”在几乎每篇评论都出现,那它对区分哪篇评论没啥用 → IDF低
  • 但“退货”这个词只在某些评论出现,那它可能是某个聚类的关键特征 → IDF高
    如果“退货”在这篇评论里出现了多次(TF高)→ 它就非常重要!

三、TF-IDF 的广泛用途

1. 文本分类

你需要把评论分成好评/差评、产品类别、垃圾邮件等,这就需要把每条评论变成“数字向量”。

  • TF-IDF 是一种“表示文本内容”的好方法

  • 它不光保留了“有哪些词”,还体现了“词的重要性”

  • 所以可以用于训练机器学习模型(SVM、LR、XGBoost 等)


2. 文本聚类

像你现在用的 KMeans 聚类:

  • 把每条文本用 TF-IDF 表示成向量

  • 系统自动识别“文本的主题相似性”,将相似的评论聚在一起

  • 通过每一类的“高TF-IDF词”还能反推出主题词


3. 搜索引擎核心算法

TF-IDF 是搜索引擎的雏形!

  • 用户输入关键词,比如“手机续航好”

  • 系统计算每篇文档对这些词的 TF-IDF 值

  • 高 TF-IDF 的文档认为“对这个关键词很相关”

  • 所以可以作为搜索结果排序的核心分值


4. 信息抽取 / 关键词提取

比如你有 1000 条评论,希望自动抽出:

  • 每一类评论的关键词

  • 某个产品的用户最常提的独特词语

就可以直接用:

TfidfVectorizer().fit_transform(text_list)

对每条文本输出最重要的词(高TF-IDF)。


四、Datawhale核心代码(包含注释与讲解版)

#目标:你希望对情感为积极/消极的评论再做一次无监督的主题识别(用 KMeans),并为每条评论打上代表性的“主题标签”。
# 创建一个包含分词和KMeans聚类的pipeline
# 使用jieba分词 + TF-IDF向量化,然后用KMeans将评论分成两个聚类
#ps 1、3应该针对的是积极
kmeans_predictor = make_pipeline(
    TfidfVectorizer(tokenizer=jieba.lcut), KMeans(n_clusters=5)
)

# 对评论数据中,情感标签为1(积极)或3(消极)的文本进行聚类训练(无监督学习,分得更好,但是还没有填写上去)
kmeans_predictor.fit(
    comments_data[comments_data["sentiment_category"].isin([1, 3])]["comment_text"]
)

# 将这些评论分配到两个聚类中,得到每条评论所属的聚类标签(0或1)(之前训好了的结果,获得一下)
kmeans_cluster_label = kmeans_predictor.predict(
    comments_data[comments_data["sentiment_category"].isin([1, 3])]["comment_text"]
)

# 准备提取每个聚类中最具代表性的关键词
kmeans_top_word = []

# 从pipeline中取出TF-IDF向量器和KMeans模型
tfidf_vectorizer = kmeans_predictor.named_steps['tfidfvectorizer']
kmeans_model = kmeans_predictor.named_steps['kmeans']

# 获取TF-IDF的词汇表
feature_names = tfidf_vectorizer.get_feature_names_out()
print("123:",feature_names)

#cluster_centers 是一个形状为 (k, n_features) 的数
cluster_centers = kmeans_model.cluster_centers_ #一个center应该也是一个TF-IDF向量

# 遍历每个聚类,找出该聚类中权重最高的top_n_words个关键词
for i in range(kmeans_model.n_clusters):
    # 对第i个聚类中心向量中的词权重降序排序,得到关键词索引(就是要降序所以权重高的在前面)
    #argsort()对向量里的值进行升序排序,返回“索引顺序”。x = np.array([0.2, 0.9, 0.1])
    #x.argsort()  # ➜ array([2, 0, 1]):表示x[2]<x[0]<x[1]
    top_feature_indices = cluster_centers[i].argsort()[::-1] #::-1就是再进行一次倒序
    # 取前top_n_words个关键词并拼接成字符串
    top_word = ' '.join([feature_names[idx] for idx in top_feature_indices[:top_n_words]])
    # 添加到结果列表中
    kmeans_top_word.append(top_word)

#例如     #kmeans_top_word = [
#     '质量 差 退货',    # 第0类的主题词
#     '客服 慢 处理'     # 第1类的主题词
# ]

    
# 为情感类别为积极(1)或消极(3)的评论,添加一个新列 "positive_cluster_theme"
# 每条评论根据其聚类编号,匹配相应聚类的代表性主题关键词
comments_data.loc[
    comments_data["sentiment_category"].isin([1, 3]), 
    "positive_cluster_theme"
] = [kmeans_top_word[x] for x in kmeans_cluster_label]
#kmeans_cluster_label = [1, 0, 1, 0, 0]
# 第1条评论属于聚类1,第2条属于聚类0,等等


网站公告

今日签到

点亮在社区的每一天
去签到