《机器学习》——TF-IDF(关键词提取)
文章目录
- TF-IDF简介
- TF-IDF应用场景
- TF-IDF模型
- 模型参数
- 主要参数
- TF-IDF实例
- 实例步骤
- 导入数据和模块
- 处理数据
- 处理文章开头和分卷处理
- 将各卷内容存储到数据帧
- jieba分词和去停用词处理
- 计算 TF-IDF 并找出核心关键词
TF-IDF简介
- TF - IDF(Term Frequency - Inverse Document Frequency)是一种用于信息检索和文本挖掘的常用加权技术。它由两部分组成:词频(TF)和逆文档频率(IDF)。
- 词频(TF)
- 词频是指某个词在一篇文档中出现的频率。计算方法是用某个词在文档中出现的次数除以文档的总词数。例如,文档 A 中有 100 个单词,单词 “apple” 出现了 5 次,那么单词 “apple” 在文档 A 中的词频 TF = 5/100 = 0.05。它衡量的是一个词在单篇文档中的重要性,词频越高,说明这个词在这篇文档中可能越重要。
- 逆文档频率(IDF)
- 逆文档频率是一个词在整个文档集合中的稀有程度的度量。计算方法是先计算文档总数 N,然后统计包含某个词的文档数 n,那么这个词的逆文档频率 IDF = log (N/n)。例如,假设有 1000 篇文档(N = 1000),其中只有 10 篇文档包含单词 “banana”(n = 10),那么单词 “banana” 的逆文档频率 IDF = log (1000/10)= log (100)≈ 2.(这里以自然对数为例)。IDF 的值越大,说明这个词越稀有,在区分文档时可能越有价值。
- TF - IDF 值
- TF - IDF 值是词频和逆文档频率的乘积,即 TF - IDF = TF×IDF。它综合考虑了一个词在单篇文档中的出现频率和在整个文档集合中的稀有程度,从而能够更好地衡量一个词对于某篇文档的重要性。在上面的例子中,如果 “apple” 的 TF = 0.05,并且假设其 IDF = 1.5(具体值取决于文档集合),那么 “apple” 的 TF - IDF 值 = 0.05×1.5 = 0.075。
- 词频(TF)
TF-IDF应用场景
- 文本分类
- 在文本分类任务中,TF - IDF 可以用来提取文本的特征向量。例如,将新闻文章分为体育、娱乐、科技等类别。通过计算每篇新闻文章中各个单词的 TF - IDF 值,然后选择 TF - IDF 值较高的单词作为特征,构建一个特征向量来代表这篇文章。这个特征向量可以作为机器学习分类算法(如朴素贝叶斯、支持向量机等)的输入,帮助分类器判断文章所属的类别。
- 信息检索
- 在搜索引擎中,TF - IDF 用于对搜索结果进行排序。当用户输入一个查询词时,搜索引擎会计算查询词与文档库中各个文档的相关性。TF - IDF 可以帮助衡量查询词在文档中的重要性,从而将与查询词相关性高的文档排在前面。例如,用户搜索 “人工智能应用”,搜索引擎会根据文档中 “人工智能” 和 “应用” 这两个词的 TF - IDF 值来判断文档与查询的相关性,TF - IDF 值高的文档更有可能被优先展示。
- 关键词提取
- 可以利用 TF - IDF 来提取文档的关键词。通常,TF - IDF 值较高的词很可能是文档的关键词。例如,对于一篇学术论文,通过计算论文中各个词的 TF - IDF 值,选择排名靠前的词作为关键词,这些关键词可以帮助读者快速了解论文的主题。
TF-IDF模型
模型参数
主要参数
- input
- 该参数指定输入数据的类型。
- 可选值:
- ‘filename’:表示输入是文件名列表,会从文件中读取文本内容。
- ‘file’:表示输入是文件对象,会从文件对象中读取文本内容。
- ‘content’(默认):表示输入是文本内容列表,直接使用输入的文本进行处理。
- encoding
- 用于指定文本的编码方式。
- 例如,对于包含多种语言字符的文本,可以使用 ‘utf-8’ 进行编码,确保字符能被正确解析。
- decode_error
- 当解码错误发生时的处理策略。
- 可选值:
- ‘strict’(默认):会引发 UnicodeDecodeError 异常。
- ‘ignore’:忽略错误,直接跳过无法解码的部分。
- ‘replace’:用 ‘?’ 或其他替换字符替换无法解码的部分。
- strip_accents
- 去除重音字符,将其转换为 ASCII 字符。
- 可选值:
- ‘ascii’:将重音字符转换为相应的 ASCII 字符。
- None:不进行此操作。
- lowercase
- 是否将文本转换为小写。
- 默认值为 True,将所有文本转换为小写,以确保不区分大小写进行处理,因为在 TF-IDF 计算中通常认为大小写不同但拼写相同的词是相同的词。
- preprocessor
- 可以自定义预处理函数,在分词前对文本进行预处理。
- 例如,可以定义一个函数,将 HTML 标签去除或进行一些特殊符号的替换,该函数会在分词前应用于每个文档。
- tokenizer
- 自定义分词函数,用于将文本拆分成词或标记。
- 例如,可以使用自己编写的分词函数代替默认的分词方式,对文本进行更细致的分词处理,如对中文进行分词,可以使用 jieba 分词工具,将其封装为一个函数传入此参数。
- analyzer
- 定义特征应该由哪些部分组成。
- 可选值:
- ‘word’(默认):以词为单位。
- ‘char’:以字符为单位。
- ‘char_wb’:以字符为单位,考虑词边界。
- stop_words
- 可以是以下几种情况:
- None(默认):不使用停用词。
- ‘english’:使用内置的英文停用词列表,会过滤掉常见的英文停用词,如 and, the, is 等。
- 自定义的停用词列表,例如 [‘我’, ‘你’, ‘他’] 可用于中文停用词过滤。
- 可以是以下几种情况:
- token_pattern
- 用于指定分词的正则表达式模式。
- 默认是 r"(?u)\b\w\w+\b",即匹配至少两个字母数字字符组成的词,可根据需要修改此正则表达式以适应不同的语言或特殊字符要求。
- ngram_range
- 定义要考虑的词或字符的范围。
- 接收一个元组 (min_n, max_n),例如 (1, 2) 表示考虑一元词(单个词)和二元词(两个词的组合),可以捕捉到一些短语信息,对于一些特定任务可能会提高性能。
- max_df
- 用于过滤掉过于常见的词。
- 可以是浮点数,范围在 (0.0, 1.0],表示文档频率的最大阈值,例如 0.8 表示文档频率超过 80% 的词将被过滤;也可以是整数,表示绝对的文档频率。
- min_df
- 用于过滤掉过于罕见的词。
- 可以是浮点数,范围在 [0.0, 1.0],表示文档频率的最小阈值,例如 0.2 表示文档频率低于 20% 的词将被过滤;也可以是整数,表示绝对的文档频率。
- max_features
- 只考虑最常见的 max_features 个词。
- 例如,设置为 1000 时,仅考虑词汇表中最常见的 1000 个词,用于限制特征的维度,避免高维度带来的计算开销和过拟合。
- vocabulary
- 可以是 None(默认),表示使用从输入数据中学习的词汇表;也可以是一个字典或可迭代对象,用于手动指定词汇表,只有在该词汇表中的词才会被考虑进行 TF-IDF 计算。
TF-IDF实例
对红楼梦文章进行TF-IDF处理,提取到关键字。
通过网盘分享的文件:红楼梦.txt
链接: https://pan.baidu.com/s/1y4_qTi1UgkCHo7exi5g4kw 提取码: 246h
–来自百度网盘超级会员v2的分享
通过网盘分享的文件:StopwordsCN.txt
链接:https://pan.baidu.com/s/1827ZPVgGdoIo86dLDJCV1Q
提取码: t27s
–来自百度网盘超级会员v2的分享
实例步骤
所导入的库下载:
pip install jieba
pip install pandas==1.3.5
pip install scikit-learn==1.0.2
- 导入数据和模块
- 处理数据
- 处理文章开头和分卷处理
- 将各卷内容存储到数据帧
- jieba分词和去停用词处理
- 训练模型并计算出TF-IDF值
导入数据和模块
import os
import pandas as pd
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
file = open('红楼梦.txt', encoding='utf-8')
处理数据
处理文章开头和分卷处理
注意:分卷文件夹需要自己创建。
# 标志,用于标记是否是第一次保存文件
flag = 0
# 打开一个文件用于存储开始部分的内容
juan_file = open('红楼梦开头.txt', 'w', encoding='utf-8')
# 开始遍历《红楼梦》的文本文件
for line in file:
# 当找到包含"卷 第"的行,认为是一个新的卷的开始
if '卷 第' in line:
# 提取卷名并添加后缀.txt
juan_name = line.strip() + '.txt'
# 构建存储该卷的文件的完整路径
path = os.path.join('.\\分卷\\', juan_name)
print(path)
# 如果是第一次读取到卷 第
if flag == 0:
# 打开新文件存储该卷内容
juan_file = open(path, 'w', encoding='utf-8')
flag = 1
else:
# 关闭之前的文件,并打开新文件存储该卷内容
juan_file.close()
juan_file = open(path, 'w', encoding='utf-8')
continue
# 将行内容写入当前的卷文件
juan_file.write(line)
# 关闭最后的卷文件
juan_file.close()
部分输出:
将各卷内容存储到数据帧
# 存储文件路径和文件内容的列表
filePaths = []
fileContents = []
# 遍历分卷目录下的所有文件
for root, dirs, files in os.walk(r'.\分卷'):
for name in files:
# 构建文件的完整路径
filePath = os.path.join(root, name)
print(filePath)
# 将文件路径添加到列表
filePaths.append(filePath)
# 打开文件
f = open(filePath, 'r', encoding='utf-8')
# 读取文件内容
fileContent = f.read()
f.close()
# 将文件内容添加到列表
fileContents.append(fileContent)
# 将文件路径和文件内容存储到一个 DataFrame 中
corpos = pd.DataFrame({
'filePath': filePaths,
'fileContent': fileContents})
print(corpos)
使用 os.walk 遍历 .\分卷 目录下的所有文件,将文件路径存储在 filePaths 列表,文件内容存储在 fileContents 列表中。
将 filePaths 和 fileContents 存储在 pandas 数据帧 corpos 中。
jieba分词和去停用词处理
# 加载结巴分词的自定义词库
jieba.load_userdict(r'./红楼梦词库.txt')
# 读取停用词文件
stopwords = pd.read_csv(r'StopwordsCN.txt',
encoding='utf-8', engine='python', index_col=False)
# 打开一个文件用于存储分词结果
file_to_jieba = open(r'分词汇总.txt', 'w', encoding='utf-8')
# 遍历 DataFrame 中的每一行
for index, row in corpos.iterrows():
# 存储分词后的内容
juan_ci = ''
# 获取文件路径
filePath = row['filePath']
# 获取文件内容
fileContent = row['fileContent']
# 对文件内容进行结巴分词
segs = jieba.cut(fileContent)
# 遍历分词结果
for seg in segs:
# 如果分词不在停用词列表中,且长度不为 0
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()
计算 TF-IDF 并找出核心关键词
# 打开存储分词结果的文件
inFile = open(r'分词汇总.txt', 'r', encoding='utf-8')
# 读取文件的每一行存储在 corpus 中
corpus = inFile.readlines()
# 创建 TF-IDF 向量化器
vectorizer = TfidfVectorizer()
# 对 corpus 进行拟合和转换,得到 TF-IDF 矩阵
tfidf = vectorizer.fit_transform(corpus)
# 获取特征名称
wordlist = vectorizer.get_feature_names()
# 将 TF-IDF 矩阵转换为 DataFrame
df = pd.DataFrame(tfidf.T.todense(), index=wordlist)
# 遍历每一个文档(这里假设是每一卷)
for i in range(len(corpus)):
# 获取当前文档的 TF-IDF 特征列表
featurelist = df.iloc[:, i].to_list()
# 存储当前文档的关键词及其 TF-IDF 值
resdict = {}
# 遍历每个特征
for j in range(0, len(wordlist)):
# 将特征和对应的 TF-IDF 值存储到字典中
resdict[wordlist[j]] = featurelist[j]
# 对关键词按 TF-IDF 值降序排序
resdict = sorted(resdict.items(), key=lambda x: x[1], reverse=True)
# 输出第 i+1 个文档的前 10 个核心关键词
print("第{}回的核心关键词:".format(i + 1), resdict[0:10]
部分结果: