虽然基于字标注的中文分词借鉴了词性标注的思想,但是在实践中,多数paper中的方法似乎局限于最大熵模型和条件随机场的应用,所以我常常疑惑字标注中文分词方法为什么不采用别的模型和方法呢?莫非是由于其诞生之初就采用了最大熵模型的缘故。但是,在词性标注中,Citar实现的是TnT中所采用的HMM trigram方法,其所宣称的性能是不亚于最大熵模型等词性标注器的。基于这样的前提,本文就验证一下基于Citar实现的HMM trigram字标注中文分词器的性能。
  我们以微软亚洲研究院提供的中文分词语料为例,采用2-tag(B,I)标记集,只针utf-8编码文本。首先准备训练语料,原始训练集msr_training.utf8的形式是人工分好词的中文句子形式:

“ 人们 常 说 生活 是 一 部 教科书 , 而 血 与 火 的 战争 更 是 不可多得 的 教科书 , 她 确实 是 名副其实 的 ‘ 我 的 大学 ’。
“ 心 静 渐 知 春 似 海 , 花 深 每 觉 影 生 香 。

  需要将其转换为字标注形式,这里52nlp利用perl写了一个简单的2-tag转换程序CharacterTagging.pl,不过请注意这个程序仅处理utf-8编码的文本:
  ./CharacterTagging.pl -i msr_training.utf8 -o msr_training.tagging.utf8
  其中-i指示的是输入文件,-o指示的是输出文件,msr_training.tagging.utf8
的内容示例如下:

“/B 人/B 们/I 常/B 说/B 生/B 活/I 是/B 一/B 部/B 教/B 科/I 书/I ,/B 而/B 血/ 与/B 火/B 的/B 战/B 争/I 更/B 是/B 不/B 可/I 多/I 得/I 的/B 教/B 科/I 书/I ,/B 她/B 确/B 实/I 是/B 名/B 副/I 其/I 实/I 的/B ‘/B 我/B 的/B 大/B 学/I ’/B /B
“/B 心/B 静/B 渐/B 知/B 春/B 似/B 海/B ,/B 花/B 深/B 每/B 觉/B 影/B 生/B 香/ 。/B

  有了这个2-tag的字标注训练语料库,就可以利用Citar中编译好的train来训练字标注器所需的输入文件了:
  ./train msr_training.tagging.utf8 msr_lex msr_ngram
  其中msr_lex包含了5000多个汉字与其标记的共同出现频率,形式如下:

锶 B 4
薛 B 97
铜 B 114 I 26
佛 B 142 I 144
榫 B 2
觚 B 1
萋 B 2 I 8
钮 B 4 I 7

  msr_ngram则是标记本身及其之间的共现频率,形式如下:

B 2368391
I 1682056
173836
86918
B B 1027319
I B 1254154
B 86017
I I 427001
B I 1255055
B 86918
I 901
86918
...

注:由于没有尖括号在Wordpress中被屏蔽,以上内容有误,谢谢读者bflout的提醒,以下重新附上msr_ngram:
[cc lang="c"]
B 2368391
I 1682056
173836
86918
B B 1027319
I B 1254154
B 86017
I I 427001
B I 1255055
B 86918
I 901
86918
B I B 1039293
B B B 408801
I I 285
B B 18403
B I I 215146
B I 60460
I I B 214861
I B I 594480
B B I 600115
B 86918
I I I 211855
B I 616
B B 26449
B 9
I B B 592069
I B 67605
[/cc]

  注意,这两个文件都很小,msr_lex只有64k,而msr_ngram则不到1k,所占用资源极小。
  在利用Citar的tag进行标注之前,需要对测试集msr_test.utf8的字符进行切分,在NIST2009机器翻译的评测主页的底部提供了这个工具 :splitUTF8Characters.p:
  ./splitUTF8Characters.pl -i msr_test.utf8 -o msr_test.split.utf8
  msr_test.utf8的形式如下:

扬帆远东做与中国合作的先行
希腊的经济结构较特殊。
...

  切分后的msr_test.split.utf8形式如下:

扬 帆 远 东 做 与 中 国 合 作 的 先 行
希 腊 的 经 济 结 构 较 特 殊 。
...

  有了msr_test.split.utf8,我们就可以利用Citar的tag进行字标注了:
  ./tag msr_lex msr_ngram < msr_test.split.utf8 > msr_test.hmmtagging.utf8
  标注后的msr_test.hmmtagging.utf8形式如下:

扬/B 帆/I 远/B 东/I 做/B 与/B 中/B 国/I 合/B 作/I 的/B 先/I 行/B
希/B 腊/I 的/B 经/B 济/I 结/B 构/I 较/B 特/B 殊/I 。/B
...

  最后,就是按照标记结果合并字符并去除标记了。这里52nlp利用perl写了一个简单的还原程序Character2word.pl,不过请注意这个程序仅处理utf-8编码的文本:
  ./Character2word.pl -i msr_test.hmmtagging.utf8 -o msr_test.hmmseg.utf8
  msr_test.hmmseg.utf8既是最终的分词结果,其形式如下:

扬帆 远东 做 与 中国 合作 的先 行
希腊 的 经济 结构 较 特殊 。

  当然,这个字标注中文分词的结果好坏还需要利用SIGHAN Bakeoff的score 进行评分:
  ../icwb2-data/scripts/score ../icwb2-data/gold/msr_training_words.utf8 msr_test_gold.utf8 msr_test.hmmseg.utf8 > msr_hmmseg.score
  最终的评分结果在msr_hmmseg.score中,总的评分如下:


=== SUMMARY:
=== TOTAL INSERTIONS: 10304
=== TOTAL DELETIONS: 7030
=== TOTAL SUBSTITUTIONS: 30727
=== TOTAL NCHANGE: 48061
=== TOTAL TRUE WORD COUNT: 106873
=== TOTAL TEST WORD COUNT: 110147
=== TOTAL TRUE WORDS RECALL: 0.647
=== TOTAL TEST WORDS PRECISION: 0.627
=== F MEASURE: 0.637
=== OOV Rate: 0.026
=== OOV Recall Rate: 0.181
=== IV Recall Rate: 0.659
### msr_test.hmmseg.utf8 10304 7030 30727 48061 106873 110147 0.647 0.627 0.637 0.026 0.181 0.659

  结果残不忍睹,不过没关系,重要的是思想,当你明白了如何进行字标注中文分词的设计和操作之后,可以做得改进有很多,譬如增加标记集,修改Citar中不合适的未登录词处理方法,甚至重新采用其他模型等等等等。同样,52nlp也会在合适的时候介绍一下最大熵模型和条件随机场在中文分词中的应用,欢迎继续关注本博客!

注:原创文章,转载请注明出处“我爱自然语言处理”:www.52nlp.cn

本文链接地址:https://www.52nlp.cn/中文分词入门之字标注法2

作者 52nlp

《中文分词入门之字标注法2》有10条评论
  1. 可以解释下msr_ngram吗?如果是标记本身及其之间的共现频率,是不是只有B,I以及四种组合可能?谢谢!

    [回复]

    52nlp 回复:

    粗心了,没有发现wordpress的屏蔽,谢谢提醒,已在文中修改,这下应该清楚些。
    严格意义上还包括citar给它自动添加的start及end标记,另外citar是3-gram的标注器,因此要分别提取1元、2元和3元的组合形式,这个和语料库有点关系,排列组合要多一些,而实际提取还要兼顾语料库及citar自身的实现。

    [回复]

  2. 请教楼主,msr_ngram中的数据是定义什么的,能解释一下么,我是新手。
    谢谢了~

    [回复]

    52nlp 回复:

    代表的是“标记本身及其之间的共现频率”,就是给语料打上标记后统计出来的。

    [回复]

  3. Charactertagging.pl和Character2word.pl 下载失败

    [回复]

    52nlp 回复:

    这两份Perl代码由于之前服务器的更换丢失了;建议参考后面的python相似功能代码

    [回复]

  4. 想问一下关于msr_lex中数据的问题。
    对于一个字可能既会被标注B,也会被标注I , 比如: 人/B 民/I ; 成/B 人/I 那么msr_lex是否会统计:
    人 B 数目 = A
    人 I 数目 = B
    当利用Citar的tag进行字标注时,遇到“人”这个字时会如何标注,是选择max(A,B)吗?还是如何处理?
    谢谢博主。

    [回复]

  5. 想问一下关于msr_lex中数据的问题。
    对于一个字可能既会被标注B,也会被标注I , 比如: 人/B 民/I ; 成/B 人/I 那么msr_lex文件是否会包含:
    人 B 数目 = A
    人 I 数目 = B
    当利用Citar的tag进行字标注时,遇到“人”这个字时会如何标注,是选择max(A,B)吗?还是如何处理?
    谢谢博主。

    [回复]

    52nlp 回复:

    根据上下文进行选择,本身就是一种概率化的方法

    [回复]

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注