EnglishTextMining:Preprocessing英⽂⽂本挖掘:⽂本预处理English Text Mining: Preprocessing
⽂章主⼲来⾃下⾯Reference中的博客,我⾃⼰进⾏了增加整理,感谢所有分享知识的⼤佬们= =
1. Data Collection or Assembly 数据收集
【Given.】20_newsgroups.
数据⽤的是20_newsgroups语料库,下⾯是笔者在数据处理过程遇到的⼀些问题和解决,Python初学者都是泪T T
1.
2.
3. ⼆进制⽂本读取,参数问rb
4. 读取⽂本后遇到的问题:cannot use a string pattern on a bytes-like object。编码问题,尝试decode解码成utf-8,新错误:
UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xff in position 0: illegal multibyte sequence
5. chardet模块检测编码,再解码,使⽤⽅法参见代码
6. 20_newsgroups中atheism中53558⽂件编码有问题,检测不出,选择跳过,如下图:
7. 如果⾃定义了和函数/头⽂件重名的变量则不可调⽤或import,显⽰not callable
8. utf-8类型的str写⼊⽂件open时需指定encoding=’utf-8’
9. :sorted返回的是⼀个list,其中每⼀项为key和value组成的元组
2. Data Preprocessing 数据预处理
2.1 Tokenization & Segmentation 单词化 / 语块化分词
下⾯基本都是单词化分词的⽅法。
2.1.1 Sentence Tokenize(分割句⼦)
实际测试发现似乎没什么意义啊?这⾥不是很明⽩。
1. 直接使⽤sent_tokenize
from sklearn.datasets import fetch_20newsgroups
news = fetch_20newsgroups(subset='train')
X,y = news.data,news.target
text = X[0]
kenize import sent_tokenize
sent_tokenize_list = sent_tokenize(text)
print(sent_tokenize_list)
2. 使⽤kenize.punkt中包含了很多预先训练好的tokenize模型。
from sklearn.datasets import fetch_20newsgroups
news = fetch_20newsgroups(subset='train')
X,y = news.data,news.target
print(X[0])
news = X[0]
2.1.2 Word Tokenize(分割单词)
kenize import word_tokenize
text='The cat is walking in the bedroom.'
sent_tokenize_list = word_tokenize(text)
print(sent_tokenize_list)
将句⼦分割成词。⾸先⽤正则表达式可以⾃⼰完成;如果要利⽤已有⼯具,Python NLTK中的word_to
kenize(),这个⽅式就是前⽂提到的Penn TreeBank语料库所使⽤的分词⽅法。听起来是不是很⾼⼤上,我是不会告诉你其实它也是正则表达式实现的。分词其实主要⼲了这么⼏个事:
将’分开. don’t -> do n’t, they’ll -> they ‘ll;
将⼤部分标点当作单独的⼀个词;
将后⼀位是逗号或者引号的词分开;
单独出现在⼀⾏的句号分开。
中⽂分词区别⽐较⼤,可以采⽤斯坦福或者ICTCLAS(中科院背景)的⽅案。
可参考:
New York 会变成 new + york,这个是单词化⽽不是语块化的问题
2.2 Normalization 数据标准化
2.2.1 Noise Removal ⾮⽂本数据去除
【Skip.】对于⾃⼰爬⾍爬下来的⽂本(如HTML格式)需要做⾮⽂本数据去除。
这⼀步主要是针对我们⽤爬⾍收集的语料数据,由于爬下来的内容中有很多html的⼀些标签,需要去掉。少量的⾮⽂本内容的可以直接⽤Python的正则表达式(re)删除, 复杂的则可以⽤beautifulsoup来去除。另外还有⼀些特殊的⾮英⽂字符(non-alpha),也可以⽤Python的正则表达式(re)删除。
2.2.2 Spell Check 拼写检查
【Skip.】由于英⽂⽂本中可能有拼写错误,因此⼀般需要进⾏拼写检查。如果确信我们分析的⽂本没有拼写问题,可以略去此步。
拼写检查,我们⼀般⽤pyenchant类库完成。pyenchant的安装很简单:”pip install pyenchant”即可。
对于⼀段⽂本,我们可以⽤下⾯的⽅式去出拼写错误:
from enchant.checker import SpellChecker
chkr = SpellChecker("en_US")
chkr.set_text("Many peope likee to watch In the Name of People.")
for err in chkr:
print "ERROR:", err.word
输出是:
ERROR: peope
ERROR: likee
出错误后,我们可以⾃⼰来决定是否要改正。当然,我们也可以⽤pyenchant中的wxSpellCheckerDialog类来⽤对话框的形式来交互决定是忽略,改正还是全部改正⽂本中的错误拼写。⼤家感兴趣的话可以去研究pyenchant的官⽅⽂档。
2.2.3 Part-Of-Speech Tagging and POS Tagger(对词进⾏标注)
lemmatization在词性标注后效果⽐较好。
参考:
kenize import word_tokenize #tokens是句⼦分词后的结果,同样是句⼦级的标注
text='The cat is walking in the bedroom.'
sent_tokenize_list = word_tokenize(text)
print(sent_tokenize_list)
pos_tag = nltk.pos_tag(sent_tokenize_list)
print(pos_tag)
2.2.4 Stemming / Lemmatization 词⼲提取/词形还原
Lemmas differ from stems in that a lemma is a canonical form of the word, while a stem may not be a real word.
先词形还原后词⼲提取,归⼀化不同词性的单词。仅词形还原可能会有复数还原不全的问题。
词⼲提取(stemming)和词型还原(lemmatization)是英⽂⽂本预处理的特⾊。两者其实有共同点,即都是要到词的原始形式。只不过词⼲提取(stemming)会更加激进⼀点,它在寻词⼲的时候可以会得到不是词的词⼲。⽐如”imaging”的词⼲可能得到的是”imag”, 并不是⼀个词。⽽词形还原则保守⼀些,它⼀般只对能够还原成⼀个正确的词的词进⾏处理。个⼈⽐较喜欢使⽤词型还原⽽不是词⼲提取。
在实际应⽤中,⼀般使⽤nltk来进⾏词⼲提取和词型还原。安装nltk也很简单,”pip install nltk”即可。只不过我们⼀般需要下载nltk的语料库,可以⽤下⾯的代码完成,nltk会弹出对话框选择要下载的内容。选择下载语料库就可以了。
import nltk
nltk.download()
在nltk中,做词⼲提取的⽅法有PorterStemmer,LancasterStemmer和SnowballStemmer。个⼈推荐使⽤SnowballStemmer。这个类可以处理很多种语⾔,当然,除了中⽂。
from nltk.stem import SnowballStemmer
stemmer = SnowballStemmer("english") # Choose a language
stemmer.stem("countries") # Stem a word
输出是”countri”,这个词⼲并不是⼀个词。
⽽如果是做词型还原,则⼀般可以使⽤WordNetLemmatizer类,即wordnet词形还原⽅法,Lemmatization 把⼀个任何形式的语⾔词汇还原为⼀般形式,标记词性的前提下效果⽐较好。
from nltk.stem import WordNetLemmatizer
wnl = WordNetLemmatizer()
print(wnl.lemmatize('countries'))
输出是”country”,⽐较符合需求。在实际的英⽂⽂本挖掘预处理的时候,建议使⽤基于wordnet的词形还原就可以了。
在有个词⼲提取和词型还原的demo,如果是这块的新⼿可以去看看,上⼿很合适。
PS:另⼀个demo:
import nltk
sent1='The cat is walking in the bedroom.'
sent2='A dog was running across the kitchen.'
tokens_1=nltk.word_tokenize(sent1)
print (tokens_1)
stemmer = nltk.stem.PorterStemmer()
stem_1 = [stemmer.stem(t) for t in tokens_1]
print(stem_1)
⼜另⼀个demo:
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
elif treebank_tag.startswith('V'):
return wordnet.VERB
elif treebank_tag.startswith('N'):
return wordnet.NOUN
elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return None
python官方文档中文版def lemmatize_sentence(sentence):
res = []
lemmatizer = WordNetLemmatizer()
for word, pos in pos_tag(word_tokenize(sentence)):
wordnet_pos = get_wordnet_pos(pos) or wordnet.NOUN
res.append(lemmatizer.lemmatize(word, pos=wordnet_pos))
return res
2.2.5 Set All Characters to Lowercase 转化为⼩写
由于英⽂单词有⼤⼩写之分,我们期望统计时像“Home”和“home”是⼀个词。因此⼀般需要将所有的词都转化为⼩写。这个直接⽤python的API(.lower())就可以搞定。
2.2.6 Remove Stop Words 去除停⽤词
在英⽂⽂本中有很多⽆效的词,⽐如“a”,“to”,⼀些短词,还有⼀些标点符号,这些我们不想在⽂本分析的时候引⼊,因此需要去掉,这些词就是停⽤词。个⼈常⽤的英⽂停⽤词表下载地址在这。当然也有其他版本的停⽤词表,不过这个版本是我常⽤的。
在我们⽤scikit-learn做特征处理的时候,可以通过参数stop_words来引⼊⼀个数组作为停⽤词表。这个⽅法和前⽂讲中⽂停⽤词的⽅法相同,这⾥就不写出代码,⼤家参考前⽂即可。
pus import stopwords #去停⽤词
cachedStopWords = stopwords.words("english")
wordStoped = []
for word in words: #去停⽤词 words是分句分词后的句⼦级别处理结果
filtered = [w for w in word if (w not in cachedStopWords)]
wordStoped.append(filtered)
3. Data Exploration & Visualization 特征处理
现在我们就可以⽤scikit-learn来对我们的⽂本特征进⾏处理了,在⽂本挖掘预处理之向量化与Hash Trick中,我们讲到了两种特征处理的⽅法,向量化与Hash Trick。⽽向量化是最常⽤的⽅法,因为它可以接着进⾏TF-IDF的特征处理。在⽂本挖掘预处理之TF-IDF中,我们也讲到了TF-IDF特征处理的⽅法。
TfidfVectorizer类可以帮助我们完成向量化,TF-IDF和标准化三步。当然,还可以帮我们处理停⽤词。这部分⼯作和中⽂的特征处理也是完全相同的,⼤家参考前⽂即可。注:即Reference中1的⼤佬博客。
4. Model Building & Evaluation 建⽴分析模型
有了每段⽂本的TF-IDF的特征向量,我们就可以利⽤这些数据建⽴分类模型,或者聚类模型了,或者进⾏主题模型的分析。此时的分类聚类模型和之前讲的⾮⾃然语⾔处理的数据分析没有什么两样。因此对应的算法都可以直接使⽤。
5. Code 源码
源码下载:
>>>>##
#!/usr/bin/python
# -*- coding: utf-8 -*-
# By Galo
>>>>##
import os
import nltk
pus import wordnet
from nltk.stem import WordNetLemmatizer #词性还原
kenize import sent_tokenize #分句
kenize import word_tokenize #分词
pus import stopwords #去停⽤词
from nltk.stem import SnowballStemmer #词⼲提取
from sklearn. import TfidfVectorizer #TFIDF
import chardet #检测编码格式
import re #匹配去标点符号,特殊字符
#nltk.download() #下载nltk的语料库
cachedStopWords = stopwords.words("english") #选⽤英⽂停⽤词词典
def read_files(path):
# 读取语料⽂件夹下所有⽂件内容(此处为⼆进制⽂件)
# 所有⽂件内⽂本组合成⼀个string存⼊all_text
files= os.listdir(path) # 得到⽂件夹下的所有⽂件名称
all_text = ""
for file in files: # 遍历⽂件夹
if not os.path.isdir(file): # 判断是否是⽂件夹,不是⽂件夹才打开
with open(path+"/"+file, "rb") as f: # ⼆进制格式⽂件参数为rb
text = f.read()
encode_type = chardet.detect(text) # 检测编码格式
if encode_type['encoding'] != None: # 排除不能解码的情况
text = text.decode(encode_type['encoding']) # 进⾏相应解码,赋给原标识符(变量)
print(file,'done.') # 标识⽂件读取完毕
all_text = all_text + text
return all_text
'''
#这⼀部分先分句后分词,后来实测没啥⽤好像,因为数据结构变复杂,所以舍弃了
sentences = sent_tokenize(atheism)
#分句,将⽂本拆分成句⼦级别
with open('C:\\Users\\Administrator\\Desktop\\Preprocessing\\sentences_atheism_', 'w',encoding='utf-8') as f:
for sentence in sentences:
f.write(str(sentence))
print('Sentences written.')
words = []
for sentence in sentences:
sentence = re.sub("[+:\.\!\/_,$%^*(+\"\'<>]+|[+——!,。?、~@#¥%……&*()]+", " ", sentence)
#去标点
words.append(word_tokenize(sentence))
#分词,对句⼦进⾏分词,tokenize的分词是句⼦级别的,需要对⽂本先进⾏分句,否则效果会很差没看出效果有差啊
with open('C:\\Users\\Administrator\\Desktop\\Preprocessing\\words_atheism_', 'w',encoding='utf-8') as f:
for word in words:
f.write(str(word))
print('Words written.')
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论