1.任务目标
单纯词频统计有个短板:高频词不一定是文档的关键词 。比如整篇文章反复出现the,就算过滤停用词,有些通用实词依然高频,但不是这篇文档独有的重点。 TF-IDF:衡量一个单词对于某一篇文档的重要程度。单词在本文出现多,同时在其他文档很少出现,TF-IDF 值就越高,就是本文关键词。
任务:
-
复用之前所有文本清洗、分词、停用词过滤函数
-
实现 TF-IDF 算法
-
计算每个单词 TF-IDF 分值,提取 TopN 关键词
2.原理
TF(词频):Term Frequency = 单词在当前文档出现次数 / 当前文档总单词数
衡量这个词在本文里有多频繁
IDF(逆文档频率) :log(总文档数 / (包含该词的文档数 + 1))
+1 防止分母为 0;
单词在很多文档都出现,IDF 就小,代表是通用词汇;
只在少数文档出现,IDF 大,是专属关键词
TF-IDF = TF × IDF
分数越高,这个词越能代表本篇文档。
和前面词频的区别: 词频只看本篇出现多少次;
TF-IDF 同时对比多篇文档的分布情况,过滤掉通用高频实词,提取真正专属关键词。
三、步骤
-
复用旧函数:
read_file、clean_split、filter_stopwords,读取并清洗全部文档 -
构建语料库:把所有文档清洗分词后存入列表
-
计算 TF:统计目标文档每个单词的词频
pythondef calculate_tf(word_list): """计算TF:单词在本文出现次数 / 文档总词数""" tf_dict = {} total_words = len(word_list) for w in word_list: tf_dict[w] = word_list.count(w) / total_words return tf_dict -
计算 IDF:遍历全部单词,统计有多少篇文档包含该词,代入 IDF 公式
pythondef calculate_idf(corpus): """ corpus:全部文档的分词列表组成的大列表 计算IDF """ idf_dict = {} doc_count = len(corpus) # 收集所有出现过的单词 all_words = set() for doc in corpus: all_words.update(doc) # 遍历每个词,统计有多少文档包含这个词 for word in all_words: contain_doc_num = 0 for doc in corpus: if word in doc: contain_doc_num += 1 idf_dict[word] = math.log(doc_count / (contain_doc_num + 1)) return idf_dict -
计算 TF-IDF = TF * IDF
pythondef calculate_tfidf(tf_dict, idf_dict): tfidf_dict = {} for word, tf in tf_dict.items(): tfidf_dict[word] = tf * idf_dict[word] return tfidf_dict -
对 TF-IDF 分数降序排序,提取 TopN 关键词
pythondef get_top_keywords(tfidf_dict, n=5): sorted_items = sorted(tfidf_dict.items(), key=lambda x:x[1], reverse=True) return sorted_items[:n] -
运行测试,对比【单纯词频选出的词】和【TF-IDF 选出的关键词】差异
pythonstop_words = {"the","a","an","is","are","of","in","on","at","to","and","or","but"} # 读取目标文档 target_text = read_file("article.txt") target_words = clean_split(target_text) target_words = filter_stopwords(target_words, stop_words) # 读取语料库其他文档 doc1 = filter_stopwords(clean_split(read_file("corpus/corpus_1.txt")), stop_words) doc2 = filter_stopwords(clean_split(read_file("corpus/corpus_2.txt")), stop_words) doc3 = filter_stopwords(clean_split(read_file("corpus/corpus_3.txt")), stop_words) corpus = [target_words, doc1, doc2, doc3] # 计算TF、IDF、TF-IDF tf = calculate_tf(target_words) idf = calculate_idf(corpus) tfidf = calculate_tfidf(tf, idf) top5 = get_top_keywords(tfidf,5) print("TF-IDF Top5关键词:") for word, score in top5: print(f"{word} : {score:.4f}")


四、总结
1. 为什么要用TF-IDF,不用单纯词频统计?
单纯词频仅统计单词在单篇文档的出现次数,无法区分通用实词和专属关键词。TF-IDF结合多文档全局语料,通过IDF抑制通用高频词汇权重,突出当前文档独有的核心词,提取结果更精准、具备实际分析价值。
2. IDF公式为什么要+1平滑?
防止目标文档独有单词、未出现在其他语料文档中,导致分母为0,出现数学运算报错,属于数值优化的平滑处理。
3. TF、IDF、TF-IDF各自的作用是什么?
TF衡量单词在单文档的出现频次,反映单词局部密集程度;IDF衡量单词在全局语料库的稀有程度,过滤通用无效词汇;TF-IDF结合二者,精准量化单词对当前文档的专属核心权重,是文本关键词提取的核心指标。
4. TF-IDF的核心缺陷是什么?
仅基于词频和统计概率计算,无法理解词语语义、无法识别上下文、不具备一词多义辨析能力,是传统统计式NLP算法,精度弱于Word2Vec、BERT等深度学习文本模型。