Chinese processing
“举一隅不以三隅反,则不复也” ——《论语·述而》
一个数据驱动的中文处理**实验环境**,可进行*中文分词*和*依存句法分析*等任务。作者张开旭。
特点
O(n)
的时间复杂度。在此以Ubuntu操作系统为例,介绍如何安装和使用**isan**。
首先,需要安装必要的软件包,包括gcc,make,Python3,Python3-dev和git,在命令行下安装:
sudo apt-get install gcc
sudo apt-get install make
sudo apt-get install python3
sudo apt-get install python3-dev
sudo apt-get install git
选好路径,使用git下载**isan**源代码,编译。
git clone https://github.com/zhangkaixu/isan.git
cd isan
make
下载一个可供实验用的SIGHAN05中文分词语料库。
wget http://www.sighan.org/bakeoff2005/data/icwb2-data.rar
sudo apt-get install unrar
mkdir sighan05
unrar e icwb2-data.rar sighan05
试着训练和测试,看看程序是否安装正确。
./cws.sh test.bin --train sighan05/msr_test_gold.utf8
./cws.sh test.bin --test sighan05/msr_test_gold.utf8
如果以上一切顺利,将会看到测试结果能有0.99以上的F1值。接下来就可以试着真枪实弹地来一次,在MSR的训练集上迭代20次训练模型,每次迭代都将测试集作为开发集检查一下模型性能。
./cws.sh test.bin --train sighan05/msr_training.utf8 --iteration=20 --dev sighan05/msr_test_gold.utf8 --beam_width=16
可以看到最后效果保持在0.973左右,一个还算可以的baseline吧?
那么只要对代码的某些地方进行进一步的修改,就可能有比baseline更好的分词模型了。
以中文分词为例,命令行用法如下:
./cws.sh model_file [--train training_file] [--test test_file] [--dev dev_file]
[--iteration iter] [--beam_width w]
其中:
model_file
是用以存储模型参数的文件training_file
如果给出,会使用该文件训练模型dev_file
如果给出,会在每次训练迭代之后在dev_file
上测试模型效果test_file
如果给出,会使用已有模型或新训练的模型在该文件上进行测试training_file
和 test_file
均未给出,则对标准输入流中的文本进行分词,输出结果到标准输出流iter
用来指定训练时的迭代次数w
用来指定柱搜索解码中的搜索宽度(柱宽度)词性标注的基本命令行用法相同,只需要将cws.sh
替换为tag.py
(当然部分功能尚未实现)。
每个句子一行
材料利用率高。
材料 利用率 高 。
材料_NN 利用率_NN 高_VA 。_PU
例如在分词./cws.sh
命令中,training_file
、 dev_file
、 test_file
以及预测阶段的输出的格式均是使用的分词结果格式, 预测阶段的输入格式是原始句子格式。
现以分词模型为例,介绍程序架构。
首先看看./cws.sh
文件,其包含了模型的三个组成部分:
./isan.py \
--model isan.common.perceptrons.Model \
--decoder isan.common.decoder.DFA \
--task isan.tagging.cws.Task \
$*
首先是--task
,包含了分词相关的所有代码,仔细阅读源代码中的所有内容,修改其中的代码,就能DIY出自己的分词模型。
其次是--decoder
,是一个解码器,与具体的任务无关。分词使用的是基于状态转移的DFA
解码器,也就是一个维特比解码器,相同解码器也可完成词性标注等任务。此外模型的特征权重也由Searcher管理。
最后是--model
,是控制模型学习、预测过程的,与具体的任务和解码器均无关。该例子中使用的是平均感知器算法进行模型的学习和预测。
解码就是根据**输入**搜索得到**输出**的过程。
isan是这样建模的。首先定义一个**动作**的集合,解码过程就是根据输入,得到一个动作序列,然后根据输入与动作序列,就能唯一确定输出。因此解码的过程就是根据输入得到动作序列的过程。
在分词例子中,动作有两种,即 分 与 断 ,一个有n
个字的输入,对应的动作序列中有n+1
个动作,分别表示各个字边界是分还是断。
下面的问题是如何依次确定动作序列中每个位置具体的动作。首先引入**状态**这一概念,有一个初始状态,一个状态根据不同的动作转移到下一个不同的状态。最后到终止状态。**isan**根据当前状态确定下一个动作哪个好哪个不好。
具体地,由状态和输入可生成每个状态的特征,每个特征-动作二元组对应一个权重。那么对于一个动作,一个状态的k
个特征就有k
个权重,它们线性相加就是一个分数,对应着这个动作的优劣。
接下来,回到最开始的解码中确定动作序列的问题上,一个动作序列的的好坏,由序列中每个动作的分数相加得到。解码就是尽量找到分数最高的动作序列,以此生成输出。