优点:
由于最大概率法考虑的是某种字串出现的条件下,最可能划分的词串,因此在拥有大量标注语料的前提下,可以在一定程度上避免切分歧义。
原理:
设Z=z1z2…zn表示字串,
W=w1w2…wm表示切分后的词串,
汉语词语切分可以看作是求使P(W|Z)最大的切分。
p(W|Z) = P(W)P(Z|W)/P(Z)
P(Z)是汉字串的概率,它对于各个候选词串都是一样的,不必考虑。
P(Z|W)表示出现词串的条件下汉字串的概率,显然该值为1,不必考虑,则仅需考虑P(W)即词串的概率。
词串的概率可以通过n元语法来求
用二元语法 P(W)=p(w1|w0)p(w2|w1)…p(wm|wm-1)(1)
用一元语法 P(W)=p(w1)p(w2)…p(wm)(2)
计算词串概率时,有一个纯技术的问题要考虑:
因为每个词的概率都是一个很小的正数,如果汉字串较长,最后得到各种可能的词串的概率都接近于0,无法在机器上表示,当然也就无法比较大小。解决这个问题的办法是:对等式两边(1)、(2)两边取负对数,即
-logp(W) = -logp(w1)-logp(w2)…-logp(wm)(3)
根据-logx的曲线特性,可知p(wi)越大,最终的结果越小,因此求(1)、(2)式最大值变为求(3)式的最小值。
按照最短路径优先算法(严蔚敏)得到C实现
汉语自动分词系统的评价
由于本文中的分词只是一个测试系统,因此并未做评价分析。
准确率:p=系统输出正确词的个数/系统输出词的个数
召回率:R=系统输出正确词的个数/标准答案中词的个数
F值:F = 2*P*R/(P+R)
关于分词的评测会议
第41届ACL国际会议(41st Annual Meeting of the Association for Computational Linguistic,国际计算语言联合会)下设的汉语特别兴趣研究组
SIGHAN(the ACL Special Interest Group on Chinese Language Processing)于2003年4月22日至25日举办了第一届国际汉语分词评测大赛。
语料库和标准分别来自北京大学(简体版)、宾州树库(简体版)、香港城市大学(繁体版),台湾“中央院”(繁体版)。每家标准分为两个任务(Track)
:受限训练任务(Close Track)和非受限训练任务(Open Track)。
/***********************************************************
* File Name : partition.c
* Copyright :
* Module Name : 分词相关操作——N最短路径法
*
* CPU : id-2328M CPU @ 2.20GHz
* OS : MicroSoft Windows Xp
*
* Create Date : 2013/07/27
* Author/Corporation : 于飞
*
* Abstract Description :
-----------------Revision Histroy---------------------------
No Version Date Revised By Item Description
************************************************************/
#include "partition.h"
/***********************************************************
* Function Name : Cut_Word
* Create Date : 2013/07/27
* Author/Corporation : 于飞
* Description : 分词
* Param : fp:输入文件路径
tp:输出文件路径
* Return Code : 返回打开文件状态
NULL: 打开文件失败
fp : 打开文件的指针
************************************************************/
extern void Cut_Word(FILE *fp,FILE *tp)
{
char wbuffer[500]="\0";
int flag = 1;
unsigned int cnt = 0;
unsigned int i = 0;
printf("对输入文本分词中。。。");
while(cnt = Read_a_Sentence(fp,wbuffer,&flag))//读一句话
{
//printf("%s\n",wbuffer);
//printf("%d",cnt);
if(flag == 0)
{
Cut_a_Sentence(tp,wbuffer,cnt);
}
if(flag == 1)
{
wbuffer[cnt++] = '/';
wbuffer[cnt++] = ' ';
wbuffer[cnt] = '\0';
fprintf(tp,"%s",wbuffer);
//printf("%s",wbuffer);
}
}
printf("\n分词完毕!\n");
}
/***********************************************************
* Function Name : Cut_Word
* Create Date : 2013/07/27
* Author/Corporation : 于飞
* Description : 对一句话分词
* Param : testp:输出文件路径
wbuffer:输入的一句话
i:句子长度
* Return Code : 返回0成功
************************************************************/
extern int Cut_a_Sentence(FILE *testp,char wbuffer[],unsigned int i)
{
OLGraph *G;
Array *A;
G =Creat_W_Graph(i/2+1,i/2,wbuffer);
Search_Word(wbuffer,i,G);
A = InitArray(i/2+1,i/2+1);
Display_Output(G,A,ShortestPath_DIJ(G,A),testp);
DestroyArray(A);
DestroyGraph(G);
return 0;
}
/***********************************************************
* Function Name : Creat_W_Graph
* Create Date : 2013/07/27
* Author/Corporation : 于飞
* Description : 构建词图
* Param : vexnum:顶点数
arcnum:弧数
pw: 输入的句子
* Return Code : 返回词图地址
************************************************************/
extern OLGraph *Creat_W_Graph(unsigned int vexnum,unsigned int arcnum,char *pw)
{
OLGraph *tG;
ArcBox *s;
char *w;
unsigned short int t = 0;
unsigned int i,j,k;
tG = (OLGraph *)malloc(sizeof(OLGraph));
tG->vexnum = vexnum;
tG->arcnum = arcnum;
for(i=0;i<tG->vexnum;i++)
{
tG->xlist[i].data = 0;
tG->xlist[i].firstin = NULL;
tG->xlist[i].firstout = NULL;
}
for(k=0,i=0,j=1;k<tG->arcnum;k++,i++,j++)
{
s = (ArcBox *)malloc(sizeof(ArcBox));
if(s == NULL)printf("没有内存啦!");
s->tailvex = i;
s->headvex = j;