自然语言处理,顾名思义,就是使用计算机对语言文字进行处理的相关技术以及应用。
Natural language processing (NLP) is a field of computer science, artificial intelligence and computational linguistics concerned with the interactions between computers and human (natural) languages, and, in particular, concerned with programming computers to fruitfully process large natural language corpora.
早在20世纪50年代,自然语言处理就被提起,但直到20世纪80年代前,自然语言处理的系统大多仅支持有限的词汇并需要大量的人工编写的规则。到了80年代,机器计算能力的飞速提升以及机器学习算法的出现,为自然语言处理领域带来了变革。隐马可夫模型的使用,以及越来越多的基于统计模型的研究,使得系统拥有了更强的对未知输入的处理能力。如今,研究更多的集中于无监督学习或者语义监督学习,比较成功的便是自动翻译系统。近几年,大数据时代的到来,以及深度学习算法的广泛应用,又为自然语言处理带来了新的突破。
既然如今主流研究使用机器学习或者统计模型的技术,那么一个首要问题就是,如何获取大量的数据?无论是统计还是机器学习,其准确率都建立在样本的好坏上,样本空间是否足够大,样本分布是否足够均匀,这些都将影响算法的最终结果。
获取语料库,一个方法就是去网络上寻找一些第三方提供的语料库,出名的开放语料库比如wiki。但事实上,很多情况中所研究或开发的系统往往是应用于某种特定的领域,这些开放语料库经常无法满足我们的需求。这种时候就需要使用另一种方法,使用爬虫去主动的获取想要的信息。可以使用如pyspider、scrapy等python框架非常轻松地编写出自己需要的爬虫,从而让机器自动地去获取大量数据,从而继续我们的研究。
对于已经获取文本,我们还需要将其进行一定的处理,将其转换为方便计算机识别的数据格式。
对于一些开放语料库,可能有其独特的数据格式,需要我们按照其提示编写代码获取语料。而我们自己去获取的语料,第一步就是要将其转换为文本格式,因为有时候我们获取的是pdf或者html文件。pdf文件,可以使用xpdf将其转换为txt格式的文本,方便我们进行读取;html文件,则可以使用python的beautifulsoup模块或者正则表达式来提取其中的文本。
beautifulsoup模块将html文本中每一个标签转化为对象,获取beautifulsoup的对象后,可以通过直接访问该对象的某一属性获取对应的标签元素或者标签中的内容、属性等。
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc)
# 获取这段html文本中第一个p标签的beautifulsoup对象
print soup.p
# 获取这段html文本中第一个p标签的class属性的值
print soup.p['class']
# 获取beautifulsoup对象中去除html标签的纯文本
print soup.get_text()
不过对于上面的获取方式,如果有多个符合条件的标签元素,该方法只会返回其中的第一个元素。想要获取符合条件的所有html标签,可以使用下面的方式:
# 获取所有该标签的bs对象
soup.find_all('tag_name')
# 获取所有标签中某属性为某值的bs对象
soup.find_all(attr_name='attr_value')
如果只想要满足条件的一个标签,也可以使用soup.find方法。
beautifulsoup还支持比如查找父节点、子节点、兄弟节点等操作,更多api可以前往官方文档查看。
一般而言,相比处理一整个句子的文本,我们更愿意去处理一个词汇组成的列表。那么,我们就需要对句子进行分词。
对英文文本,可以使用python的nltk模块,来进行分词。用pip安装nltk后,还需要在cmd的python交互界面中进行以下操作用来下载分词用的词典。
>>import nltk
>>nltk.download()
下载完成后,就可以来对文本进行分割了
from nltk.tokenize import WordPunctTokenizer
tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
# 将一段文本分割成句子
sentences = tokenizer.tokenize(paragraph)
words = []
# 将每个句子分词,词汇集合加入到列表中
for sentence in sentences:
words.append(WordPunctTokenizer().tokenize(sentence))
对于中文文本,实际上nltk也可以进行分词,但比较麻烦。一个更简单的模块是jieba模块,jieba模块同时还支持用户自己导入词典。
import jieba
# 如有需要,载入自己的字典。字典中每一行为一个单词,可以添加该词的词性
# jieba.load_usrdict('dict.txt')
# 将待分词字符串分割,返回一个迭代器
words = jieba.cut(string_to_cut)
jieba除了简单的分词外,还支持词性标注以及tfidf等算法,有兴趣可以去官方文档查看。
文本中,会存在大量的虚词、代词或者没有特定含义的动词、名词,这些词语对文本分析起不到任何的帮助,我们往往希望能去掉这些“停用词”。
去停用词实际上没有什么模块,因为其本身也不是什么复杂的程序。对于上面的分词算法,你只需要在把每个单词加入集合前判断一下其是否是停用词即可。判断是否为停用词,需要你自己构建一个停用词表,程序运行时将其读入即可。
本篇对自然语言处理做了一个简单的介绍,并讲解了文本的预处理部分。更多自然语言处理技术,以及上文中提到的一些没有展开的部分,可能都会在以后部分中出现。