赞
踩
python上著名的自然语言处理库。自带语料库,词性分类看;自带分类,分词,等功能。有强大的社区支持,和N多的简单版wrapper(eg.TextBlob)
TextBlob是一个用于处理文本数据的Python库。对NLTK的封装。它为常见的自然语言处理(NLP)任务提供了一个简单的API,例如词性标注,名词短语提取,情感分析,分类,翻译等。结果:(-1,1)GitHub链接:https://github.com/sloria/TextBlob
SnowNLP是一个python写的类库,可以方便的处理中文文本内容,是受到了TextBlob的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和TextBlob不同的是,这里没有用NLTK,所有的算法都是自己实现的,并且自带了一些训练好的字典。SnowNLP用于情感分析方面(现在训练数据主要是买卖东西时的评价,所以对其他的一些可能效果不是很好),而且它的分词能力并没有jieba强大。
彭博社Bloomberg API(30k一个月)、Thomson Reuters(15K)、 Wind、大智慧、同花顺数据API。
from nltk.corpus import brown #从nltk语料库中引入brown
brown.categories() #brown中有哪些类型
print(len(brown.sents())) #brown中的句子总数
print(len(brown.words())) #brown中的单词总数
分词方式:
(1)启发式分词:Heuristic。基于查字典进行分词。类比于relu_based
(2)机器学习/统计方法:HMM、CRF、nn、LSTM、RNN等。基于data进行分词(HMM、CRF传统模型是由公式计算是一个单词的概率是多少(概率P);nn、LSTM、RNN深度学习是黑盒子)。类比于Generative
中文的字(1000个覆盖约92%,2000字覆盖98%以上,3000字则已到99%)相当于英文的字母(26个)
(3)案例
英文分词:Tokenize
>>> import nltk
>>> sentence = “hello, world"
>>> tokens = nltk.word_tokenize(sentence)
>>> tokens
['hello', ',', 'world']
中文分词库:jieba
import jieba
seg_list = jieba.cut("我来到北北京清华⼤大学", cut_all=True)
print "Full Mode:", "/ ".join(seg_list) # 全模式
seg_list = jieba.cut("我来到北北京清华⼤大学", cut_all=False)
print "Default Mode:", "/ ".join(seg_list) # 精确模式
seg_list = jieba.cut("他来到了了⽹网易易杭研⼤大厦") # 默认是精确模式
print ", ".join(seg_list)
seg_list = jieba.cut_for_search("⼩小明硕⼠士毕业于中国科学院计算所,后在⽇日本京都⼤大学深造")
# 搜索引擎模式
print ", ".join(seg_list)
【全模式】: 我/ 来到/ 北北京/ 清华/ 清华⼤大学/ 华⼤大/ ⼤大学
【精确模式】: 我/ 来到/ 北北京/ 清华⼤大学
【新词识别】:他, 来到, 了了, ⽹网易易, 杭研, ⼤大厦
(此处,“杭研”并没有在词典中,但是也被Viterbi算法识别出来了了)
【搜索引擎模式】: 小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算,计算所, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造
特殊符号:
from nltk.tokenize import word_tokenize
tweet = 'RT @angelababy: love you baby! :D http://ah.love #168cm'
print(word_tokenize(tweet))
输出:
[‘RT’, ‘@’, ‘angelababy’, ‘:’, ‘love’, ‘you’, ‘baby’, ‘!’, ‘:’, ’D’, ‘http’, ‘:’, ‘//ah.love’, ‘#’, ‘168cm’]
输出内容@+人名、网址等都是不需要的;:D表情文本没有表示出其含义。可以利用正则表达式re,对这些内容进行删除或转化。
(4)正则表达式对照表:
http://www.regexlab.com/zh/regref.htm
import re #识别表情O(∩_∩)O emoticons_str = r""" (?: [:=;] #眼睛 [oO\-]? #鼻子 [D\)\]\(\]/\\OpP] #嘴 )""" #识别特殊符号 regex_str = [ emticons_str, r'<[^>]+>', # HTML tags r'(?:@[\w_]+)', # @某人 r"(?:\#+[\w_]+[\w\'_\-]*[\w_]+)", # 话题标签 r'http[s]?://(?:[a-z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-f][0-9a-f]))+', # URLs r'(?:(?:\d+,?)+(?:\.?\d+)?)', # 数字 r"(?:[a-z][a-z'\-_]+[a-z])", # 含有-和'的单词 r'(?:[\w_]+)', # 其他 r'(?:\S)' # 其他 ]
注:虚词:语义处理里没有用,但对于文本表面(如写作水平等)是有用的。分词可根据需要保留
(5)社交网络中的分词案例
tokens_re = re.compile(r'('+'|'.join(regex_str)+')', re.VERBOSE | re.IGNORECASE)
emoticon_re = re.compile(r'^'+emoticons_str+'$', re.VERBOSE | re.IGNORECASE)
def tokenize(s):
return tokens_re.findall(s)
def preprocess(s, lowercase=False):
tokens = tokenize(s)
if lowercase:
tokens = [token if emoticon_re.search(token) else token.lower() for token in tokens]
return tokens
tweet = 'RT @angelababy: love you baby! :D http://ah.love #168cm'
print(preprocess(tweet)) # ['RT', '@angelababy', ':', 'love', 'you', 'baby', # ’!', ':D', 'http://ah.love', '#168cm']
(1)将不同的词性(但意思相同)规范为同一个表达式。如
Inflection时态变化(不要影响词性):walk ==> walking ==> walked
derivation引申(词性的变化):nation(noun) ==> national(adjective) ==> nationalize(veb)
(2)词形归一化方法
Stemming词干提取:一般是吧不影响词性的时态的小尾巴砍掉
walking ==> walk
walked ==> walk
Lemmatization词形归一:把各种类型的词的变形(查表),都归为一个形式
went ==> go
are ==> be
(3)代码实现
from nltk.stem.porter import PorterStemmer
porter_stemmer = PorterStemmer()
print(porter_stemmer.stem('maximum'))
print(porter_stemmer.stem('presumably'))
print(porter_stemmer.stem('multiply'))
print(porter_stemmer.stem('provision'))
输出:
maximum
presum
multipli
provis
from nltk.stem import SnowballStemmer
snowball_stemmer = SnowballStemmer("english")
print(snowball_stemmer.stem('maximum'))
print(snowball_stemmer.stem('presumably'))
print(snowball_stemmer.stem('multiply'))
print(snowball_stemmer.stem('provision'))
maximum
presum
multipli
provis
from nltk.stem.lancaster import LancasterStemmer
lancaster_stemmer = LancasterStemmer()
print(lancaster_stemmer.stem('maximum'))
print(lancaster_stemmer.stem('presumably'))
print(lancaster_stemmer.stem('multiply'))
print(lancaster_stemmer.stem('provision'))
输出:
maxim
presum
multiply
provid
from nltk.stem.porter import PorterStemmer
p = PorterStemmer()
print(p.stem('went'))
print(p.stem('wenting'))
输出:
went
went
from nltk.stem import WordNetLemmatizer
wordnet_lemmatizer = WordNetLemmatizer()
print(wordnet_lemmatizer.lemmatize('dogs'))
print(wordnet_lemmatizer.lemmatize('churches'))
print(wordnet_lemmatizer.lemmatize('aardwolves'))
print(wordnet_lemmatizer.lemmatize('abaci'))
print(wordnet_lemmatizer.lemmatize('hardrock'))
输出:
dog
church
aardwolf
abacus
hardrock
一般先使用词性标注判断出词性,在使用Lemma进行词形还原。
1、对于Went:v.go的过去是;n.英文名:温特。直接使用Lemma无法正确还原
2、加入词性后即可准确的进行词形还原
#没有POS Tag,默认为NN 名词
wordnet_lemmatizer.lemmatize('are')
wordnet_lemmatizer.lemmatize('is')
#加上POS Tag
wordnet_lemmatizer.lemmatize('are',pos='v')
wordnet_lemmatizer.lemmatize('is',pos='v')
import nltk
text = nltk.word_tokenize('what does the fox say')
print(text)
print(nltk.pos_tag(text))
输出:
[‘what’, ‘does’, ‘the’, ‘fox’, ‘say’]
[(‘what’, ‘WDT’), (‘does’, ‘VBZ’), (‘the’, ‘DT’), (‘fox’, ‘NNS’), (‘say’, ‘VBP’)]
1、全体stopwords列表 http://www.ranks.nl/stopwords
2、nltk.download(‘stopwords’)
3、代码实现
from nltk.corpus import stopwords
# 先token,得到一个word_list
# ...
# 然后filter
filtered_words = [word for word in word_list if word not in stopwords.words('english')]
文本的一般预处理流程:
除了NLTK外,斯坦福的:CORENLP库指出中、英、西班牙文
机器学习:通过设定的规则去构造特征。
步骤:建立字典、句子单词出现即在字典对应记为1
缺点:没有考虑词的重要性和顺序关系
(1)含义
词表位置需要固定,保持在一个空间内。文本表示相当于,每个词都进行one-hot,在累加。
(2)优点:
import nltk from nltk import FreqDist #先做一个词库 corpus = 'this is my sentence ' 'this is my life' 'this is the day' tokens = nltk.word_tokenize(corpus) print(tokens) #使用NLTK的FreqDist统计一下文字出现的频率 fdist = FreqDist(tokens) print(fdist) print(fdist['is']) #输出最常见的50个单词 standard_freq_vector = fdist.most_common(50) size = len(standard_freq_vector) print(size) print(standard_freq_vector) #按照词频大小,生成{词:位置索引}字典 word_to_count = {} for term in standard_freq_vector: word_to_count[term[0]] = term[1] print(word_to_count) #对于任意句子 sentence = 'this is cool' #分词 tokens = nltk.word_tokenize(sentence) sentence_vector = [] for word in tokens: sentence_vector.append(word_to_count.get(word,0))
单用频率表示,无法真实表达出词在该文本中的重要性,如某些公有词虽然在文本中出现的次数多,可能在整个语料库中都出现很多。
(1)TF: Term Frequency, 衡量⼀个term在⽂档中出现得有多频繁。
TF(t) = (t出现在⽂档中的次数) / (⽂档中的term总数)。
(2)IDF: Inverse Document Frequency, 衡量⼀个term有多重要。有些词出现的很多,但是明显不是很有卵⽤。⽐如’is’,’the‘,’and‘之类
的。为了平衡,我们把罕见的词的重要性(weight)搞⾼,把常见词的重要性搞低。
IDF(t) = log_e(⽂档总数 / 含有t的⽂档总数).
(3)
T
F
−
I
D
F
=
T
F
∗
I
D
F
TF-IDF = TF * IDF
TF−IDF=TF∗IDF
(4)例子:
现在有10M的文档,baby出现在其中的1000个文档中。
IDF(baby) = log(10000000/1000) = 4
那么来了一个文档有100个单词,其中单词baby出现3次。
TF(baby) = (3/100) = 0.03
所以,TF-IDF(baby) = TF(baby) * IDF(baby) = 0.03 * 4 = 0.12
(5)代码实现
from nltk.text import TextCollection
#首先, 把所有的⽂文档放到TextCollection类中。
#这个类会⾃自动帮你断句句, 做统计, 做计算
corpus = TextCollection(['this is sentence one',
'this is sentence two',
'this is sentence three'])
#直接就能算出tfidf
#(term:一句话中的某个term,text:这句话)
print(corpus.tf_idf('this','this is sentence four'))
(1)介绍
一句话分词后通过情感词字典,对每个词进行打分,最后得出句子情感得分。例如:like:1,good:2,bad:-2,terrible:-3。这代表着like的情感正面程度分值为1,good的情感正面程度为2,bad的情感正面程度为-2,terrible的情感正面程度为-3。
AFINN-111就是一个典型的情感字典:http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6010
下载后如图:
(2)使用NLTK完成简单的情感分析代码实现:
#NLTK进行情感分析 import nltk #建立情感字典 sentiment_dictionary ={} for line in open('you_file\AFINN-111.txt'): word,score = line.split(' ') sentiment_dictionary[word] = int(score) #构建{单词:得分}字典 sentence_1 ='i love you!' sentence_2 ='i hate you!' #分词 word_list1 = nltk.word_tokenize(sentence_1) word_list2 = nltk.word_tokenize(sentence_2) #遍历每个句子,把每个词的情感得分相加,不在情感字典中的词分数全部置0 s1_score = sum(sentiment_dictionary.get(word,0) for word in word_list1) s2_score = sum(sentiment_dictionary.get(word,0) for word in word_list2) print('我是句子'+sentence_1+'的正面情感得分:',s1_score) print('我是句子'+sentence_2+'的正面情感得分:',s2_score)
输出结果:
我是句子i love you!的正面情感得分:3
我是句子i hate you!的正面情感得分:-3
(3)存在的问题:
from nltk.classify import NaiveBayesClassifier from nltk import word_tokenize #简单手造的训练集 s1 = 'i am a good boy' s2 = 'i am a handsome boy' s3 = 'he is a bad boy' s4 = 'he is a terrible boy' #预处理后得到字典类型: #key表示fname对应句子中出现的单词 #value表示每个文本单词对应的值 def preprocess(s): return {word:True for word in s.lower().split()} #把训练集做成标准形式 training_data = [[preprocess(s1),'pos'], [preprocess(s2),'pos'], [preprocess(s3),'neg'], [preprocess(s4),'neg'],] #采用朴素贝叶斯模型训练 model = NaiveBayesClassifier.train(training_data) new_s1 = 'i am a good girl' new_s2 = 'she is a terrible girl' #输出预测结果 print('我在预测 '+new_s1+' 结果是:',model.classify(preprocess(new_s1))) print('我在预测 '+new_s2+' 结果是:',model.classify(preprocess(new_s2)))
输出结果:
我在预测 i am a good girl 结果是: pos
我在预测 she is a terrible girl 结果是: neg
在句子被向量化后,我们根据余弦定理便可计算出句子的相似度
s
i
m
i
l
a
r
i
t
y
=
c
o
s
(
θ
)
=
A
⋅
B
∥
A
∥
⋅
∥
B
∥
\displaystyle similarity=cos( \theta ) =\frac{A\cdot B}{\| A\| \cdot \| B\| }
similarity=cos(θ)=∥A∥⋅∥B∥A⋅B
文本表示称为向量后,通过及其学习模型,对分类任务进行预测。
gensim:word2vec、tensorflow
英文、ASII编码(英文)、Unicode中文、自定义一个index编码、电报编码等,在进行深度学习时,输入的词约原始越好。
(1)Auto-Encoder
无监督学习,工业上主要用于降维。
**(2)Word2vec:**单词本身不是单独存在于句子中间的,而是由周围的词决定。
(1)Full document: TF-IDF
(2)Window: co-occurrence matrix + SVD(2个单词都出现的矩阵计算)不光关注在文章中出现的频率,重点关注词与词之间的相关性
a.贡献计数表
b.构建SVD矩阵:把任何形状的矩阵, 都转化为三个向量相乘的矩阵。个性特征:每一行代表自己的特有特征
c.将特征值取出,放在空间平面里。做词向量表达
应为SVD计算复杂度很高,所以想到用两边定义中间的形式,去表达。
model = word2vec.Word2Vec(sentences, size=size, workers=num_workers, size=num_features, min_count = min_word_count, window = window)
model['computer']
输出:
array([-0.00449447, -0.00310097, 0.02421786, …], dtype=float32)
model.similarity('woman', 'man')
输出:0.73723527
#woman + king - man = queen
model.most_similar(positive=['woman', 'king'], negative=['man'])
输出:
[(‘queen’, 0.50882536), …]
“你好吗?”——>向量,“你最近怎么样”——>向量
通过word2vec、tf-idf等形式,把句子把句子表达为向量形式。
无监督学习:KNN做聚类,计算两个句子的距离是否小于某个阈值,如果小于则认为属于一类,可以使用同一个回答
有监督学习:分类问题。
根据网上的语料库,输入词向量,确定它属于那个标签。
这个时候你会发现,我们的vec是针对每个word的。而我们的训练集是sen和label互相对应的,
工业上,到了这一步,有三种解决方案:
1、平均化一个句子里所有词的vec。
sen_vec = [vec, vec, vec, …] / n
2、排成一个大matrix (M * N),等着CNN进行特征提取。
[ vec | vec | vec | vec | … ]
3、用Doc2Vec。这是基于句子的vec,跟word2vec差不多思路路,用起来也差不多。
只对长篇 大文章效果好。对头条新闻,twitter这种的东西,就不行了。每一篇的就太少。
具体可以看gensim。
参考文献:文本为七月在线《自动聊天机器人项目班》学习笔记
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。