以下我们会演示了如何使用 scikit-learn 的 CountVectorizer 和 TfidfVectorizer 进行文本特征抽取。
CountVectorizer 和 TfidfVectorizer 都可以用于文本特征抽取,但是它们有一些不同之处。CountVectorizer 将文本转换为词频向量,而 TfidfVectorizer 将文本转换为TF-IDF权重向量。TF-IDF权重向量会根据词频和逆文档频率对词进行加权,从而更好地表示文本数据。
首先,我们需要安装 scikit-learn 库,可以通过 pip 安装:
pip install scikit-learn
其次我们给出数据
data = ["life is too short, i like like python", "pony is a super super man"]
先试用使用 CountVectorizer 进行文本特征抽取:
定义函数:count_demo
from sklearn.feature_extraction.text import CountVectorizer
def count_demo():
"""
文本特征抽取
:return:
"""
data = ["life is too short, i like like python", "pony is a super super man"]
# 1 实例化一个转换器类
transfer = CountVectorizer() # 统计样本中每个词语出现的次数
# 2 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
调用函数
if __name__ == '__main__':
# 英文文本特征抽取
count_demo()
如果直接打印data_new,显示的是一个稀疏矩阵
print("data_new is: \n", data_new) data_new is: (0, 1) 1 (0, 0) 1 (0, 8) 1 (0, 6) 1 (0, 2) 2 (0, 5) 1 (1, 0) 1 (1, 4) 1
如果想要显示成常规的样式,可以加上 toarray
print("data_new is: \n", data_new.toarray()) [[1 1 2 0 0 1 1 0 1] [1 0 0 1 1 0 0 2 0]]
上面演示的数据是英文的,接下来演示数据是中文的情况。
# 如果样本中的数据是中文的,那么应该怎么处理呢?
def count_demo2():
"""
文本特征抽取
:return:
"""
data = ["我喜欢喜欢吃饭' '我喜欢睡觉觉'"]
# 1 实例化一个转换器类
transfer = CountVectorizer() # 统计样本中每个词语出现的次数
# 2 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
print("data_new is: \n", data_new)
data_new is:
(0, 0) 1
(0, 1) 1
一眼看过去,就觉得结果不太像的样子。由于中文的特殊性,我们需要进行分词。分词后,结果会稍微好一点。
比如我把data改一下。手工进行一下分词
# 如果样本中的数据是中文的,那么应该怎么处理呢?
def count_demo2():
"""
文本特征抽取
:return:
"""
data = ["我喜欢 喜欢 吃饭" "我喜欢 睡觉觉"]
# 1 实例化一个转换器类
transfer = CountVectorizer() # 统计样本中每个词语出现的次数
# 2 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
print("data_new is: \n", data_new)
print("data_new to array is: \n", data_new.toarray())
print("特征名字是: \n", transfer.get_feature_names_out())
data_new is:
(0, 2) 1
(0, 1) 1
(0, 0) 1
(0, 3) 1
data_new to array is:
[[1 1 1 1]]
特征名字是:
['吃饭我喜欢' '喜欢' '我喜欢' '睡觉觉']
一般的来说,我们分词会借助相关的工具来分词,不会进行手工分词,比如使用jieba。
在演示jieba之前,先演示一下停用词,停用词可以过滤掉一下常见词,通常会有停用词表:
# 加上stopwrds参数,可以过滤掉一些常见的词语
def count_demo3():
"""
文本特征抽取
:return:
"""
data = ["我 喜欢 吃饭", "我 喜欢 睡觉觉"]
# 1 实例化一个转换器类
transfer = CountVectorizer(stop_words=["喜欢"])
# 2 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
print("data_new is: \n", data_new)
print("data_new to array is: \n", data_new.toarray())
print("特征名字是: \n", transfer.get_feature_names_out())
data_new is:
(0, 0) 1
(1, 1) 1
data_new to array is:
[[1 0]
[0 1]]
特征名字是:
['吃饭' '睡觉觉']
我们看到“喜欢”被过滤掉了。这就是分词的简单应用。
下面我们来演示一下jieba
首先,需要导入相关的库
import jieba
接着,我们自定义分词函数
# 定义一个专门用来分词的函数
def cut_words(text):
"""
进行中文分词
jieba.lcut 直接生成的就是一个list
jieba.cut 生成的是一个生成器,generator,也就是可以通过for循环来取里面的每一个词。
"""
print(type(jieba.cut(text))) # <class 'generator'> 迭代器
# 我们需要把迭代器做一个转换,把迭代器转换为列表
text = list(jieba.cut(text))
return "".join(text)
接下来,我们来使用自定义的分词函数,进行文本特征抽取。
我们获取了一些数据,这些数据是关于国际货币基金组织(IMF)和经合组织(OECD)对全球经济增速的预测。
# 1 获取数据
data = ["据国际货币基金组织(IMF)预测,2024年全球经济增速将为2.9 %。",
"IMF建议,多国已接近其紧缩周期的峰值,不需要进一步收紧;要提高长期经济增速,需通过结构性改革实现,特别是侧重于治理、企业监管和对外部门的改革;多边合作有助于确保所有国家取得更好的增长成果;各国应致力于限制地缘经济割裂、努力恢复对基于规则的多边框架的信任,以提高透明度和政策确定性,帮助促进全球共同繁荣。",
"相比之下,经合组织(OECD)对世界经济前景较为悲观。据OECD最新预测,明年全球经济增速将放缓至2.7 %,这意味着2024年或将成为自2020年以来全球经济增速最低的一年。",
"OECD指出,美国明年将放慢增长步伐,这是导致全球经济增长放缓的关键因素。美国经济增速预计将从2023年的2.4 % 放缓至2024年的1.5 %,因为美联储的加息举措会继续抑制经济增长。美联储加息大幅抬高了消费者和企业的借贷成本。"]
然后,我们对这些数据进行了分词处理。我们定义了一个名为cut_words的函数,该函数使用jieba.cut方法对文本进行分词,并将分词结果保存到一个列表中。
先定义一个空列表,接着把分词的结果保存到列表中。
# 2 分词
content_S = []
for line in data:
# 对每一篇文章进行分词
content_S.append(cut_words(line)) # 保存分词的结果
接下来,我们获取了一个哈工大的停用词表。这个停用词表是从一个文本文件中读取的,文件中包含了一些常见的中文停用词。
# 3 获取停用词表
stopwords = pd.read_csv("D:\MyCodes\PythonCodes\scientificProject\AAA_itcast\哈工大停用词表.txt", index_col=False,
sep="\t", quoting=3, names=['stopword'],
encoding='utf-8')
然后,我们创建了一个CountVectorizer对象,该对象用于将文本数据转化为词频矩阵。我们传入停用词表作为参数,以便在转化过程中忽略停用词。
# 4 实例化一个转换器类
transfer = CountVectorizer(stop_words=stopwords['stopword'].tolist())
最后,我们调用了fit_transform方法,将分词后的文本数据转化为词频矩阵。然后,我们将词频矩阵打印出来,并打印了特征名字。
# 5 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
data_new2 = data_new.toarray()
print("data_new2 is: \n", data_new2)
print("特征名字是: \n", transfer.get_feature_names_out())
完整的代码如下:
import pandas as pd
def count_demo4():
"""
文本特征抽取,jieba自动分词
:return:
"""
# 1 获取数据
data = ["据国际货币基金组织(IMF)预测,2024年全球经济增速将为2.9 %。",
"IMF建议,多国已接近其紧缩周期的峰值,不需要进一步收紧;要提高长期经济增速,需通过结构性改革实现,特别是侧重于治理、企业监管和对外部门的改革;多边合作有助于确保所有国家取得更好的增长成果;各国应致力于限制地缘经济割裂、努力恢复对基于规则的多边框架的信任,以提高透明度和政策确定性,帮助促进全球共同繁荣。",
"相比之下,经合组织(OECD)对世界经济前景较为悲观。据OECD最新预测,明年全球经济增速将放缓至2.7 %,这意味着2024年或将成为自2020年以来全球经济增速最低的一年。",
"OECD指出,美国明年将放慢增长步伐,这是导致全球经济增长放缓的关键因素。美国经济增速预计将从2023年的2.4 % 放缓至2024年的1.5 %,因为美联储的加息举措会继续抑制经济增长。美联储加息大幅抬高了消费者和企业的借贷成本。"]
# 2 分词
content_S = []
for line in data:
# 对每一篇文章进行分词
content_S.append(cut_words(line)) # 保存分词的结果
print("contest_S is: \n", content_S)
# 3 获取停用词表
stopwords = pd.read_csv("D:\GUYA\MyCodes\PythonCodes\scientificProject\AAA_itcast\哈工大停用词表.txt", index_col=False,
sep="\t", quoting=3, names=['stopword'],
encoding='utf-8')
# 4 实例化一个转换器类
transfer = CountVectorizer(stop_words=stopwords['stopword'].tolist())
# 5 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
data_new2 = data_new.toarray()
print("data_new2 is: \n", data_new2)
print("特征名字是: \n", transfer.get_feature_names_out())
contest_S is:
[['据', '国际货币基金组织', '(', 'IMF', ')', '预测', ',', '2024', '年', '全球', '经济', '增速', '将', '为', '2.9', ' ', '%', '。'], ['IMF', '建议', ',', '多国', '已', '接近', '其', '紧缩', '周期', '的', '峰值', ',', '不', '需要', '进一步', '收紧', ';', '要', '提高', '长期', '经济', '增速', ',', '需', '通过', '结构性', '改革', '实现', ',', '特别', '是', '侧重于', '治理', '、', '企业', '监管', '和', '对外', '部门', '的', '改革', ';', '多边合作', '有助于', '确保', '所有', '国家', '取得', '更好', '的', '增长', '成果', ';', '各国', '应', '致力于', '限制', '地缘', '经济', '割裂', '、', '努力', '恢复', '对', '基于', '规则', '的', '多边', '框架', '的', '信任', ',', '以', '提高', '透明度', '和', '政策', '确定性', ',', '帮助', '促进', '全球', '共同', '繁荣', '。'], ['相比之下', ',', '经合组织', '(', 'OECD', ')', '对', '世界', '经济', '前景', '较为', '悲观', '。', '据', 'OECD', '最新', '预测', ',', '明年', '全球', '经济', '增速', '将', '放缓', '至', '2.7', ' ', '%', ',', '这', '意味着', '2024', '年', '或', '将', '成为', '自', '2020', '年', '以来', '全球', '经济', '增速', '最低', '的', '一年', '。'], ['OECD', '指出', ',', '美国', '明年', '将', '放慢', '增长', '步伐', ',', '这是', '导致', '全球', '经济', '增长', '放缓', '的', '关键因素', '。', '美国', '经济', '增速', '预计', '将', '从', '2023', '年', '的', '2.4', ' ', '%', ' ', '放缓', '至', '2024', '年', '的', '1.5', ' ', '%', ',', '因为', '美联储', '的', '加息', '举措', '会', '继续', '抑制', '经济', '增长', '。', '美联储', '加息', '大幅', '抬高', '了', '消费者', '和', '企业', '的', '借贷', '成本', '。']]
data_new2 is:
[[1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1]
[0 0 1 0 0 1 1 1 1 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0]
[0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 1 0 0 0 0 1 0 0 0]
[0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 0 0]]
特征名字是:
['2024年全球经济增速将为2' 'imf' 'imf建议' 'oecd' 'oecd指出' '不需要进一步收紧' '以提高透明度和政策确定性'
'企业监管和对外部门的改革' '努力恢复对基于规则的多边框架的信任' '各国应致力于限制地缘经济割裂' '因为美联储的加息举措会继续抑制经济增长'
'多国已接近其紧缩周期的峰值' '多边合作有助于确保所有国家取得更好的增长成果' '对世界经济前景较为悲观' '帮助促进全球共同繁荣'
'据oecd最新预测' '据国际货币基金组织' '放缓至2024年的1' '明年全球经济增速将放缓至2' '特别是侧重于治理' '相比之下'
'经合组织' '美国明年将放慢增长步伐' '美国经济增速预计将从2023年的2' '美联储加息大幅抬高了消费者和企业的借贷成本'
'要提高长期经济增速' '这意味着2024年或将成为自2020年以来全球经济增速最低的一年' '这是导致全球经济增长放缓的关键因素'
'需通过结构性改革实现' '预测']
上面就演示好了 CountVectorizer的简单示例。
接下来,我们演示TF-IDF。
首先,我们定义了一个名为tfidf_demo的函数。这个函数的目的是使用TF-IDF来进行文本特征抽取。
我们获取了一些数据,这些数据是关于生活态度和喜欢的编程语言的描述。
然后,我们创建了一个TfidfVectorizer对象,该对象用于将文本数据转化为TF-IDF特征矩阵。TfidfVectorizer会统计样本中每个词语出现的次数,并计算TF-IDF值。
接下来,我们调用了fit_transform方法,将原始文本数据转化为TF-IDF特征矩阵。然后,我们将特征矩阵打印出来,并打印了特征名字。
from sklearn.feature_extraction.text import TfidfVectorizer
def tfidf_demo():
"""
使用tfidf来进行文本特征抽取
tfidf的主要思想是:如果某个词语在一篇文章中出现的频率高,而在其他文章中出现的频率低,那么这个词语在这篇文章中的重要性就应该高。
相反,如果某个词语在一篇文章中出现的频率低,而在其他文章中出现的频率高,那么这个词语在这篇文章中的重要性就应该低。
也就是说,TF-IDF就是重要程度
TF是词频
IDF是逆文档频率,用来反映一个词语在语料库中的重要程度,IDF越大,说明这个词语在语料库中的重要性越低。
TF-IDF的公式:TF-IDF = TF * IDF
"""
data = ["life is too short, i like like python", "pony is a super super man"]
# 1 实例化一个转换器类
transfer = TfidfVectorizer() # 统计样本中每个词语出现的次数
# 2 调用fit_transform方法,将文本转化为词频矩阵
data_new = transfer.fit_transform(data)
print("data_new is: \n", data_new.toarray())
print("特征名字是: \n", transfer.get_feature_names_out())
这个示例展示了如何使用TF-IDF进行文本特征抽取。TF-IDF是一种统计方法,用以评估一字词对于一个文本集合中一个文本的重要程度。TF(Term Frequency)表示词条在文本中出现的频率,IDF(Inverse Document Frequency)是逆文档频率,用于减少一些常用词的权重。TF-IDF的主要思想是:如果某个词语在一篇文章中出现的频率高,而在其他文章中出现的频率低,那么这个词语在这篇文章中的重要性就应该高。相反,如果某个词语在一篇文章中出现的频率低,而在其他文章中出现的频率高,那么这个词语在这篇文章中的重要性就应该低。
data_new is:
[[0.24395573 0.34287126 0.68574252 0. 0. 0.34287126
0.34287126 0. 0.34287126]
[0.27894255 0. 0. 0.39204401 0.39204401 0.
0. 0.78408803 0. ]]
特征名字是:
['is' 'life' 'like' 'man' 'pony' 'python' 'short' 'super' 'too']