Python自然语言处理学习笔记

2021-04-29  本文已影响0人  creepycool

1. 用Python处理自然语言

1.1. 安装nltk

nltk是一个基于Python的自然语言处理工具集,主要用于英文的自然语言处理。

nltk为超过50个语料库和词汇资源(如WordNet)提供易于使用的接口,以及一套用于分类、标记化、词干化、标记、解析和语义推理的文本处理库,用于工业级NLP库的包装器,以及一个活跃的讨论论坛。

  1. 创建用于学习nlp的python虚拟环境
$ cd ~
$ mkdir venv
$ cd venv
$ python3 -m venv nlp
$ source nlp/bin/activate
  1. 安装nltk
    我这里使用了豆瓣源来加速安装过程
$ pip install nltk -i https://pypi.douban.com/simple
  1. 验证并下载nltk_data
$ python
import nltk
nltk.download('all')

下载nltk_data对外网环境有一定要求,有条件的同学可以挂代理下载,我是通过proxychains来对Python解释器进行的代理。

1.2. 常用函数

1.3. 简单的统计

>>> fq = nltk.FreqDist(text1)
>>> fq
FreqDist({',': 18713, 'the': 13721, '.': 6862, 'of': 6536, 'and': 6024, 'a': 4569, 'to': 4542, ';': 4072, 'in': 3916, 'that': 2982, ...})
>>> hp = fq.hapaxes()
>>> hp[:10]
['Herman', 'Melville', ']', 'ETYMOLOGY', 'Late', 'Consumptive', 'School', 'threadbare', 'lexicons', 'mockingly']
>>>

</details>

通过两个方法的结合使用,我们可以排除大部分的无需参考的词汇,有助于减少我们的分析量,很好地帮助我们排除了干扰词汇,更好的去寻找文章的中心主旨。

1.4. 细粒度划分

细粒度划分是将剩余的重要词汇进行细粒度选择。

  1. 条件划分
    [w for w in v if condition]
  2. 双连词查询
    text1.collocations():查找双连词,是为了我们进行分词和词性标记的时候,能够准确的标记我们的双连词,red wine的例子。
    <details>
    <summary>示例 Click to expand</summary>
>>> text1.collocations()
Sperm Whale; Moby Dick; White Whale; old man; Captain Ahab; sperm
whale; Right Whale; Captain Peleg; New Bedford; Cape Horn; cried Ahab;
years ago; lower jaw; never mind; Father Mapple; cried Stubb; chief
mate; white whale; ivory leg; one hand
>>> v = set(text1)
>>> word = [w for w in v if len(w) > 15]
>>> word
['superstitiousness', 'uncompromisedness', 'supernaturalness', 'hermaphroditical', 'apprehensiveness', 'cannibalistically', 'irresistibleness', 'uncomfortableness', 'characteristically', 'undiscriminating', 'subterraneousness', 'Physiognomically', 'responsibilities', 'physiognomically', 'simultaneousness', 'circumnavigating', 'preternaturalness', 'circumnavigation', 'circumnavigations', 'indispensableness', 'uninterpenetratingly', 'CIRCUMNAVIGATION', 'comprehensiveness', 'indiscriminately']
>>>

</details>

1.5. 细粒度划分的条件

2. 获取文本语料和词汇资源

2.1. 语料库操作相关函数

为了操作文本语料和词汇资源,介绍nltk语料库相关函数的使用。

2.2. 常用语料库介绍

2.3. 导入自己的语料库

新建一个目录如test/,在test/目录下新建文件1.txt,文件内容为Hello world

from nltk.corpus import PlaintextReader
# 语料库目录
path = '/test'
# 导入
myself = PlaintextReader(path, '.*')

2.4. 简单的条件频率分布与图表绘制

nltk支持生成plot图表,参考如下实例:

# 实验:对比不同语言翻译的同一个文本中,每个词汇的字母个数的不同,并且绘制图表。
from nltk.corpus import udhr
import nltk
languages = ['Chickasaw', 'English', 'German_Deutsch', 'Greenlandic_Inuktikut', 'Hungarian_Magyar']

cfd = nltk.ConditionalFreqDist(
    (lang, len(word))
    for lang in languages
    for word in udhr.words(lang+'-Latin1')
)

cfd.plot()

3. 原料文本的处理加工

3.1. 网络读取文件处理HTML

3.2. 对搜索引擎与RSS订阅的处理

3.3. 读取本地文件与NLP流程介绍

读取本地文件

NLP流程

参考如下截图:

image

使用Unicode进行文本处理

使用codecs库进行编码文件的读取。

import nltk
import codecs
path = nltk.data.find('corpora/unicode_samples/polish-lat2.txt')
f = codecs.open(path, encoding='latin2')
for line in f:
  line = line.strip()
  print(line.encode('unicode_escape'))

使用正则表达式进行词干提取

基本元字符

查找以ed结尾的单词

import re
import nltk
wl = [w for w in nltk.corpus.words.words('en') if w.islower()]
[w for w in wl if re.search('ed$', w)]

范围与闭包

模拟英文键盘九宫格联想输入法

[w for w in wl if re.search('^[ghi][mno][jlk][def]$', w)]

提取字符块

word = 'ajgsdjguwgnagjwglagvjdsajlkgkqj'
re.findall(r'[aeiou]', word)

wsj = sorted(set(nltk.corpus.treebank.words()))
fd = nltk.FreqDist(vs for word in wsj 
        for vs in re.findall(r'[aeiou]{2,}', word))
fd.items()

查找词干

def stem(word):
  regexp = r'(.*?)(ing|ly|ed|ious|ies|ive|es|s|ment)?$'
  stem, suffix = re.findall(regexp, word)[0]
  return stem

raw = """DENNIS: Listen, strange women lying in ponds distributing swords 
is no basis for a system of government. Supreme executive power derives from
a mandate from the messes, not from farcical aquatic cermony. """
tokens = nltk.word_tokenize(raw)
[stem(t) for t in tokens]

NLTK词干提取器

注意比较这两个提取器的异同

import nltk
porter = nltk.PorterStemmer()
lancaster = nltk.LancasterStemmer()

raw = """DENNIS: Listen, strange women lying in ponds distributing swords 
is no basis for a system of government. Supreme executive power derives from
a mandate from the messes, not from farcical aquatic cermony. """
tokens = nltk.word_tokenize(raw)

[porter.stem(t) for t in tokens]
[lancaster.stem(t) for t in tokens]

实际中根据提取器在文本中的表现而选择,选择准确率较高的。

使用正则表达式为文本分词

了解一下NLTK的正则表达式分词器

text = 'That U.S.A. poster-print costs $12.40'
# 视频里正则表达式太复杂了,字体显示也不清楚,这里就随便敲个U代替了
pattern = r'U'
nltk.regexp_tokenize(text, pattern)

词汇分类与词汇标注

使用词性标注器

一个词性标注器(part-of-speech tagger或POS tagger)处理一个词序列,为每个词附加一个词性标记。

import nltk
text = nltk.word_tokenize('And now for something completely different')
nltk.pos_tag(text)

对语料库进行词性标注

有的语料库自带了词性标注,比如brown语料库。

查询已标记的语料库:

import nltk
nltk.corpus.brown.tagged_words()
nltk.corpus.nps_chat.tagged_words()

自动标注-默认标注

最基础的标注器,90%情况下不使用默认标注器。
10%情况,前提,尽可能对所有词进行标注,可以用默认标注器对陌生的词汇进行标注。

import nltk
from nltk.corpus import brown
tags = [tag for (word, tag) in brown.tagged_words(categories='news')]
nltk.FreqDist(tags).max()

raw = 'I do not like green eggs and han, I do not like the Sam I an!'
tokens = nltk.word_tokenize(raw)
f = nltk.DefaultTagger('NN')
# 会将所有tokens标注为NN
f.tag(tokens)

自动标注-正则表达式标注

import nltk
from nltk.corpus import brown
brown_sents = brown.sents(categories='news')
patterns = [
  (r'.*ing$', 'VBG'),
  (r'.*ed$', 'VBD'),
  (r'.*', 'NN')
]
reg_tagger = nltk.RegexpTagger(patterns)

reg_tagger.tag(brown_sents[3])

N-gram标注

常用,利用已有的标注好的语料库,预测未知的文本的词性。

import nltk
from nltk.corpus import brown
brown_tagged_sents = brown.tagged_sents(categories='news')
brown_sents = brown.sents(categories='news')
f = nltk.UnigramTagger(brown_tagged_sents)
f.tag(brown_sents[2007])

从文本中提取有用的信息并分析

信息提取介绍

信息有很多种“形状”和“大小”。一个重要的形式是结构化数据:实体和关系的可预测的规范的结构。例如:我们可能对公司和地点之间的关系感兴趣。给定一个公司,我们希望能够确定它做业务的位置;反过来,给定位置,我们会想发现哪些公司在该位置做业务。

信息提取有许多应用,包括商业智能、简历收获、媒体分析、情感检测、专利检索、电子邮件扫描。当前研究的一个特别重要的领域是提取出电子科学文献的结构化数据。

名词短语分块

NP-分块信息最有用的来源之一是词性标记。这是在我们的信息提取系统中进行词性标注的动机之一。

这条规则是说一个NP-块由一个可选的限定词(DT)后面跟着任何数目的形容词(JJ)然后是一个名词(NN)组成。

sentence = [("the", "DT"), ("little", "JJ"), ("yellow", "JJ"), ("dog", "NN"), ("barked", "VBD"), ("at", "IN"), ("the", "DT"), ("cat", "NN")]
grammar = "NP: {<DT>?<JJ>*<NN>}"
cp = nltk.RegexpParser(grammar)
res = cp.parse(sentence)
print(res)
res.draw()

画出来,就看到了结果,狗在欺负猫。


image

标记模式

参考上节

grammar = "NP: {<DT>?<JJ>*<NN>}"

这条规则是说一个NP-块由一个可选的限定词(DT)后面跟着任何数目的形容词(JJ)然后是一个名词(NN)组成。

理解自然语言

本章的目的是要回答下列问题:

  1. 我们如何能表示自然语言的意思,使计算机能够处理这些表示?
  2. 我们怎样才能将意思表示与无限的句子集合关联?
  3. 我们怎样才能使用连接意思表示与句子的程序来存储知识?
import nltk
from nltk import load_parser
cp = load_parser('grammars/book_grammars/sql0.fcfg')
query = 'What cities are located in China'
trees = next(cp.parse(query.split()))
ans = trees[0].label()
print(ans)

生成sql语句,实现的高级的用法

>>> print(ans)
[ *type* = 'NP'                           ]
[ SEM    = (SELECT, City FROM city_table) ]
上一篇 下一篇

猜你喜欢

热点阅读