Datawhale AI夏令营笔记-TF-IDF方法
一、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,等等