文本数据预处理:sklearn 中 CountVectorizer、TfidfTransformer 和 TfidfVectorizer

文本数据预处理的第一步通常是进行分词,分词后会进行向量化的操作。在介绍向量化之前,我们先来了解下词袋模型。

 

1.词袋模型(Bag of words,简称 BoW )

 

  词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。

  词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。向量化完毕后一般也会使用 TF-IDF 进行特征的权重修正,再将特征进行标准化。 再进行一些其他的特征工程后,就可以将数据带入机器学习模型中计算。

  词袋模型的三部曲:分词(tokenizing),统计修订词特征值(counting)与标准化(normalizing)。

  词袋模型有很大的局限性,因为它仅仅考虑了词频,没有考虑上下文的关系,因此会丢失一部分文本的语义。

  在词袋模型统计词频的时候,可以使用 sklearn 中的 CountVectorizer 来完成。下面具体说明。

 

2.词频向量化

 

  CountVectorizer 类会将文本中的词语转换为词频矩阵,例如矩阵中包含一个元素a[i][j],它表示j词在i类文本下的词频。它通过 fit_transform 函数计算各个词语出现的次数,通过get_feature_names()可获取词袋中所有文本的关键字,通过 toarray()可看到词频矩阵的结果。

官方文件中提到其参数很多默认值就很好,无需再改动,详细参数设置参见:点击打开链接。例子如下:

from sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer(min_df=1)

corpus = [      'This is the first document.',
    		'This is the second second document.',
    		'And the third one.',
		'Is this the first document?',
		]
X = vectorizer.fit_transform(corpus)
feature_name = vectorizer.get_feature_names()

print (X)
print (feature_name)
print (X.toarray())

输出:

   (0, 1)        1
  (0, 2)        1
  (0, 6)        1
  (0, 3)        1
  (0, 8)        1
  (1, 5)        2
  (1, 1)        1
  (1, 6)        1
  (1, 3)        1
  (1, 8)        1
  (2, 4)        1
  (2, 7)        1
  (2, 0)        1
  (2, 6)        1
  (3, 1)        1
  (3, 2)        1
  (3, 6)        1
  (3, 3)        1
  (3, 8)        1
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']

[[0 1 1 ..., 1 0 1]
 [0 1 0 ..., 1 0 1]
 [1 0 0 ..., 1 1 0]
 [0 1 1 ..., 1 0 1]]

 

  在输出中,左边的括号中的第一个数字是文本的序号i,第2个数字是词的序号j,注意词的序号是基于所有的文档的。第三个数字就是我们的词频。

可以看到一共有9个词,所以4个文本对应的都是9维的特征向量。

由于大部分文本都只会用词汇表中很少一部分的词,因此词向量中有大量的0,也就是说词向量是稀疏的。因此在实际应用中一般使用稀疏矩阵来存储。

3.TF-IDF处理

  然而有些词在文本中尽管词频高,但是并不重要,这个时候就可以用TF-IDF技术。

 

    TF-IDF(Term Frequency–Inverse Document Frequency)是一种用于资讯检索与文本挖掘的常用加权技术。TF-IDF是一种统计方法,用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。

TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上是:TF * IDF。

(1)词频(Term Frequency,TF)指的是某一个给定的词语在该文件中出现的频率。即词w在文档d中出现的次数count(w, d)和文档d中总词数size(d)的比值。

tf(w,d) = count(w, d) / size(d)

这个数字是对词数 (term count) 的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)

(2)逆向文件频率(Inverse Document Frequency,IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。即文档总数n与词w所出现文件数docs(w, D)比值的对数。 

idf = log(n / docs(w, D))

TF-IDF根据 tf 和 idf 为每一个文档d和由关键词w[1]…w[k]组成的查询串q计算一个权值,用于表示查询串q与文档d的匹配度:

tf-idf(q, d) = sum { i = 1..k | tf-idf(w[i], d) } = sum { i = 1..k | tf(w[i], d) * idf(w[i]) }

某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

 

4.用sklearn进行TF-IDF预处理

   第一种方法是在用 CountVectorizer 类向量化之后再调用 TfidfTransformer 类进行预处理。第二种方法是直接用 TfidfVectorizer 完成向量化与 TF-IDF 预处理。

4.1 CountVectorizer 结合 TfidfTransformer

依旧用上面的文本,实现如下:

from sklearn.feature_extraction.text import TfidfTransformer 
from sklearn.feature_extraction.text import CountVectorizer 


corpus = [          'This is the first document.',
		'This is the second second document.',
		'And the third one.',
		'Is this the first document?',
		]


vectorizer=CountVectorizer()


transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus)) 
print (tfidf)

 

输出的各个文本各个词的 TF-IDF 值如下:

 

  (0, 8)        0.438776742859
  (0, 3)        0.438776742859
  (0, 6)        0.358728738248
  (0, 2)        0.541976569726
  (0, 1)        0.438776742859
  (1, 8)        0.272301467523
  (1, 3)        0.272301467523
  (1, 6)        0.222624292325
  (1, 1)        0.272301467523
  (1, 5)        0.853225736145
  (2, 6)        0.28847674875
  (2, 0)        0.552805319991
  (2, 7)        0.552805319991
  (2, 4)        0.552805319991
  (3, 8)        0.438776742859
  (3, 3)        0.438776742859
  (3, 6)        0.358728738248
  (3, 2)        0.541976569726
  (3, 1)        0.438776742859

4.2 用 TfidfVectorizer

实现代码如下:

from sklearn.feature_extraction.text import TfidfVectorizer
tfidf2 = TfidfVectorizer()
re = tfidf2.fit_transform(corpus)
print (re)

输出:

  (0, 8)        0.438776742859
  (0, 3)        0.438776742859
  (0, 6)        0.358728738248
  (0, 2)        0.541976569726
  (0, 1)        0.438776742859
  (1, 8)        0.272301467523
  (1, 3)        0.272301467523
  (1, 6)        0.222624292325
  (1, 1)        0.272301467523
  (1, 5)        0.853225736145
  (2, 6)        0.28847674875
  (2, 0)        0.552805319991
  (2, 7)        0.552805319991
  (2, 4)        0.552805319991
  (3, 8)        0.438776742859
  (3, 3)        0.438776742859
  (3, 6)        0.358728738248
  (3, 2)        0.541976569726
  (3, 1)        0.438776742859 (0, 8)        0.438776742859
  (0, 3)        0.438776742859
  (0, 6)        0.358728738248
  (0, 2)        0.541976569726
  (0, 1)        0.438776742859
  (1, 8)        0.272301467523
  (1, 3)        0.272301467523
  (1, 6)        0.222624292325
  (1, 1)        0.272301467523
  (1, 5)        0.853225736145
  (2, 6)        0.28847674875
  (2, 0)        0.552805319991
  (2, 7)        0.552805319991
  (2, 4)        0.552805319991
  (3, 8)        0.438776742859
  (3, 3)        0.438776742859
  (3, 6)        0.358728738248
  (3, 2)        0.541976569726
  (3, 1)        0.438776742859

 

  

统计个数和计算频率两种方法虽然非常实用,但是也由其局限性导致词汇量可能变得非常大。词汇量过大又将导致需要非常大的矢量来编码文档,从而对内存产生很大的要求,同时拖慢算法的速度。卤煮会在后续的博客中介绍优化方法。

 

 

 

 

 

 

 

参考资料:

http://scikit-learn.org/stable/modules/feature_extraction.html#common-vectorizer-usage

http://www.cnblogs.com/weidagang2046/archive/2012/10/22/tf-idf-from-probabilistic-view.html#top

https://zhangzirui.github.io/posts/Document-14%20(sklearn-feature).md

 

 

 

<think>嗯,用户问的是如何基于多行的txt文本文件生成词频矩阵TF-IDF权重矩阵。我需要一步步理清楚处理流程,然后给出清晰的步骤示例代码。首先,用户可能对自然语言处理的基础不太熟悉,所以得从基本概念讲起,但也要避免太冗长。 首先,得确认用户的需求:处理多个txt文件,每行一个文档,对吗?对的,用户提到“多行txt文本”,可能是指每个文件中的每一行代表一个文档。不过也有可能用户是指多个txt文件,每个文件是一个文档。需要明确这一点。但根据常见情况,可能是指每个文件中的每一行是一个文档,或者多个文件每个文件是一个文档。不过示例代码可能需要处理的是多个文档,比如每个文档一行的情况。比如,可能用户有一个txt文件,里面每一行是一个文档的文本内容。或者多个txt文件,每个文件是一个文档。这里可能需要先明确,但考虑到用户给出的示例可能更倾向于处理单个文件,每行一个文档的情况。 接下来,构建词频矩阵,也就是词袋模型,统计每个文档中的词频。然后转换为TF-IDF矩阵。流程应该是:读取文本数据、分词处理、去除停用词、构建词频矩阵、计算TF-IDF权重。 然后,用户可能需要具体的代码示例,使用Python的sklearn库。因为sklearnCountVectorizerTfidfVectorizer是常用的工具。所以步骤大概是: 1. 读取文本数据:假设每个文档是txt文件中的一行,用Python读取每行。 2. 文本预处理:分词、去除停用词、合并实体等。中文需要分词,英文可能需要分词词干提取。这里可能需要用jieba库处理中文,或者nltk处理英文。 3. 构建词频矩阵:使用CountVectorizer来统计词频,生成文档-词项的矩阵。 4. 计算TF-IDF矩阵:使用TfidfTransformer或者直接使用TfidfVectorizer来转换。 但用户提供的引用中提到了使用gensim的HDP模型,所以可能用户对gensim的流程也感兴趣。不过用户的问题是关于生成词频矩阵TF-IDF矩阵,所以重点可能在sklearn的处理上。但是引用中的示例代码是将TF-IDF矩阵转换为gensim的格式,所以可能需要展示如何生成gensim兼容的格式,或者直接使用sklearn的方法。 需要确保代码示例正确,比如处理中文可能需要分词,而处理英文可能不需要。用户的问题没有明确是中英文,但引用的例子中有中文处理,比如分词、去除停用词,所以可能需要以中文为例,使用jieba分词。 所以步骤可能如下: 1. 读取多行文本:比如,用Python的open函数读取,每行作为一个文档。 2. 分词处理:使用jieba对每行进行分词。 3. 去除停用词:加载停用词表,过滤掉停用词。 4. 构建词频矩阵:使用CountVectorizer,或者手动构建词袋模型。但用sklearnCountVectorizer更方便。 5. 转换为TF-IDF矩阵:使用TfidfTransformer词频矩阵进行转换,或者直接使用TfidfVectorizer。 不过,CountVectorizer本身可以直接处理原始文本,如果使用英文的话,但中文需要先分词,所以需要自定义分词后的处理。这时候,可能需要使用CountVectorizer的tokenizer参数,传入自定义的分词函数。 例如: def tokenize(text): words = jieba.cut(text) return [word for word in words if word not in stopwords] 然后,使用CountVectorizer(tokenizer=tokenize, ...) 来生成词频矩阵。 但需要注意的是,CountVectorizer的tokenizer参数在最新版本中可能需要使用tokenizer的可调用对象,且可能需要处理预处理步骤。 另外,用户可能需要示例代码,所以需要给出完整的代码示例,包括导入库、读取文件、预处理、构建矩阵等步骤。 可能的代码结构: 导入必要的库:jieba,sklearn,pandas等。 读取停用词文件,比如从txt中读取。 定义分词函数,处理每个文档。 读取原始文本文件,每行一个文档。 使用CountVectorizer生成词频矩阵,然后使用TfidfTransformer转换为TF-IDF矩阵,或者直接使用TfidfVectorizer。 然后,可能需要将结果转换为数组或DataFrame以便查看。 另外,用户可能需要了解如何将生成的矩阵保存或查看,比如打印前几行或者转换为DataFrame显示词汇对应的列。 同时,需要处理停用词的问题,比如如何加载停用词表,可能在代码中需要示例。 需要注意,在示例代码中,停用词文件可能需要用户自己准备,或者使用默认的停用词列表,比如中文常用停用词表。 总结步骤: 1. 数据读取:读取多行txt文件,每行作为文档。 2. 中文分词:使用jieba进行分词。 3. 去除停用词:过滤掉停用词表中的词。 4. 构建词频矩阵:使用CountVectorizer生成文档-词项矩阵。 5. 计算TF-IDF权重:使用TfidfTransformer转换词频矩阵,或直接使用TfidfVectorizer。 在代码示例中,需要包括这些步骤。例如: import jieba from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer # 读取数据 with open('data.txt', 'r', encoding='utf-8') as f: docs = [line.strip() for line in f] # 加载停用词 stopwords = set() with open('stopwords.txt', 'r', encoding='utf-8') as f: for line in f: stopwords.add(line.strip()) # 自定义分词函数 def chinese_tokenizer(text): words = jieba.cut(text) return [word for word in words if word not in stopwords and len(word) > 1] # 生成词频矩阵 vectorizer = CountVectorizer(tokenizer=chinese_tokenizer, token_pattern=None) count_matrix = vectorizer.fit_transform(docs) # 转换为TF-IDF矩阵 transformer = TfidfTransformer() tfidf_matrix = transformer.fit_transform(count_matrix) # 转换为DataFrame查看 import pandas as pd tfidf_df = pd.DataFrame(tfidf_matrix.toarray(), columns=vectorizer.get_feature_names_out()) print("词频矩阵示例:") print(count_matrix.toarray()[:3]) print("\nTF-IDF矩阵示例:") print(tfidf_df.iloc[:3, :5]) 这里可能存在一个问题:sklearnCountVectorizer的tokenizer参数可能在新版本中被弃用或者需要特定的处理方式。例如,在较新的版本中,可能需要使用tokenizer函数,并且可能需要禁用token_pattern,否则默认的正则表达式可能会过滤掉中文分词后的结果。所以,在定义vectorizer时,设置token_pattern=None,以避免与默认的正则冲突。 另外,可能需要处理分词后的词语长度,比如过滤掉单字词,如代码中的len(word) > 1。 然后,用户可能需要了解如何将生成的矩阵应用到后续的模型,比如引用中的HDP模型,这时候需要将TF-IDF矩阵转换为gensim的corpus格式。例如,使用gensim的Sparse2Corpus函数。 但用户的问题主要在于生成这两个矩阵,所以这部分可能不需要深入,但可以作为扩展提示。 最后,生成相关问题,比如如何应用这些矩阵进行话题建模,或者如何处理英文文本等。 在思考过程中,还需要检查是否有遗漏的步骤,例如文本预处理中的合并数字或人名,但根据引用中的描述,可能在分词程序中处理了这些。例如,用户引用中的步骤:“文本经过分词程序后,首先去除停用词,合并数字人名等词汇”,但合并可能需要特定的处理,比如使用正则表达式或者自定义函数。但在示例代码中可能没有展示这部分,所以可能需要说明,或者提示用户可以根据需要添加实体识别的步骤。 总结,整个回答的结构应该包括步骤说明、代码示例、结果解读,以及相关问题。需要确保代码正确,特别是处理中文分词停用词的部分,并且代码能够运行。可能需要提醒用户安装必要的库,如jieba、sklearn等。</think>以下是基于多行txt文本构建词频矩阵TF-IDF权重矩阵的分步说明,包含Python代码示例: ### 一、数据预处理流程 1. **读取文本数据** 假设每个txt文件每行为一个文档 2. **分词处理** 使用中文分词工具(如jieba)进行分词 3. **去除停用词** 过滤无意义词汇(的、是、了等)[^3] 4. **特征提取** 统计词频并构建矩阵[^4] ### 二、Python实现代码 ```python import jieba from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer # 读取多行txt文件(示例) docs = [ "自然语言处理是人工智能的重要领域", "TF-IDF是常用的文本特征提取方法", "中文分词需要借助专门的分词工具" ] # 加载停用词表 stopwords = set([line.strip() for line in open("stopwords.txt", encoding="utf-8")]) # 自定义分词函数 def chinese_tokenizer(text): words = jieba.lcut(text) return [word for word in words if word not in stopwords and len(word) > 1] # 生成词频矩阵 vectorizer = CountVectorizer(tokenizer=chinese_tokenizer, token_pattern=None) count_matrix = vectorizer.fit_transform(docs) # 转换为TF-IDF矩阵 transformer = TfidfTransformer() tfidf_matrix = transformer.fit_transform(count_matrix) # 查看结果 print("词袋模型特征:", vectorizer.get_feature_names_out()) print("词频矩阵:\n", count_matrix.toarray()) print("TF-IDF矩阵:\n", tfidf_matrix.toarray()) ``` ### 三、关键输出说明 1. **词频矩阵** 行表示文档,列表示词语,值表示词频(TF)[^2] 2. **TF-IDF矩阵** 通过词频逆向文件频率计算权重值 3. **特征名称** 对应矩阵列的词语列表 ### 四、扩展应用示例 ```python # 转换为gensim兼容格式(用于后续主题模型) from gensim.matutils import Sparse2Corpus corpus = Sparse2Corpus(tfidf_matrix.T) # 需要转置矩阵[^1] ```
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值