引言
在自然语言处理(NLP)和文本挖掘中,TF-IDF是一种常用的技术,用于评估一个词在文档中的重要性。它不仅在信息检索领域广泛应用,还在文本分类、关键词提取等任务中发挥着重要作用。本文将详细介绍TF-IDF的原理,并通过一个实际的代码示例来展示如何使用TF-IDF从《红楼梦》中提取核心关键词。
1. 什么是TF-IDF?
TF-IDF是一种统计方法,用于评估一个词在文档中的重要性。它由两部分组成:
- TF(Term Frequency):词频,表示一个词在文档中出现的频率。词频越高,说明该词在文档中越重要。
- IDF(Inverse Document Frequency):逆文档频率,用于衡量一个词在整个语料库中的普遍性。如果一个词在很多文档中都出现,那么它的IDF值会较低,说明它对区分文档的贡献较小。
最终的TF-IDF值是TF和IDF的乘积:
通过TF-IDF,我们可以得到一个词在文档中的重要性评分。评分越高,说明该词在文档中越重要。
2. TF-IDF的应用场景
TF-IDF广泛应用于以下场景:
- 关键词提取:从文档中提取出最重要的关键词。
- 文本分类:通过TF-IDF值将文本转化为向量,用于机器学习模型的输入。
- 信息检索:在搜索引擎中,TF-IDF用于评估查询词与文档的相关性。
3. 代码实现:从《红楼梦》中提取核心关键词
接下来,我们通过一个实际的代码示例,展示如何使用TF-IDF从《红楼梦》中提取核心关键词。
3.1 代码结构
代码主要分为以下几个步骤:
1. 读取分词后的文本:将《红楼梦》的分卷内容进行分词,并保存到 ‘分词后汇总.txt’ 中。
2. 计算TF-IDF值:使用`TfidfVectorizer`计算每个词的TF-IDF值。
3. 提取核心关键词:根据TF-IDF值,提取每个分卷的核心关键词。
代码详解
1、分卷处理
1.1 代码功能
将《红楼梦》的全文按照“卷”进行分割,并将每一卷的内容保存到单独的文本文件中。同时,过滤掉一些无关的内容(如“手机电子书·大学生小说网 更新时间”)。
1.2 代码实现
1.2.1、读取文件
- 使用`open`函数打开《红楼梦》全文文件,指定编码为`utf-8`。
- 创建一个初始文件对象`juan_file`,用于写入卷的内容。
import os# 打开《红楼梦》全文文件
file = open('..\红楼梦\红楼梦.txt', encoding='utf-8')# 创建一个文件对象,用于写入卷的内容
juan_file = open('..\红楼梦\红楼梦卷开头.txt', 'w', encoding='utf-8')
1.2.2逐行处理
- 使用`for line in file`逐行读取全文。
- 如果某一行包含“手机电子书·大学生小说网 更新时间”,则跳过该行(`continue`)。
- 如果某一行包含“卷 第”,则表示新的卷开始:
- 提取卷名,并去掉首尾空白字符(`line.strip()`)。
- 构建保存路径(`os.path.join`)。
- 关闭当前卷的文件,并打开一个新的卷文件。
- 跳过这一行,不将其写入卷内容。
for line in file:# 过滤掉包含“手机电子书·大学生小说网 更新时间”的行if '手机电子书·大学生小说网 更新时间' in line:continue # 跳过这一行# 如果遇到“卷 第”开头的行,表示新的卷开始if '卷 第' in line:juan_name = line.strip() + '.txt' # 获取卷名,并去掉首尾空白字符path = os.path.join('..\\红楼梦\\分卷\\', juan_name) # 构建卷的保存路径print(path) # 打印路径,用于调试# 关闭当前卷的文件,并打开一个新的卷文件juan_file.close()juan_file = open(path, 'w', encoding='utf-8')continue # 跳过这一行,不写入卷内容# 将当前行写入当前卷的文件中juan_file.write(line)
1.2.3. 关闭文件
# 关闭最后一个卷的文件
juan_file.close()
2、分词与停用词过滤
2.1 代码功能
对每一卷的内容进行分词,并过滤掉停用词(无意义的关键词)。最终,将分词后的内容保存到一个汇总文件中。
2.2 代码实现
2.2.1 读取分卷内容
- 使用`os.walk`遍历`..\红楼梦\分卷\`目录,获取所有卷的文件路径和内容。
- 将文件路径和内容存储到`filePaths`和`fileContents`列表中。
import pandas as pd# 保存文件路径和内容的列表
filePaths = [] # 文件路径
fileContents = [] # 文件内容# 遍历分卷目录,读取所有卷的内容
for root, dirs, files in os.walk('..\\红楼梦\\分卷\\'):for name in files:filePath = os.path.join(root, name) # 构建文件路径filePaths.append(filePath) # 将路径添加到列表中# 读取文件内容f = open(filePath, 'r', encoding='utf-8')fileContent = f.read()f.close()fileContents.append(fileContent) # 将内容添加到列表中
构建DataFrame:
- 使用`pandas`将文件路径和内容存储到`DataFrame`中,方便后续处理。
# 将文件路径和内容存储到DataFrame中
corpos = pd.DataFrame({'filePath': filePaths,'fileContent': fileContents
})
print(corpos) # 打印DataFrame,用于调试
2.2.2 分词与停用词过滤
1. 加载自定义词库:
- 使用`jieba.load_userdict`加载自定义词库(如“红楼梦词库.txt”),以提高分词的准确性。
2. 读取停用词表:
- 使用`pandas`读取停用词表(如“StopwordsCN.txt”),用于过滤无意义的关键词。
import jieba# 加载自定义词库
jieba.load_userdict(r'..\红楼梦\红楼梦词库.txt')# 读取停用词表
stopwords = pd.read_csv('StopwordsCN.txt', encoding='utf-8', engine='python', index_col=False)# 创建一个文件对象,用于写入分词后的内容
file_to_jieba = open(r'../红楼梦/分词后汇总.txt', 'w', encoding='utf-8')# 对每一卷的内容进行分词和停用词过滤
for index, row in corpos.iterrows():juan_ci = '' # 保存当前卷的分词结果filePath = row['filePath'] # 文件路径fileContent = row['fileContent'] # 文件内容
3.分词与过滤:
- 对每一卷的内容进行分词(`jieba.cut`)。
- 过滤掉停用词和空白字符。
- 将分词结果保存到`juan_ci`中。
# 使用jieba进行分词segs = jieba.cut(fileContent)for seg in segs:# 过滤停用词和空白字符if seg not in stopwords.stopword.values and len(seg.strip()) > 0:juan_ci += seg + ' ' # 将分词结果拼接成字符串# 将分词结果写入文件file_to_jieba.write(juan_ci + '\n')# 关闭文件
file_to_jieba.close()
3、关键词提取
3.1、代码功能
这部分代码,我们借助模型,将关键词提取出来
3.2、代码实现
3.2.1 读取分词后的文本
首先,我们读取已经分词后的文本文件`分词后汇总.txt`,并将其存储在`corpus`变量中。
infile = open(r'..\红楼梦\分词后汇总.txt', 'r', encoding='utf-8')
corpus = infile.readlines()
3.2.2 计算TF-IDF值
我们使用`TfidfVectorizer`来计算每个词的TF-IDF值。`TfidfVectorizer`是`scikit-learn`库中的一个类,用于将文本转换为TF-IDF特征向量。
from sklearn.feature_extraction.text import TfidfVectorizervectorizer = TfidfVectorizer() # 创建TF-IDF向量转换对象
tfidf = vectorizer.fit_transform(corpus) # 计算TF-IDF值
`tfidf`是一个稀疏矩阵,表示每个文档中每个词的TF-IDF值。
3.2.3 提取核心关键词
接下来,我们通过`np.argsort`函数找到每个文档中TF-IDF值最高的前10个词,并输出这些关键词及其对应的TF-IDF值。
import numpy as np
import pandas as pdwordlist = vectorizer.get_feature_names_out() # 获取特征名称
df = pd.DataFrame(tfidf.T.todense(), index=wordlist) # 将TF-IDF矩阵转换为DataFramefor i in range(len(corpus)):featurelist = df.iloc[:, i] # 获取第i列的TF-IDF值top_index = np.argsort(featurelist)[-10:][::-1] # 找到TF-IDF值最高的前10个词的索引print(f'第{i + 1}回的核心关键词有:')for j in top_index:print(f'{wordlist[j]}: {featurelist.iloc[j]:.2f}') # 输出关键词及其TF-IDF值print() # 添加空行分隔不同回的结果
4、代码输出
代码运行后,会输出每个分卷的核心关键词及其TF-IDF值。例如:
总结
TF-IDF是一种简单但非常有效的文本特征提取方法,能够帮助我们快速识别文档中的关键词。通过本文的代码示例,我们展示了如何使用TF-IDF从《红楼梦》中提取核心关键词。希望这篇文章能帮助你更好地理解TF-IDF的原理和应用。