Isan

Chinese processing

isan

“举一隅不以三隅反,则不复也” ——《论语·述而》

一个数据驱动的中文处理**实验环境**,可进行*中文分词*和*依存句法分析*等任务。作者张开旭

特点

Run

Getting started

在此以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更好的分词模型了。

Command line

以中文分词为例,命令行用法如下:

./cws.sh model_file [--train training_file] [--test test_file] [--dev dev_file]
    [--iteration iter] [--beam_width w]

其中:

词性标注的基本命令行用法相同,只需要将cws.sh替换为tag.py(当然部分功能尚未实现)。

Input & output

每个句子一行

例如在分词./cws.sh命令中,training_filedev_filetest_file 以及预测阶段的输出的格式均是使用的分词结果格式, 预测阶段的输入格式是原始句子格式。

Architecture

现以分词模型为例,介绍程序架构。

The program

首先看看./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,是控制模型学习、预测过程的,与具体的任务和解码器均无关。该例子中使用的是平均感知器算法进行模型的学习和预测。

Decoding

解码就是根据**输入**搜索得到**输出**的过程。

Actions

isan是这样建模的。首先定义一个**动作**的集合,解码过程就是根据输入,得到一个动作序列,然后根据输入与动作序列,就能唯一确定输出。因此解码的过程就是根据输入得到动作序列的过程。

在分词例子中,动作有两种,即 ,一个有n个字的输入,对应的动作序列中有n+1个动作,分别表示各个字边界是分还是断。

Status

下面的问题是如何依次确定动作序列中每个位置具体的动作。首先引入**状态**这一概念,有一个初始状态,一个状态根据不同的动作转移到下一个不同的状态。最后到终止状态。**isan**根据当前状态确定下一个动作哪个好哪个不好。

Features

具体地,由状态和输入可生成每个状态的特征,每个特征-动作二元组对应一个权重。那么对于一个动作,一个状态的k个特征就有k个权重,它们线性相加就是一个分数,对应着这个动作的优劣。

接下来,回到最开始的解码中确定动作序列的问题上,一个动作序列的的好坏,由序列中每个动作的分数相加得到。解码就是尽量找到分数最高的动作序列,以此生成输出。