NLPNote
6/Feb 2014
1.《Python自然语言处理》笔记
- 遍历序列的各种方式
Python 表达式 评论
for item in s 遍历 s 中的元素
for item in sorted(s) 按顺序遍历 s 中的元素
for item in set(s) 遍历 s 中的无重复的元素
for item in reversed(s) 按逆序遍历 s 中的元素
for item in set(s).difference(t) 遍历在集合 s 中不在集合 t 的元素
for item in random.shuffle(s) 按随机顺序遍历 s 中的元素
组合使用显威力: reversed(sorted(set(s)))
- zip && enumerate
>>> words = ['I', 'turned', 'off', 'the', 'spectroroute']
>>> tags = ['noun', 'verb', 'prep', 'det', 'noun']
>>> zip(words, tags)
[('I', 'noun'), ('turned', 'verb'), ('off', 'prep'),
('the', 'det'), ('spectroroute', 'noun')]
>>> list(enumerate(words))
[(0, 'I'), (1, 'turned'), (2, 'off'), (3, 'the'), (4, 'spectroroute')]
对于一些 NLP 的任务,有必要将一个序列分割成两个或两个以上的部分。例如:我们
可能需要用 90%的数据来“训练”一个系统,剩余 10%进行测试。要做到这一点,我们指
定想要分割数据的位置,然后在这个位置分割序列。
>>> text = nltk.corpus.nps_chat.words()
>>> cut = int(0.9 * len(text))
>>> training_data, test_data = text[:cut], text[cut:]
>>> text == training_data + test_data
True
>>> len(training_data) / len(test_data) 4
9
我们可以验证在此过程中的原始数据没有丢失,也不是复制。我们也可以验证两块大
小的比例是我们预期的。
让我们综合关于这三种类型的序列的知识,一起使用链表推导处理一个字符串中的词,
按它们的长度排序。
>>> words = 'I turned off the spectroroute'.split()
>>> wordlens = [(len(word), word) for word in words]
>>> wordlens.sort()
>>> ' '.join(w for (_, w) in wordlens)
'I off the turned spectroroute'
- 从html中提取信息的通用办法
import re
def get_text(file):
"""Read text from a file, normalizing whitespace and stripping HTML markup."""
text = open(file).read()
text = re.sub('\s+', ' ', text)
text = re.sub(r'<.*?>', ' ', text)
return text
- 防御性编程
def tag(word):
assert isinstance(word, basestring), "argument to tag() must be a string"
if word in ['a', 'the', 'all']:
return 'det'
else:
return 'noun'
- FreqDist
def freq_words(file, min=1, num=10):
text = open(file).read()
tokens = nltk.word_tokenize(text)
freqdist = nltk.FreqDist(t for t in tokens if len(t) >= min)
return freqdist.keys()[:num]
def freq_words_verbose(file, min=1, num=10, verbose=False):
'''如果设置了 verbose 标志将会报告其进展情况'''
freqdist = FreqDist()
if trace: print "Opening", file
text = open(file).read()
if trace: print "Read in %d characters" % len(file)
for word in nltk.word_tokenize(text):
if len(word) >= min:
freqdist.inc(word)
if trace and freqdist.N() % 100 == 0: print "."
if trace: print
return freqdist.keys()[:num]
调试&&Pdb
CSV :Python有自己的CSV库,csv.reader
动态规划是一种在 NLP 中广泛使用的算法设计技术,它存储以前的计算结果,
以避免不必要的重复计算。
2. 文本分类
过拟合: 如果你提供太多的特征,那么该算法将高度依赖你的训练数据的特性,而一般化到新的例子的效果不会很好。这个问题被称为过拟合。
devtest: 一旦初始特征集被选定,完善特征集的一个非常有成效的方法是错误分析。首先,我们选择一个开发集,包含用于创建模型的语料数据。然后将这种开发集分为训练集和开发测试集。
Topic映射到关键词组,映射的越多,表示越切题。
不去关注词法,语法阶段的错误,做到隔离。面面俱到的效果未必好。
algorithm : 主题检测
input: document
tools:
- 特征提取器(eg:给定一些模式(词,词组,词模式),得到对于给定document的`布尔数组`)
- 训练一个文档分类器
特征提取函数的行为就像有色眼镜一样,强调我们的数据中的某些属性(颜色),并使其无法看到其他属性。分类器在决定如何标记输入时,将完全依赖它们强调的属性。
要不要走一条无监督学习之路,寻找不动点。
文本自动层级聚类
这种试探性的数据分析(exploratory data analysis)来识别跑题作文,并辅以人工鉴别。这种内容评价方法的特点是不需要事先基于大规模标注训练集构建评价模型,并且有着层级聚合聚类法的突出优点,郎能够生成比较规整的类集合,聚类结果不依赖文档的初始排列或输入次序,与聚类过程的先后次序无关,聚类结果比较稳定,不易导致类的重构。并且对于作文i平价来讲,得到的结果比较容易解释。实验结果表明,该方法能比较清晰地识别与大多数作文内容不同的作文,再辅以人工鉴别,可准确识别跑题作文,从而在通用自动作文评价中实现作文内容的测量。
3. 代码工具库
# -*- coding: utf-8 -*-
"""
为跑题检测储备的工具代码
~/Project/NLTK-offTopic/.temp.py
"""
import numpy as np
import nltk as nk
import re
s=open("nlptest.txt","r")
'''s.seek(0)'''
m1=s.read()
pattern=re.compile("^A-Za-z")
s1=re.split("\s+",re.sub(pattern," ",m1.replace("\n"," ")))
s2=set(s1) #union作用
s3=nk.FreqDist(s1)
nk.FreqDist(s1).items()#显示所有信息
nk.FreqDist(s1).keys()[:50]#显示前50的词频为降序排列
s4=[len(ca) for ca in s1]#计算词频长度
s5=nk.FreqDist(s4)
max(s5)#显示最大的词频
s5.freq(s5.keys(max(s5))#可显示比率
z1=[ca for ca in set(s1) if s3[ca]>10]#可以只输出符合规则的词频
s3.plot(50,cumulative=True)#累计汇总图前50个词频的
s3.hapaxes()#输出只一次的词
nk.bigrams(s1)#形成双连词
s3.inc(s3)#可添加样本
s3.N()可现实总量
s3.tabulate(conditions="表示第几个文本对应的名字",samples="表示要显示的词")#绘制频率分布表
###nltk上的人机交互程序
nk.chat.chatbots()
##载入自己的语料库
from nltk.corpus import PlaintextCorpusReader
wd="D:\\nlptest"
wd1=PlaintextCorpusReader(wd,".*")
wd1.fileids()#显示语料库中的文件名
wd1.words("nlptest.txt")#显示词和split效果一样
cfd=nk.ConditionalFreqDist((genre,word) for genre in ["first","second"] for word in s1)
#对应的条件概率如果在word,其实就是分类汇总
cfd.conditions()#显示并按照条件字母排序
#一样可以用tabulate显示table列表
#英文同义词字典库
from nltk.corpus import wordnet as wn
wn.synsets("hell")#显示出同义词类
wn.synset("hell.n.01").lemma_names#可以显示出在第几种词义词性下对应的相同英文
wn.synset("hell.n.01").definition#词语定义
wn.synset("hell.n.01").examples#常用词义例句子
wn.synset("hell.n.01").lemmas#显示所有词条
wn.lemma("hell.n.01.hell_on_earth")
wn.lemma("hell.n.01.hell_on_earth").synset#显示上层hell.n.01
wn.lemma("hell.n.01.hell_on_earth").name#显示单词'hell_on_earth'
hell=wn.synset("cat.n.01")
hell1=hell.hyponyms()
sorted([lemma.name for synset1 in hell1 for lemma in synset1.lemmas])
#Out[65]: ['Felis_catus', 'Felis_domesticus', 'domestic_cat', 'house_cat', 'wildcat']
#先进行词条分类
#通过hyponyms找到下位词如毛 可以使什么类型的猫等
hell.root_hypernyms()#可以找到最一般的上位词
hell.hypernym_paths()#可以找到层次 len测是几类
wn.synset("cat.n.01").part_meronyms()#可以显示出如猫耳朵,猫毛这类词汇关系
wn.synset("cat.n.01").substance_meronyms()#不理解什么叫树的实质是心材和边材
wn.synset("walk.v.01").entailments()#动词的蕴含意义,如走路蕴含着抬脚,吃蕴含着咀嚼等
wn.lemma("rush.v.01").antonyms()#动词的反义
dir(wn.synset("rush.v.01"))#可以通过此种方式再词汇挂你选等上查找
wn.synset("right_whale.n.01").lowest_common_hypernyms(wn.synset("orca.n.01"))#可以计算出两个相似的类
wn.synset("right_whale.n.01").min_depth()#可以查对应的深度量化
wn.synset("right_whale.n.01").path_similarity(wn.synset("orca.n.01"))#直接可以计算相似度1为基本一样
'''urllib urlopen urlopen().read()
#nk.word_tokenize()可直接对文本分词
#text=nk.Text(nk.word_tokenize)的list形变为nltk文本
list形式可用 .find("")
#html
k1=urlopen().read()
#直接转换
k2=nk.clean_html(k1)
k3=nk.word_tokenize(k2)
'''
#词干提取器
porter=nk.PorterStemmer()#或者LancasterStemmer()
[porter.stem(t) for t in s1]
#词型归并器
l1=nk.WordNetLemmatizer()
[l1.lemmatize(t) for t in s1]
#nk.regexp_tokenize(text,pattern)比re.findall快很多
#random.shuffle(sample)
#词性标注器
nk.pos_tag(s1)#cc连词 rb副词 in介词 nn名词 jj形容词 vbp动词
#adj形容词 adv动词 cnj连词 det限定词 ex存量词 fw外来词 mod情态动词
#n 名词 np 专有名词 num数量词 pro代词 p介词 to 词投 uh感叹词 v动词
#vd过去式 vg现有分词 vn过去分词 wh wh限定词
#读取已标注的语料库
s1.tagged_words()
#朴素贝叶斯
cla=nk.NaiveBayesClassifier.train()
cla.classfiy()
nk.classify.accuracy(cla,"测试集")
#决策树
nk.DecisionTreeClassifier.tarin()