课程要求的一部分,目前找了一些并跑通代码进行相关测试,不完整待续。
自然语言基础工具调研
- 词典(https://github.com/fighting41love/funNLP)
- 分词工具
- NLPIR(https://blog.csdn.net/MebiuW/article/details/52232562)
NLPIR汉语分词系统(又名ICTCLAS2013),主要功能包括中文分词;词性标注;命名实体识别;用户词典功能;支持GBK编码、UTF8编码、BIG5编码。新增微博分词、新词发现与关键词提取;张华平博士先后倾力打造十余年,内核升级10次。
全球用户突破20万,先后获得了2010年钱伟长中文信息处理科学技术奖一等奖,2003年国际SIGHAN分词大赛综合第一名,2002年国内973评测综合第一名。
代码:
import pynlpir
pynlpir.open()
s = '江苏海洋大学计算机工程学院'
segments = pynlpir.segment(s)
print('\n分词测试:')
for segment in segments:
print(segment[0], '\t')
pynlpir.close()
# 关键词提取
import pynlpir
pynlpir.open()
s = '江苏海洋大学计算机工程学院'
print('\n关键词测试:')
key_words = pynlpir.get_key_words(s, weighted=True)
for key_word in key_words:
print(key_word[0], '\t', key_word[1])
pynlpir.close()
结果:
-
- Jieba
jieba是目前最好的 Python 中文分词组件,它主要有以下 3 种特性:(1)支持 3 种分词模式:精确模式、全模式、搜索引擎模式
(2)支持繁体分词
(3)支持自定义词典
代码1:
import jieba
print(jieba.lcut("江苏海洋大学计算机工程学院"))
print(jieba.lcut("江苏海洋大学计算机工程学院",cut_all=True))
print(jieba.lcut_for_search("江苏海洋大学计算机工程学院"))
结果1:
代码2:
txt = open("./sanguo.txt", "r", encoding='utf-8').read()
words = jieba.lcut(txt) # 使用精确模式对文本进行分词
counts = {} # 通过键值对的形式存储词语及其出现的次数
for word in words:
if len(word) == 1: # 单个词语不计算在内
continue
else:
counts[word] = counts.get(word, 0) + 1 # 遍历所有词语,每出现一次其对应的值加 1
items = list(counts.items()) # 将键值对转换成列表
items.sort(key=lambda x: x[1], reverse=True) # 根据词语出现的次数进行从大到小排序
print("\n利用jiaba库统计三国演义出场次数:")
for i in range(15):
word, count = items[i]
print("{0:<5}{1:>5}".format(word, count))
结果2:
- 词向量模型
- Word2vec
- 主题模型
在文本挖掘领域,大量的数据都是非结构化的,很难从信息中直接获取相关和期望的信息,一种文本挖掘的方法:主题模型(Topic Model)能够识别在文档里的主题,并且挖掘语料里隐藏信息,并且在主题聚合、从非结构化文本中提取信息、特征选择等场景有广泛的用途。
-
- LDA
LDA 模式是生成式模型,在这里,假设需要建模的数据为 XX,标签信息为 YY。
判别式模型:对 YY 的产生过程进行描述,对特征信息本身不建模。判别式模型有利于构建分类器或者回归分析生成式模型需要对 XX 和 YY 同时建模,更适合做无监督学习分析。
生成式模型:描述一个联合概率分布 P(X,Y)P(X,Y) 的分解过程,这个分解过程是虚拟的过程,真实的数据不是这么产生的,但是任何一个数据的产生过程可以在数学上等价为一个联合概率分布。
LDA 是一种矩阵分解技术,在向量空间中,任何语料(文档的集合)可以表示为文档(Document - Term,DT)矩阵.
代码:
import numpy as np
import lda
import lda.datasets
import jieba
import codecs
class LDA_v20161130():
def __init__(self, topics=2):
self.n_topic = topics
self.corpus = None
self.vocab = None
self.ppCountMatrix = None
self.stop_words = [u',', u'。', u'、', u'(', u')', u'·', u'!', u' ', u':', u'“', u'”', u'\n']
self.model = None
def loadCorpusFromFile(self, fn):
# 中文分词
f = open(fn, 'r')
text = f.readlines()
text = r' '.join(text)
seg_generator = jieba.cut(text)
seg_list = [i for i in seg_generator if i not in self.stop_words]
seg_list = r' '.join(seg_list)
# 切割统计所有出现的词纳入词典
seglist = seg_list.split(" ")
self.vocab = []
for word in seglist:
if (word != u' ' and word not in self.vocab):
self.vocab.append(word)
CountMatrix = []
f.seek(0, 0)
# 统计每个文档中出现的词频
for line in f:
# 置零
count = np.zeros(len(self.vocab),dtype=np.int)
text = line.strip()
# 但还是要先分词
seg_generator = jieba.cut(text)
seg_list = [i for i in seg_generator if i not in self.stop_words]
seg_list = r' '.join(seg_list)
seglist = seg_list.split(" ")
# 查询词典中的词出现的词频
for word in seglist:
if word in self.vocab:
count[self.vocab.index(word)] += 1
CountMatrix.append(count)
f.close()
#self.ppCountMatrix = (len(CountMatrix), len(self.vocab))
self.ppCountMatrix = np.array(CountMatrix)
print("load corpus from %s success!"%fn)
def setStopWords(self, word_list):
self.stop_words = word_list
def fitModel(self, n_iter = 1500, _alpha = 0.1, _eta = 0.01):
self.model = lda.LDA(n_topics=self.n_topic, n_iter=n_iter, alpha=_alpha, eta= _eta, random_state= 1)
self.model.fit(self.ppCountMatrix)
def printTopic_Word(self, n_top_word = 8):
for i, topic_dist in enumerate(self.model.topic_word_):
topic_words = np.array(self.vocab)[np.argsort(topic_dist)][:-(n_top_word + 1):-1]
print("Topic:",i,"\t",)
for word in topic_words:
print(word,)
print
def printDoc_Topic(self):
for i in range(len(self.ppCountMatrix)):
print ("Doc %d:((top topic:%s) topic distribution:%s)"%(i, self.model.doc_topic_[i].argmax(),self.model.doc_topic_[i]))
def printVocabulary(self):
print ("vocabulary:")
for word in self.vocab:
print (word,)
print
def saveVocabulary(self, fn):
f = codecs.open(fn, 'w', 'utf-8')
for word in self.vocab:
f.write("%s\n"%word)
f.close()
def saveTopic_Words(self, fn, n_top_word = -1):
if n_top_word==-1:
n_top_word = len(self.vocab)
f = codecs.open(fn, 'w', 'utf-8')
for i, topic_dist in enumerate(self.model.topic_word_):
topic_words = np.array(self.vocab)[np.argsort(topic_dist)][:-(n_top_word + 1):-1]
f.write( "Topic:%d\t"%i)
for word in topic_words:
f.write("%s "%word)
f.write("\n")
f.close()
def saveDoc_Topic(self, fn):
f = codecs.open(fn, 'w', 'utf-8')
for i in range(len(self.ppCountMatrix)):
f.write("Doc %d:((top topic:%s) topic distribution:%s)\n" % (i, self.model.doc_topic_[i].argmax(), self.model.doc_topic_[i]))
f.close()
if __name__=="__main__":
_lda = LDA_v20161130(topics=20)
stop = [u'!', u'@', u'#', u',',u'.',u'/',u';',u' ',u'[',u']',u'$',u'%',u'^',u'&',u'*',u'(',u')',
u'"',u':',u'<',u'>',u'?',u'{',u'}',u'=',u'+',u'_',u'-',u'''''']
_lda.setStopWords(stop)
_lda.loadCorpusFromFile(u'G:\\A.txt')
_lda.fitModel(n_iter=1500)
_lda.printTopic_Word(n_top_word=10)
_lda.printDoc_Topic()
_lda.saveVocabulary(u'G:\\B.txt')
_lda.saveTopic_Words(u'G:\\C.txt')
_lda.saveDoc_Topic(u'G:\\D.txt')
结果:
- 关键词提取
- Textrank
(1)第一步是把所有文章整合成文本数据
(2)接下来把文本分割成单个句子
(3)然后,我们将为每个句子找到向量表示(词向量)。
(4)计算句子向量间的相似性并存放在矩阵中
(5)然后将相似矩阵转换为以句子为节点、相似性得分为边的图结构,用于句子TextRank计算。
(6)最后,一定数量的排名最高的句子构成最后的摘要。