自然语言处理(NLP)-NLTK入门学习(一)

自从看了吴军的《数学之美》,被其中的数学算法在IT发展历程中的应用后,发现NLP的算法其实不仅仅是语音检测单一的应用场景,所以下定决心买两本书来学习一下,这里先从NLTK开始,写的不好,欢迎大家拍砖。

还是先说说自然语言处理(NLP),NLP与教孩子学语言的过程非常相似,其大多数任务都是对单词、语句的理解,形成语法和结构都正确的语句等,这些任务对于人类来说都是非常自然的事情,但是对于NLP来说,其中一些任务就转化成为了标识化处理,语块分解,词性标注,语法解析等工作。

下面列举一些NLP应用的实例,我相信大家基本上都用过了:

1. 拼写提示,修正(word,搜狗输入法)

2. 搜索引擎(Google,Bing, Yahoo!,Baidu)

3. 语音引擎(Siri, 小冰)

4. 垃圾邮件分类

5. 新闻订阅

6. 机器翻译(Google,Youdao)

这里选择NLTK(Natual Language Tool Kit)作为学习的开始,主要有两个原因:1. Python的相对是比较容易学习的语言;2. NLTK现在已经是NLP社区中最流行的工具之一。

下面进入正文,以上只是背景介绍,以后的文章里不会再出现。

文本数据提取

首先我们需要从数据源那里把数据提取出来,当然实际生产环境中的数据源是多种多样的,包括csv,Json,PDF,database, HTML。这里就其中几个举例示意。

1. csv 数据提取

样本数据:
['2018-06-11', '1041902', 'xxx', '', '', '812919', 'BASIC', '2018-05-14 11:50:56', '', '', '', '', '', '', '', '0']

['2018-06-11', '1041965', 'xxx', '', '', '73573510', 'PLUS', '2018-05-15 16:11:45', '', '', '', '', '', '', '', '0']

代码:

import csv
with open("../../data/test01.csv") as f:
    reader = csv.reader(f, delimiter=';', quotechar='"')
    for line in reader:
        print(line)

2. Json 数据提取

样本数据:

 
 
{
  "array": [1,2,3,4],
  "boolean":"True",
  "object": {
    "a": "b",
    "c":123
  },
  "string": "Hello world!"
}

代码:

import json
with open("../../data/test01.json") as f:
    data = json.load(f)
    print(data)
    print(data["boolean"])

这里的json可能有些不实用,因为大部分情况json数据都是出现在Web API数据获取中,所以在提取前一定是需要使用urllib去call 那个APiece才能获取一个数据流,然后再进行数据解析。

数据库的链接和数据提取这里就不掩饰,其官网的文档已经写的很清楚了,后期有空的话会继续补充一个PDF中数据提取,因为很多上市公司的发布的财报都是PDF格式的。

4. pdf

5. 语句分离

这里需要额外提到语句分离,因为在别的格式化比较整齐的非文本数据中是不需要用到这一步的,所以需要提出来单独做一下。

首先你需要下载一个nltk_data,只需要在代码中加入:

import nltk
nltk.download()

它就会弹窗提示下载,点击dwonload即可。否则会提示:Resource punkt not found.

下面是其断句的示例代码:

input_str = "Today is a good day. It is sunny. I want to go to study in the conpany."
from nltk.tokenize import sent_tokenize
all_sent = sent_tokenize(input_str)
print(all_sent)
当然这个断句也可以通过机器学习的方法去实现智能识别,这里就不展开描述了。


数据预处理

数据预处理几乎是所有做数据分析的必须要完成的工作,但是NLP有些说法上和工作分类上有些不同。这里的数据预处理步骤分为:标识化处理词干提取词性还原以及停用词移除

1. 标识化处理

标识化这里指的是将原生字符串分割成一系列有意义的分词。标识化处理的复杂性因具体的NLP应用而异。例如英语中可以使用正则表达式选取纯单词内容和数字。但是在亚洲语言(包括:中文和日文)中,这会是一个非常复杂的任务。

这里展示几个NLTLK中的标识器的示例:

代码:

input_str = "Hi everyone! Hola gr8 &*$"
print(input_str.split())
from nltk.tokenize import word_tokenize, regexp_tokenize, wordpunct_tokenize, blankline_tokenize
output_str = word_tokenize(input_str)
print('word_tokenize: ')
print(output_str)
output_str = regexp_tokenize(input_str, pattern='\w+')
print('regexp_tokenize: ')
print(output_str)
output_str = regexp_tokenize(input_str, pattern='\d+')
print('regexp_tokenize: ')
print(output_str)
output_str = wordpunct_tokenize(input_str)
print('wordpunct_tokenize: ')
print(output_str)
output_str = blankline_tokenize(input_str)
print('blankline_tokenize: ')
print(output_str)

输出结果:

['Hi', 'everyone!', 'Hola', 'gr8', '&*$']
word_tokenize: 
['Hi', 'everyone', '!', 'Hola', 'gr8', '&', '*', '$']
regexp_tokenize: 
['Hi', 'everyone', 'Hola', 'gr8']
regexp_tokenize: 
['8']
wordpunct_tokenize: 
['Hi', 'everyone', '!', 'Hola', 'gr8', '&*$']
blankline_tokenize: 
['Hi everyone! Hola gr8 &*$']

当然也可以直接使用split()来划分,但是其本身很难被配置为一些较为复杂的标识化处理过程。

推荐参考网站:http://text-processing.com/demo

2. 词干提取(streaming)

这里的词干提取其实是一种基于规则的较为粗糙的处理过程。例如eat eaten eating 其实都是在说吃这个动作,在某些应用场景中我们没有必要去区分他们。

这里展示两个:

from nltk.stem import PorterStemmer
from nltk.stem.lancaster import LancasterStemmer
from nltk.stem.snowball import SnowballStemmer
pst = PorterStemmer()
lst = LancasterStemmer()
print(lst.stem("eating"))
print(pst.stem("shopping"))

如果是英语环境,那么Poster就够用了,要是其它语言,可以考虑使用Snowball提取器,其支持荷兰语,英语,法语,德语,意大利语,葡萄牙语,罗马尼亚语和俄语等。

3. 词性还原(lemmatization 也叫:lemma)

词性还原是一种更条理化的方法,它涵盖了词根所有的文法和变化形式。词性还原操作会利用上下文语境和词性来确定相关单词的变化形式,并运用不同的标准化规则,根据词性来获取相关的词根。

代码:

from nltk.stem import WordNetLemmatizer
wlem = WordNetLemmatizer()
res = wlem.lemmatize("ate")
print(res)

4. 停用词移除

这个步骤的思路就是简单地移除语料库中的在所有文档中都会出现的单词。通常情况下,冠词和代词都会被列为停用词。这些词在NLP中的大多数场景都是毫无意义的。NLTK库中内置了22种语言的停用词列表。

代码:

from nltk.corpus import stopwords
stopwords = list(set(stopwords.words('english')))
text = "This is just a test for learning NLP."
clean_words=[word for word in text.split() if word not in stopwords]
print(clean_words)
结果:

['This', 'test', 'learning', 'NLP.']

5. 罕见词移除

主要针对一些罕见的word进行清除,比如说名称,品牌,产品名称,某些噪音字符,例如html里的左缩进等。这里调用FreqDist()函数获取了相关术语在语料库中的分布情况,并选取了其中最稀有的一些词形成了一个列表,并用它来过滤我们的原始语料库,当然,我们也可以用它对单一文档执行同样的操作。

代码:

import nltk
from bs4 import BeautifulSoup
from nltk.tokenize import regexp_tokenize
import urllib
response = urllib.request.urlopen('https://docs.python.org/2/library/re.html')
html = response.read().decode('UTF-8')
soup = BeautifulSoup(html, 'lxml')
clean = regexp_tokenize(soup.getText(), pattern='\w+')
# clean = nltk.clean_html(html)
tokens = [token for token in clean]
freq_dist = nltk.FreqDist(tokens)
rare_word = freq_dist.keys()
after_rare_words = [word for word in tokens not in rare_word]

6. 拼写纠错

相信这个步骤是最常见的了,比如,百度搜索时会在用户打错字了或者拼错了的时候给用户一个提示或者推荐,这里就是类似的拼写检查器。可以通过纯字典查找的方式来创建一个非常基本的拼写检查器,业界已经又专门为此类应用开发的一些增强型字符串算法,用于一些模糊的字符串匹配。

代码:

from nltk.metrics import edit_distance

a = edit_distance("rain", "shine")
b = edit_distance("good", "god")
print(a, b)


猜你喜欢

转载自blog.csdn.net/maizi1045/article/details/80718224
今日推荐