1. 什么是 TF-IDF? #
- TF-IDF TF-IDF(Term Frequency-Inverse Document Frequency,词频-逆文档频率)是信息检索和文本挖掘中常用的加权技术,用于评估一个词语在文档集中的重要性。
1.1 简单理解 #
想象你在图书馆找关于"机器学习"的书:
- TF(词频):某本书中"机器学习"这个词出现得越多,这本书可能越相关
- IDF(逆文档频率):如果"机器学习"这个词只在少数几本书中出现,说明它很有区分度;如果每本书都有这个词,说明它很普通,区分度低
- TF-IDF:综合考虑这两个因素,找出真正重要的词
TF-IDF 的核心思想:一个词在一篇文档中出现的频率高(TF 高),但在整个文档集合中出现的频率低(IDF 高),则这个词具有很好的区分能力,适合作为关键词。
1.2 为什么需要 TF-IDF? #
在文本处理中,我们需要:
- 找出重要词汇:哪些词最能代表文档的内容?
- 过滤常见词:像"的"、"是"、"在"这样的词虽然出现频繁,但对区分文档没有帮助
- 量化词语重要性:给每个词一个数值,表示它的重要性
TF-IDF 就是解决这些问题的经典方法。
1.3 应用场景 #
TF-IDF 广泛应用于:
- 搜索引擎:计算查询词与文档的相关性
- 文本相似度:将文档转为 TF-IDF 向量,用余弦相似度比较
- 关键词提取:选取 TF-IDF 值最高的词作为关键词
- 文档分类/聚类:作为特征输入机器学习模型
- 自动摘要:识别文档中的重要句子
2. 前置知识 #
在学习 TF-IDF 之前,我们需要了解一些基础概念:
2.1 词频(Term Frequency, TF) #
词频是指一个词在文档中出现的次数。
示例:
- 文档:"我喜欢机器学习,机器学习很有趣"
- "机器学习"出现 2 次,TF("机器学习") = 2
- "我"出现 1 次,TF("我") = 1
直觉:一个词在文档中出现次数越多,该文档可能与该词越相关。
2.2 文档频率(Document Frequency, DF) #
文档频率是指包含某个词的文档数量。
示例:
- 文档集合中有 100 篇文档
- 其中 5 篇包含"机器学习",则 DF("机器学习") = 5
- 其中 80 篇包含"的",则 DF("的") = 80
直觉:一个词在越少的文档中出现,它越能区分文档(如"机器学习"比"的"更有区分度)。
2.3 逆文档频率(Inverse Document Frequency, IDF) #
逆文档频率是文档频率的倒数,用于衡量词的稀有程度。
公式: $$ \text{IDF}(词) = \log\left(\frac{\text{总文档数}}{\text{包含该词的文档数}}\right) $$
示例:
- 总文档数 = 100
- DF("机器学习") = 5,则 IDF("机器学习") = log(100/5) = log(20) ≈ 3.0
- DF("的") = 80,则 IDF("的") = log(100/80) = log(1.25) ≈ 0.22
直觉:IDF 越大,表示词越稀有,越能区分文档。
2.4 对数(Logarithm) #
对数是数学中的一种运算,用于处理大数值的缩放。
常用对数:
- log(10) = 1
- log(100) = 2
- log(1000) = 3
- log(1) = 0
为什么使用对数?
- 压缩数值范围:避免 IDF 值过大
- 符合信息论:信息量与对数成正比
Python 中的对数:
import math
math.log(10) # 自然对数(以 e 为底)
math.log10(10) # 常用对数(以 10 为底)2.5 词袋模型(Bag of Words) #
词袋模型是一种文本表示方法,将文档看作词的集合,忽略词序和语法。
示例:
- 文档 1:"我喜欢机器学习"
- 文档 2:"机器学习很有趣"
词袋表示:
- 文档 1:{"我": 1, "喜欢": 1, "机器学习": 1}
- 文档 2:{"机器学习": 1, "很": 1, "有趣": 1}
特点:
- 简单有效
- 忽略词序("我喜欢"和"喜欢我"被视为相同)
- 忽略语法结构
2.6 Python 基础知识 #
需要了解:
- 列表(list):用于存储文档和词
- 字典(dict):用于存储词频、文档频率等统计信息
- 字符串操作:分词、计数等
- 数学函数:
log()(对数函数)、sum()(求和)
3. TF-IDF 的核心思想 #
TF-IDF 的核心思想是:一个词在文档中出现的次数越多,同时在整个文档集合中出现的次数越少,则该词对于该文档的重要性越高。
3.1 TF(词频)的作用 #
TF 衡量词在单篇文档中的重要性:
- TF 高:词在文档中出现频繁,可能很重要
- TF 低:词在文档中出现很少,可能不重要
示例:
- 文档 A:"机器学习是人工智能的重要分支,机器学习应用广泛"
- "机器学习"出现 2 次,TF 高,说明文档 A 与"机器学习"相关
3.2 IDF(逆文档频率)的作用 #
IDF 衡量词在整个文档集合中的稀有程度:
- IDF 高:词只在少数文档中出现,区分能力强
- IDF 低:词在很多文档中出现,区分能力弱
示例:
- "机器学习"只在 5% 的文档中出现,IDF 高,是很好的关键词
- "的"在 95% 的文档中出现,IDF 低,不是好的关键词
3.3 TF-IDF 的组合 #
TF-IDF = TF × IDF
组合效果:
- TF 高 + IDF 高:完美关键词(如文档特有的专业术语)
- TF 高 + IDF 低:常见但无区分度(如"的"、"是")
- TF 低 + IDF 高:稀有但不重要(如拼写错误)
- TF 低 + IDF 低:完全不重要
4.TF-IDF 的计算公式 #
4.1 TF(词频)的计算 #
TF 有多种计算方法,最常用的是标准化频率:
$$ \text{TF}(t, d) = \frac{\text{词 t 在文档 d 中出现的次数}}{\text{文档 d 的总词数}} $$
其他方法:
- 原始计数:
TF(t,d) = 词 t 在文档 d 中出现的次数 - 对数缩放:
TF(t,d) = log(1 + 原始计数)
示例:
- 文档:"我喜欢机器学习,机器学习很有趣"(共 8 个词)
- "机器学习"出现 2 次
- TF("机器学习") = 2/8 = 0.25
4.2 IDF(逆文档频率)的计算 #
IDF 的标准公式:
$$ \text{IDF}(t) = \log\left(\frac{N}{n(t) + 1}\right) $$
其中:
- $N$:文档集合中的总文档数
- $n(t)$:包含词 t 的文档数
- 加 1 是为了避免分母为零(平滑处理)
示例:
- 总文档数 $N = 1000$
- 包含"机器学习"的文档数 $n(\text{机器学习}) = 10$
- IDF("机器学习") = log(1000/(10+1)) = log(90.9) ≈ 4.51
4.3 TF-IDF 的计算 #
$$ \text{TF-IDF}(t, d) = \text{TF}(t, d) \times \text{IDF}(t) $$
完整示例: 假设文档集合有 1000 篇文档,某文档 d 有 100 个词,"机器学习"出现 5 次:
计算 TF:
- TF("机器学习", d) = 5/100 = 0.05
计算 IDF:
- 假设有 10 篇文档包含"机器学习"
- IDF("机器学习") = log(1000/(10+1)) ≈ 4.51
计算 TF-IDF:
- TF-IDF("机器学习", d) = 0.05 × 4.51 ≈ 0.23
5. 计算文档TF-IDF向量 #
5.1 代码实现 #
# 导入math库,用于数学运算
import math
# 导入Counter用于统计词频
from collections import Counter
# 定义TFIDF类
class TFIDF:
# 初始化方法,传入文档集合
def __init__(self, documents):
"""
初始化 TF-IDF 模型
参数:
documents: 文档列表,每个文档是一个词列表
"""
# 保存文档集合,每个文档是单词列表
self.documents = documents
# 计算文档总数
self.N = len(documents)
# 定义词-文档频率(DF)字典
self.df = {}
# 遍历每个文档
for doc in documents:
# 获取当前文档中所有唯一词(去重)
unique_words = set(doc)
# 遍历文档中的每个唯一单词
for word in unique_words:
# 如果词未出现在df中,返回0并加1,否则直接加1
self.df[word] = self.df.get(word, 0) + 1
# 定义词-IDF值字典
self.idf = {}
# 遍历每个词及其对应DF值
for word, df_value in self.df.items():
# 计算IDF值,采用log(N/(df+1))避免分母为0
self.idf[word] = math.log(self.N / (df_value + 1))
# 计算某个词在某一文档中的词频(TF)
def calculate_tf(self, word, doc):
"""
计算词在文档中的词频(TF)
参数:
word: 词
doc: 文档(词的列表)
返回:
词频(标准化频率)
"""
# 如果文档为空,直接返回0
if len(doc) == 0:
return 0
# 统计文档中每个词出现的次数
word_counts = Counter(doc)
# 获取目标词出现的次数
word_count = word_counts.get(word, 0)
# 计算词频:出现次数/文档长度
tf = word_count / len(doc)
# 返回tf值
return tf
# 计算某个词在某一文档中的TF-IDF值
def calculate_tfidf(self, word, doc):
"""
计算词的 TF-IDF 值
参数:
word: 词
doc: 文档(词的列表)
返回:
TF-IDF 值
"""
# 先计算词频TF
tf = self.calculate_tf(word, doc)
# 如果该词不在IDF词典中,返回0(没在所有文档中出现过)
if word not in self.idf:
return 0
# 获取该词的IDF值
idf = self.idf[word]
# 计算TF-IDF值
tfidf = tf * idf
# 返回TF-IDF结果
return tfidf
# 获取文档的TF-IDF向量(仅包含出现的词)
def get_tfidf_vector(self, doc):
"""
获取文档的 TF-IDF 向量
参数:
doc: 文档(词的列表)
返回:
字典,键为词,值为 TF-IDF 值
"""
# 定义用于存放向量的字典
vector = {}
# 获取文档中所有唯一词
unique_words = set(doc)
# 遍历每个词,计算TF-IDF值存入字典
for word in unique_words:
vector[word] = self.calculate_tfidf(word, doc)
# 返回字典
return vector
# 获取文档中TF-IDF值最大的前k个关键词
def get_top_keywords(self, doc, top_k=10):
"""
获取文档中 TF-IDF 值最高的前 k 个词(关键词)
参数:
doc: 文档(词的列表)
top_k: 返回的关键词数量
返回:
关键词列表(按 TF-IDF 值降序排列)
"""
# 获取当前文档的TF-IDF字典向量
vector = self.get_tfidf_vector(doc)
# 对词按照TF-IDF值降序排序
sorted_words = sorted(vector.items(), key=lambda x: x[1], reverse=True)
# 取出前k个关键词
top_keywords = [word for word, score in sorted_words[:top_k]]
# 返回关键词列表
return top_keywords
# 定义文档数据,每个文档是词的列表
documents = [
["我", "喜欢", "机器学习"],
["机器学习", "很", "有趣"],
["自然语言处理", "是", "AI", "的", "重要", "分支"]
]
# 创建TFIDF对象
tfidf = TFIDF(documents)
# 获取整个词汇表,并排序,便于统一向量顺序
vocabulary = sorted(tfidf.df.keys())
print(vocabulary)
# 计算所有文档的稀疏TF-IDF向量(字典形式)
sparse_vectors = [tfidf.get_tfidf_vector(doc) for doc in documents]
print(sparse_vectors)
# 初始化完整向量列表
full_vectors = []
# 对每个文档构造完整的向量(所有词都占一个维度,不出现则为0)
for sparse_vector in sparse_vectors:
# 存放当前文档完整向量
vec = []
# 按词汇表顺序补足0
for word in vocabulary:
vec.append(sparse_vector.get(word, 0.0))
# 将当前文档向量加入总列表
full_vectors.append(vec)
# 打印所有文档的完整TF-IDF向量
print(full_vectors)5.2 执行过程 #
阶段 1:导入库和定义类
import math
from collections import Counter
class TFIDF:
# ... 类定义- 导入
math用于对数计算 - 导入
Counter用于词频统计 - 定义
TFIDF类
阶段 2:准备数据
documents = [
["我", "喜欢", "机器学习"],
["机器学习", "很", "有趣"],
["自然语言处理", "是", "AI", "的", "重要", "分支"]
]- 定义 3 个文档,每个文档是词列表
阶段 3:创建 TFIDF 对象
tfidf = TFIDF(documents)执行 __init__ 方法:
步骤 3.1:保存文档集合
self.documents = documents
self.N = 3 # 文档总数步骤 3.2:计算文档频率 DF
遍历每个文档,统计每个词出现在多少个文档中:
# 文档1: ["我", "喜欢", "机器学习"]
# "我" → df["我"] = 1
# "喜欢" → df["喜欢"] = 1
# "机器学习" → df["机器学习"] = 1
# 文档2: ["机器学习", "很", "有趣"]
# "机器学习" → df["机器学习"] = 1 + 1 = 2 (已存在,加1)
# "很" → df["很"] = 1
# "有趣" → df["有趣"] = 1
# 文档3: ["自然语言处理", "是", "AI", "的", "重要", "分支"]
# "自然语言处理" → df["自然语言处理"] = 1
# "是" → df["是"] = 1
# "AI" → df["AI"] = 1
# "的" → df["的"] = 1
# "重要" → df["重要"] = 1
# "分支" → df["分支"] = 1最终 df 字典:
{
"我": 1,
"喜欢": 1,
"机器学习": 2, # 出现在2个文档中
"很": 1,
"有趣": 1,
"自然语言处理": 1,
"是": 1,
"AI": 1,
"的": 1,
"重要": 1,
"分支": 1
}步骤 3.3:计算 IDF 值
对每个词计算 IDF = log(N / (df + 1)):
# 对于 "我": IDF = log(3 / (1 + 1)) = log(1.5) ≈ 0.4055
# 对于 "机器学习": IDF = log(3 / (2 + 1)) = log(1) = 0.0000
# 对于 "AI": IDF = log(3 / (1 + 1)) = log(1.5) ≈ 0.4055
# ... 其他词类似最终 idf 字典:
{
"我": 0.4055,
"喜欢": 0.4055,
"机器学习": 0.0000, # 很常见,IDF低
"很": 0.4055,
"有趣": 0.4055,
"自然语言处理": 0.4055,
"是": 0.4055,
"AI": 0.4055,
"的": 0.4055,
"重要": 0.4055,
"分支": 0.4055
}阶段 4:获取词汇表
vocabulary = sorted(tfidf.df.keys())
print(vocabulary)- 获取所有词并排序,用于统一向量顺序
- 输出:
['AI', '分支', '喜欢', '很', '的', '是', '有趣', '机器学习', '我', '自然语言处理', '重要']
阶段 5:计算所有文档的稀疏向量
sparse_vectors = [tfidf.get_tfidf_vector(doc) for doc in documents]
print(sparse_vectors)对每个文档调用 get_tfidf_vector:
文档1:["我", "喜欢", "机器学习"]
# 1. 获取唯一词: {"我", "喜欢", "机器学习"}
# 2. 对每个词计算 TF-IDF:
# "我":
# - TF = 1/3 = 0.3333
# - IDF = 0.4055
# - TF-IDF = 0.3333 × 0.4055 = 0.1352
# "喜欢":
# - TF = 1/3 = 0.3333
# - IDF = 0.4055
# - TF-IDF = 0.3333 × 0.4055 = 0.1352
# "机器学习":
# - TF = 1/3 = 0.3333
# - IDF = 0.0000
# - TF-IDF = 0.3333 × 0.0000 = 0.0000文档1的稀疏向量:
{"我": 0.1352, "喜欢": 0.1352, "机器学习": 0.0000}文档2:["机器学习", "很", "有趣"]
# "机器学习": TF=1/3=0.3333, IDF=0.0000, TF-IDF=0.0000
# "很": TF=1/3=0.3333, IDF=0.4055, TF-IDF=0.1352
# "有趣": TF=1/3=0.3333, IDF=0.4055, TF-IDF=0.1352文档2的稀疏向量:
{"机器学习": 0.0000, "很": 0.1352, "有趣": 0.1352}文档3:["自然语言处理", "是", "AI", "的", "重要", "分支"]
# 每个词: TF=1/6=0.1667, IDF=0.4055, TF-IDF=0.1667×0.4055=0.0676文档3的稀疏向量:
{"自然语言处理": 0.0676, "是": 0.0676, "AI": 0.0676,
"的": 0.0676, "重要": 0.0676, "分支": 0.0676}最终 sparse_vectors:
[
{"我": 0.1352, "喜欢": 0.1352, "机器学习": 0.0000},
{"机器学习": 0.0000, "很": 0.1352, "有趣": 0.1352},
{"自然语言处理": 0.0676, "是": 0.0676, "AI": 0.0676,
"的": 0.0676, "重要": 0.0676, "分支": 0.0676}
]阶段 6:转换为完整向量
full_vectors = []
for sparse_vector in sparse_vectors:
vec = []
for word in vocabulary: # 按词汇表顺序
vec.append(sparse_vector.get(word, 0.0)) # 存在则取值,不存在则为0
full_vectors.append(vec)按词汇表顺序,将稀疏向量扩展为完整向量:
文档1的完整向量:
# vocabulary = ['AI', '分支', '喜欢', '很', '的', '是', '有趣', '机器学习', '我', '自然语言处理', '重要']
# sparse_vector = {"我": 0.1352, "喜欢": 0.1352, "机器学习": 0.0000}
vec = [
0.0000, # 'AI' (不存在)
0.0000, # '分支' (不存在)
0.1352, # '喜欢' (存在)
0.0000, # '很' (不存在)
0.0000, # '的' (不存在)
0.0000, # '是' (不存在)
0.0000, # '有趣' (不存在)
0.0000, # '机器学习' (存在,但值为0)
0.1352, # '我' (存在)
0.0000, # '自然语言处理' (不存在)
0.0000 # '重要' (不存在)
]文档2和文档3类似处理
最终 full_vectors:
[
[0.0, 0.0, 0.1352, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1352, 0.0, 0.0], # 文档1
[0.0, 0.0, 0.0, 0.1352, 0.0, 0.0, 0.1352, 0.0, 0.0, 0.0, 0.0], # 文档2
[0.0676, 0.0676, 0.0, 0.0, 0.0676, 0.0676, 0.0, 0.0, 0.0, 0.0676, 0.0676] # 文档3
]5.3 执行流程图 #
定义文档集合
↓
创建 TFIDF 对象
↓
【初始化阶段】
├─ 计算文档频率 DF
└─ 计算 IDF 值
↓
获取词汇表(排序)
↓
【向量化阶段】
├─ 对每个文档计算稀疏向量
│ ├─ 计算每个词的 TF
│ ├─ 获取每个词的 IDF
│ └─ 计算 TF-IDF = TF × IDF
└─ 转换为完整向量
↓
输出结果5.4 关键点总结 #
- 初始化时计算全局的 DF 和 IDF
- 每个文档的 TF 是文档特定的
- 稀疏向量只包含文档中出现的词
- 完整向量按词汇表顺序,缺失词用 0 填充
- 所有文档的向量维度相同(等于词汇表大小)
6. 实际应用示例 #
6.1 文档相似度计算 #
使用 TF-IDF 向量计算文档之间的相似度:
# 导入必要的库
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import jieba
# 定义中文分词函数
def chinese_tokenizer(text):
"""使用 jieba 进行中文分词"""
return " ".join(jieba.cut(text))
# 定义文档集合
documents = [
"我喜欢机器学习",
"机器学习很有趣",
"自然语言处理是AI的重要分支",
"我喜欢编程"
]
# 创建 TF-IDF 向量化器,使用中文分词器
vectorizer = TfidfVectorizer(tokenizer=chinese_tokenizer)
# 将文档转换为 TF-IDF 矩阵(训练向量化器)
tfidf_matrix = vectorizer.fit_transform(documents)
# 定义新文档
new_document = "我对深度学习和人工智能很感兴趣"
# 将新文档转换为 TF-IDF 向量(使用已训练的 vectorizer)
# transform 方法使用 fit 时学到的词汇表和 IDF 值
new_doc_vector = vectorizer.transform([new_document])
# 计算新文档与所有文档的余弦相似度
# cosine_similarity 返回一个矩阵,[0] 取第一行(新文档与所有文档的相似度)
similarities = cosine_similarity(new_doc_vector, tfidf_matrix)[0]
# 获取相似度最高的2个文档的索引
# argsort 返回排序后的索引,[::-1] 反转得到降序,[:2] 取前2个
top_2_indices = np.argsort(similarities)[::-1][:2]
for rank, idx in enumerate(top_2_indices, 1):
similarity_score = similarities[idx]
print(f"\n排名 {rank}:")
print(f" 文档编号: D{idx+1}")
print(f" 相似度: {similarity_score:.4f}")
print(f" 文档内容: {documents[idx]}")6.2 关键词提取 #
从文档中提取最重要的关键词:
# 导入sklearn中的TfidfVectorizer用于TF-IDF计算
from sklearn.feature_extraction.text import TfidfVectorizer
# 导入numpy用于数值运算和排序
import numpy as np
# 导入jieba用于中文分词
import jieba
# 定义待处理的中文文档
document = "机器学习是人工智能的重要分支,机器学习应用广泛,包括自然语言处理和计算机视觉"
# 创建TF-IDF向量化器,设置最多保留10个特征词,仅使用1-gram(即单个词)
vectorizer = TfidfVectorizer(
max_features=10, # 最多保留10个特征词
ngram_range=(1, 1) # 仅考虑单个词
)
# 使用jieba对中文文档进行分词
words = jieba.cut(document)
# 用空格拼接分词结果,供向量化器处理
doc_text = " ".join(words)
# 训练TF-IDF向量化器,并将文档转换成TF-IDF向量
tfidf_vector = vectorizer.fit_transform([doc_text])
# 获取所有特征词(即词汇表中被保留的词)
feature_names = vectorizer.get_feature_names_out()
# 获取文档对应的TF-IDF值,并转换为一维数组
tfidf_scores = tfidf_vector.toarray()[0]
# 对TF-IDF分数进行降序排序,得到排序后的索引
sorted_indices = np.argsort(tfidf_scores)[::-1]
# 打印待分析的文档内容
print(f"文档: {document}")
# 输出前5个关键词
print("\n关键词(Top 5):")
for i, idx in enumerate(sorted_indices[:5], 1):
# 获取排序后的特征词
word = feature_names[idx]
# 获取对应的TF-IDF得分
score = tfidf_scores[idx]
# 打印关键词及对应的TF-IDF分值
print(f" {i}. {word} (TF-IDF: {score:.4f})")7.TF-IDF 的优缺点 #
7.1 优点 #
- 简单有效:算法简单,容易理解和实现
- 计算高效:计算速度快,适合大规模文档处理
- 过滤常见词:IDF 部分可以自动过滤停用词(如"的"、"是")
- 无监督方法:不需要标注数据,可以直接使用
- 解释性强:每个词的 TF-IDF 值都有明确的含义
7.2 缺点 #
忽略词序:基于词袋模型,不考虑词的顺序
- 例如:"我喜欢你"和"你喜欢我"被视为相同
忽略语义:只考虑字面匹配,不考虑语义
- 例如:"汽车"和"车辆"被视为不同
- 例如:"苹果"(水果)和"苹果"(公司)无法区分
偏好长文档:长文档中词频容易高,可能获得不公平的优势
无法处理未登录词:如果词不在文档集合中出现,无法计算 TF-IDF
不能捕捉上下文:不考虑词的上下文信息
8.常见问题 #
8.1 TF-IDF 值越大越好吗? #
不一定。TF-IDF 值表示词的重要性,但需要结合具体任务:
- 关键词提取:选择 TF-IDF 值最高的词
- 文档相似度:使用 TF-IDF 向量计算相似度
- 文档分类:作为特征输入分类器
8.2 如何处理中文文档? #
对于中文文档,需要先进行分词:
# 使用 jieba 进行中文分词
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
# 中文文档
documents = [
"我喜欢机器学习",
"机器学习很有趣",
"自然语言处理是AI的重要分支"
]
# 分词处理
tokenized_docs = [" ".join(jieba.cut(doc)) for doc in documents]
# 创建 TF-IDF 向量化器
vectorizer = TfidfVectorizer()
# 转换为 TF-IDF 矩阵
tfidf_matrix = vectorizer.fit_transform(tokenized_docs)8.3 TF-IDF 和词频(TF)有什么区别? #
- TF:只考虑词在单篇文档中的频率
- TF-IDF:同时考虑词在单篇文档中的频率和在整个文档集合中的稀有程度
示例:
- "的"在文档中 TF 很高,但 IDF 很低(因为很多文档都有),所以 TF-IDF 不高
- "机器学习"在文档中 TF 较高,IDF 也较高(因为只有少数文档有),所以 TF-IDF 较高
8.4 如何选择 TF 和 IDF 的计算方法? #
TF 计算方法:
- 标准化频率(最常用):
TF = 词频 / 文档总词数 - 原始计数:简单但受文档长度影响
- 对数缩放:压缩大值的影响
IDF 计算方法:
- 标准公式:
IDF = log(N / (df + 1)) - 加 1 是为了避免分母为零(平滑处理)
大多数情况下,使用标准方法即可。
8.5 TF-IDF 适合多大规模的数据? #
TF-IDF 适合:
- 小规模:几千到几万文档(单机即可)
- 中规模:几十万到几百万文档(需要优化,如稀疏矩阵)
- 大规模:千万级以上文档(需要分布式系统)
性能优化:
- 使用稀疏矩阵存储(scikit-learn 默认)
- 限制特征数量(
max_features参数) - 过滤停用词(
max_df参数)
9. 总结 #
TF-IDF 是文本处理领域的经典方法,虽然简单,但在许多实际应用中仍然非常有效。
核心特点:
- 简单有效:算法简单,容易理解和实现
- 计算高效:适合大规模文档处理
- 无监督:不需要标注数据
- 解释性强:每个值都有明确的含义
适用场景:
- 搜索引擎(计算查询与文档的相关性)
- 文本相似度计算
- 关键词提取
- 文档分类/聚类(作为特征)
使用建议:
- 对于大多数场景,使用
scikit-learn的TfidfVectorizer即可 - 中文文档需要先进行分词
- 根据任务需求调整参数(如
max_features、min_df、max_df) - 可以结合其他方法(如词向量、深度学习)获得更好的效果