PyHanLP&kenlm&HarvestText领域自适应文本挖掘工具
新词发现
新词发现是 NLP 的基础任务之一,通过对已有语料进行挖掘,从中识别出新词。它主要是希望通过无监督发掘一些语言特征(主要是统计特征),来判断一批语料中哪些字符片段可能是一个新词。“新词发现”是一个比较通俗的叫法,更准确的叫法应该是“无监督构建词库”,因为原则上它能完整地构建一个词库出来,而不仅仅是“新词”。当然,你可以将它跟常用词库进行对比,删掉常见词,就可以得到新词了。
特定领域的专有名词也可归属于新词的范畴。何出此言呢?通常我们会很容易找到通用领域的词表,但要找到某个具体领域的专有名词则非常困难,因此特定领域的专有名词相对于通用领域的词语即为新词。换言之,“新”并非只是时间上的概念,同样可以迁移到领域或空间上。因此,新词发现不仅可以挖掘随时间变化而产生的新词,也可以挖掘不同领域的专有名词。
新词发现的方法
目前主要有基于规则和基于统计两种方法:
- 基于规则的方法:根据新词的构词特征或外型特征建立规则库、专业词库或模式库,然后通过规则匹配发现新词。
- 基于统计的方法
- 有监督:有监督方法利用标注语料,将新词发现看作分类或者序列标注问题。
- 无监督:不依赖于任何已有的词库、分词工具和标注语料,仅仅根据词的共同特征,利用统计策略将一段大规模语料中可能成词的文本片段全部提取出来,然后再利用语言知识排除不是新词语的“无用片段”或者计算相关度,寻找相关度最大的字与字的组合。最后,把所有抽取得到的词和已有的词库进行比较,就能得到新词
项目开源地址
✨ https://github.com/bojone/word-discovery
✨ PyHanLP 新词识别)
✨ HarvestText: 领域自适应文本挖掘工具(新词发现、情感分析、实体链接等)√
语言模型简介
语言模型是计算条件概率
的模型,其中$w_1,w_2,…,w_{n−1}$是句子中的前$n−1$个词(或字),$w_n$是第$n$个词(或字)。语言模型在很多方面都有应用,比如说分词、语音识别、机器翻译等。为了得到语言模型,有很多方法,比如说最简单的是“统计+平滑”的方法,还有最大熵语言模型、CRF语言模型等,而当前深度学习框架下研究得很多的是“神经网络语言模型”,它的大概思路是:==$p(w_n|w_1,w_2,…,w_{n−1})$是关于$w1,w2,…,wn$的一个函数,这个函数的具体形式我不知道,所以利用神经网络去拟合它,为了更好地拟合,并且减少模型参数,还把词语“嵌入”到实数空间中,用短向量来表示词语,跟语言模型一起训练。从这个角度看,词向量只是语言模型的副产品。==
语言模型生成的词向量能够较好地表示语义,这是很有趣的,却也是在情理之中。什么是语义?对人类来说,语义是一种推理和理解的过程,而我们的语言模型,就是从前$n−1$个字推测下一个字,这也是一个推理的过程。既然包含了推理成分在里边,就有可能捕捉到语义了。
详细的算法
完整的算法步骤如下:
1 |
|
每一步的补充说明:
1 |
|
细节
Linux环境CentOS系统 kenlm 的自行编译
kenlm
是一个C++编写的语言模型工具,具有速度快、占用内存小的特点,也提供了Python接口。使用了语言模型工具kenlm的count_ngrams
程序来统计ngram。首先,安装必要的包:
1
2
3
4
5
6
7
8
9
10sudo yum install boost
sudo yum install boost-devel
sudo yum install libboost-program-options-dev
sudo yum install zlib
sudo yum install zlib-devel
sudo yum install libbz2-dev
sudo yum install lzma-devel
sudo yum install eigen3
sudo yum install xz-devel
sudo yum install bzip2-devel然后下载&解压 kenlm.tar.gz工具包
1
wget -O - https://kheafield.com/code/kenlm.tar.gz |tar xz
进入子目录进行编译(有用的脚本在
build/bin
之中)1
2
3
4mkdir -p kenlm/build
cd kenlm/build
cmake ..
make -j 4python库的安装方式:
1
pip install https://github.com/kpu/kenlm/archive/master.zip
==把生成的 build/bin/count_ngrams 放到跟 word_discovery.py 同一目录下==
测试是否可运行:
1
./count_ngrams -o 4 --memory=50% --write_vocab_list thucnews.chars <thucnews.corpus >thucnews.ngrams
kenlm 的简单使用
训练一个==4-gram==的语言模型(训练的文本分好词(用空格隔开,如果你是做基于字的模型,就把模型的每个字用空格隔开)):
1
2
3python p.py|./kenlm/bin/lmplz -o 4 > weixin.arpa
# 压缩模型为二进制,方便模型快速加载:
./kenlm/bin/build_binary weixin.arpa weixin.klm简单使用:
1
2
3
4
5
6
7
8import kenlm
model = kenlm.Model('weixin.klm')
model.score('微 信', bos=False, eos=False)
'''
score函数输出的是对数概率,即log10(p('微 信')),其中字符串可以是gbk,也可以是utf-8
bos=False, eos=False意思是不自动添加句首和句末标记符
'''
- 在第二次遍历词库以得到候选词的时候,使用了
Trie
树结构来加速搜索字符串是否出现过某个ngram。Trie树或者其变种基本上是所有基于词典的分词工具的标配,就是因为它可以加快搜索字符串中是否出现过词典中的词。
代码讲解
- 逐句地把原始语料给yield出来
1 |
|
- 参数配置
1 |
|
顺便提一下,因为是无监督训练,语料一般都是越大越好,几百M到几个G都可以,==但其实如果你只要几M的语料(比如一部小说),也可以直接测试,也能看到基本的效果(但可能要修改下面的参数)==
- 用结巴分词加载这个得到的词库(不用它自带的词库,并且关闭新词发现功能),这就构成了一个基于无监督词库的分词工具