文本预处理和计算TF-IDF值
Posted August1s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文本预处理和计算TF-IDF值相关的知识,希望对你有一定的参考价值。
计算文档的TF-IDF值
参考链接:
英文文本挖掘预处理流程总结,文本挖掘预处理之向量化,文本挖掘预处理之TF-IDF
1.TF-IDF
TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率)。
是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降.
上述引用总结就是, 一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章.
词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否.)
但是, 需要注意, 一些通用的词语对于主题并没有太大的作用, 反倒是一些出现频率较少的词才能够表达文章的主题, 所以单纯使用是TF不合适的。权重的设计必须满足:一个词预测主题的能力越强,权重越大,反之,权重越小。所有统计的文章中,一些词只是在其中很少几篇文章中出现,那么这样的词对文章的主题的作用很大,这些词的权重应该设计的较大。IDF就是在完成这样的工作.
词频的计算公式:
逆向文件频率 (inverse document frequency, IDF) IDF的主要思想是:如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。
公式:
其中,分子是语料库中的文件总数,分母是包含词语的文件数目(即目的文件数目)。如果该词语不在语料库中,就会导致分母为零,因此一般情况下分母要+1,即:
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
公式:
2.文本预处理
为了计算文本的TF-IDF值,我们需要将待处理的文本转化成比较好处理的形式。
a.除去非文本部分
在一篇文章中,总会有很多的空格和标点符号,比如;,"等等,这里我们处理的方式非常简单,只需要使用正则表达式的sub函数,将非文本部分代替为空格即可。
def Filter_text(text):
str = re.sub(\'[^a-zA-Z]\', \' \', text)
return re.sub(r\'\\s+\', \' \', str)
除此之外,还需要大小写转换
def Lower_text(text):
return text.lower()
b.词形还原
我们利用词形还原的方法,将文本中的词转化为相同的形式,这样才能更好地计算TF值。比如,country和countries其实是表达的相同的意思,但是如果不做词形还原,他们的TF值就会分别被计算。在实际应用中,一般使用nltk的WordNetLemmatizer类来进行词型还原。词形还原代码如下
# 使用WordNetLemmatizer类,即wordnet词形还原方法
def Lemmatization_text(text_cut_list):
wnl = WordNetLemmatizer()
return [wnl.lemmatize(n) for n in text_cut_list]
这里,由于词形还原是以一个list为单位进行的,因此在之前我们要进行一个转化
# 将article中的文章转化成由单词构成的list
def text_cut(text):
return re.findall(\'[a-zA-z]+\', text)
在有些程序里,我们也使用词干提取来进行类似的操作。事实上,词干提取(stemming)和词型还原(lemmatization)是英文文本预处理的特色。两者其实有共同点,即都是要找到词的原始形式。只不过词干提取(stemming)会更加激进一点,它在寻找词干的时候可以会得到不是词的词干。比如"imaging"的词干可能得到的是"imag", 并不是一个词。而词形还原则保守一些,它一般只对能够还原成一个正确的词的词进行处理。词干提取还有PorterStemmer,LancasterStemmer和SnowballStemmer等方法,这里我没有用到,因此不做说明。
c.停用词处理
一篇文章中有很多无效的词,比如“a”,“to”,一些短词,还有一些标点符号,这些我们不想在文本分析的时候引入,因此需要去掉,这些词就是停用词。在我们用scikit-learn做特征处理的时候,可以通过参数stop_words来引入一个数组作为停用词表。
# 过滤停用词以及长度小于3的词
def Stopwords_text(text_cut_list):
Stop_Word_list = stopwords.words("english")
return [n for n in text_cut_list if n not in Stop_Word_list and len(n) >= 3]
计算TF-IDF的值
在scikit-learn中,有两种方法进行TF-IDF的预处理。第一种方法是在用CountVectorizer类向量化之后再调用TfidfTransformer类进行预处理。第二种方法是直接用TfidfVectorizer完成向量化与TF-IDF预处理。
用CountVectorizer类向量化其实是一种统计词频的方法,第一种方法的过程就是,先统计词频,再计算TF-IDF。代码很简单,如下:
def TF_IDF_count(text):
vectorizer = CountVectorizer()
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(text))
word = vectorizer.get_feature_names() # 所有文本的关键字
weight = tfidf.toarray() # 对应的tfidf矩阵
return [(word[j], float(weight[0][j])) for j in range(len(word))]
用第二种方法的话,就是用TfidfVectorizer一步到位,类似的代码如下:
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf2 = TfidfVectorizer()
re = tfidf2.fit_transform(corpus)
代码
最后的代码如下:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re
from nltk.stem import WordNetLemmatizer
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
# 导入文章到list
def Insert_text():
L = []
with open(\'E:/pypy/TF-IDF/101666.txt\', \'r\') as f:
L.append(f.read())
return L
# 将text中的标点符号和数字过滤
# 第二次过滤合并多个空格
def Filter_text(text):
str = re.sub(\'[^a-zA-Z]\', \' \', text)
return re.sub(r\'\\s+\', \' \', str)
# 将大写转化为小写
def Lower_text(text):
return text.lower()
# 使用WordNetLemmatizer类,即wordnet词形还原方法
def Lemmatization_text(text_cut_list):
wnl = WordNetLemmatizer()
return [wnl.lemmatize(n) for n in text_cut_list]
# 将article中的文章转化成由单词构成的list
def text_cut(text):
return re.findall(\'[a-zA-z]+\', text)
# 过滤停用词以及长度小于3的词
def Stopwords_text(text_cut_list):
Stop_Word_list = stopwords.words("english")
return [n for n in text_cut_list if n not in Stop_Word_list and len(n) >= 3]
# 计算TF-IDF
def TF_IDF_count(text):
vectorizer = CountVectorizer()
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(text))
word = vectorizer.get_feature_names() # 所有文本的关键字
weight = tfidf.toarray() # 对应的tfidf矩阵
return [(word[j], float(weight[0][j])) for j in range(len(word))]
def main():
article = Insert_text()
article[0] = Filter_text(article[0])
article[0] = Lower_text(article[0])
word_cut = Lemmatization_text(text_cut(article[0]))
word_cut = Stopwords_text(word_cut)
# print(Stopwords_text(word_cut))
article[0] = \'\'
for w in word_cut:
article[0] = article[0] + w + \' \'
L = TF_IDF_count(article)
print(sorted(L, key=lambda x: (x[1]), reverse=True))
if __name__== "__main__":
print(\'test\')
main()
以上是关于文本预处理和计算TF-IDF值的主要内容,如果未能解决你的问题,请参考以下文章