机器学习算法篇(十):TF-IDF算法详解与应用实战
引言
TF-IDF(Term Frequency-Inverse Document Frequency)是文本挖掘和信息检索领域最基础也最重要的特征提取方法之一。本文将全面解析TF-IDF的核心原理、实现方法以及实际应用场景,并通过Python代码示例展示其完整应用流程。
一、TF-IDF算法原理
1.1 基本概念
TF-IDF是一种统计方法,用于评估一个词语对于一篇文档的重要程度。其核心思想是:一个词语的重要性与其在文档中出现的频率成正比,与在整个语料库中出现的频率成反比。
1.2 数学表达
TF-IDF由两部分组成:
词频(TF):表示词语在文档中的出现频率
TF(t,d) = (词语t在文档d中出现的次数) / (文档d的总词数)
逆文档频率(IDF):衡量词语的普遍重要性
IDF(t) = log[语料库中文档总数 / (包含词语t的文档数 + 1)]
最终TF-IDF值为两者的乘积:
TF-IDF(t,d) = TF(t,d) × IDF(t)
1.3 计算示例
假设我们有一个包含3篇文档的语料库:
- "机器学习是人工智能的分支"
- "深度学习是机器学习的分支"
- "自然语言处理需要机器学习"
计算词语"机器学习"在文档1中的TF-IDF值:
TF计算:
- "机器学习"在文档1出现1次
- 文档1总词数6
- TF = 1/6 ≈ 0.167
IDF计算:
- 语料库文档总数3
- "机器学习"出现在3篇文档中
- IDF = log(3/(3+1)) ≈ -0.125
TF-IDF = 0.167 × (-0.125) ≈ -0.021
(注:实际应用中会对负数结果做特殊处理)
二、TF-IDF的变体与改进
2.1 TF计算变体
计算方式 | 公式 | 特点 |
---|---|---|
原始频率 | count(t,d)/len(d) | 简单直接 |
对数归一化 | 1 + log(count(t,d)) | 抑制高频词影响 |
双归一化 | 0.5 + 0.5*count/max_count | 平衡文档长度差异 |
2.2 IDF计算改进
平滑处理:
IDF(t) = log[N/(df(t)+1)] + 1
避免出现零值
最大IDF限制:
IDF(t) = log(1 + N/df(t))
防止IDF值过大
三、TF-IDF的Python实现
3.1 使用sklearn实现
from sklearn.feature_extraction.text import TfidfVectorizercorpus = ['This is the first document.','This document is the second document.','And this is the third one.','Is this the first document?'
]vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus)print("特征词列表:", vectorizer.get_feature_names_out())
print("TF-IDF矩阵:\n", X.toarray())
3.2 参数详解
TfidfVectorizer(input='content', # 输入类型encoding='utf-8', # 编码方式decode_error='strict',strip_accents=None, # 去除重音lowercase=True, # 转换为小写stop_words=None, # 停用词表token_pattern=r"(?u)\b\w\w+\b", # 分词模式ngram_range=(1, 1), # n-gram范围max_df=1.0, # 忽略高频词阈值min_df=1, # 忽略低频词阈值max_features=None, # 最大特征数norm='l2', # 归一化方式use_idf=True, # 使用IDFsmooth_idf=True, # 平滑IDFsublinear_tf=False # 对数TF
)
四、TF-IDF的应用场景
4.1 关键词提取
通过计算文档中所有词语的TF-IDF值,取权重最高的几个词作为关键词:
import numpy as npdef extract_keywords(tfidf_matrix, feature_names, top_n=3):keywords = []for i in range(tfidf_matrix.shape[0]):row = np.squeeze(tfidf_matrix[i].toarray())top_indices = row.argsort()[-top_n:][::-1]keywords.append([feature_names[j] for j in top_indices])return keywordskeywords = extract_keywords(X, vectorizer.get_feature_names_out())
print("每篇文档的关键词:", keywords)
4.2 文本相似度计算
使用TF-IDF向量计算余弦相似度:
from sklearn.metrics.pairwise import cosine_similarity# 计算第一篇文档与其他文档的相似度
similarities = cosine_similarity(X[0:1], X[1:])
print("文档相似度:", similarities)
4.3 搜索引擎排序
在搜索查询时,计算查询词与文档的TF-IDF匹配度:
query = "first document"
query_vec = vectorizer.transform([query])
scores = cosine_similarity(query_vec, X)
print("查询匹配得分:", scores)
五、TF-IDF的优缺点分析
5.1 优势
- 计算高效:线性时间复杂度,适合大规模文本处理
- 可解释性强:权重直接反映词语重要性
- 无需标注数据:完全无监督方法
- 有效过滤停用词:自动降低常见词的权重
5.2 局限性
- 忽略语义信息:无法识别同义词和一词多义
- 静态权重:IDF基于固定语料库,难以适应新词
- 长尾分布问题:对低频词处理不够理想
- 无法捕捉词序:丢失了词语位置信息
六、TF-IDF的改进方向
6.1 结合词向量
from gensim.models import Word2Vec# 训练Word2Vec模型
sentences = [doc.split() for doc in corpus]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1)# 结合TF-IDF权重
def get_weighted_vector(words, tfidf_weights, model):vector = np.zeros(model.vector_size)for word in words:if word in model.wv:vector += model.wv[word] * tfidf_weights.get(word, 0)return vector
6.2 动态TF-IDF
实现滑动窗口更新IDF值:
class DynamicTfidfVectorizer:def __init__(self, window_size=1000):self.window_size = window_sizeself.document_queue = []self.word_doc_count = {}def update_model(self, new_documents):# 更新文档队列self.document_queue.extend(new_documents)if len(self.document_queue) > self.window_size:removed_docs = self.document_queue[:len(new_documents)]self._remove_docs(removed_docs)# 更新词频统计for doc in new_documents:words = set(doc.split())for word in words:self.word_doc_count[word] = self.word_doc_count.get(word, 0) + 1
6.3 领域自适应
def domain_adapted_tfidf(corpus, domain_lexicon):# 计算基础TF-IDFbase_vectorizer = TfidfVectorizer()base_tfidf = base_vectorizer.fit_transform(corpus)# 领域词典加权feature_names = base_vectorizer.get_feature_names_out()domain_weights = np.ones(len(feature_names))for i, word in enumerate(feature_names):if word in domain_lexicon:domain_weights[i] *= 2.0 # 领域词权重加倍# 应用加权weighted_tfidf = base_tfidf.multiply(domain_weights)return weighted_tfidf
七、实战案例:新闻分类系统
7.1 数据准备
使用20 Newsgroups数据集:
from sklearn.datasets import fetch_20newsgroupsnewsgroups = fetch_20newsgroups(subset='train')
documents = newsgroups.data
labels = newsgroups.target
7.2 特征工程
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import TruncatedSVD# TF-IDF特征提取
tfidf = TfidfVectorizer(max_features=10000, stop_words='english')
X_tfidf = tfidf.fit_transform(documents)# 降维处理
svd = TruncatedSVD(n_components=300)
X_svd = svd.fit_transform(X_tfidf)
7.3 模型训练与评估
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_scoremodel = RandomForestClassifier(n_estimators=100)
scores = cross_val_score(model, X_svd, labels, cv=5)
print("平均准确率:", scores.mean())
八、总结与展望
TF-IDF作为经典的文本特征表示方法,虽然简单但非常有效。在实际应用中,我们通常:
- 根据具体任务调整TF-IDF参数
- 结合其他特征表示方法(如词向量)
- 针对领域特点进行定制化改进
未来发展方向包括:
- 动态更新的TF-IDF
- 结合深度学习模型
- 跨语言TF-IDF应用
通过本文的介绍,希望读者能够全面理解TF-IDF的原理和应用,并在实际项目中灵活运用这一强大的文本处理工具。