自然语言理解工程报告 本文关键词:自然语言,理解,报告,工程
自然语言理解工程报告 本文简介:中文分词工程报告课程:自然语言理解姓名:学号:班级:日期:2013/11/14一,研究背景(一)研究背景:由于中文只有字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂的多、困难的多。中文分词技术产生的因为是中
自然语言理解工程报告 本文内容:
中文分词工程报告
课程:自然语言理解
姓名:
学号:
班级:
日期:2013/11/14
一,
研究背景
(一)
研究背景:
由于中文只有字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂的多、困难的多。中文分词技术产生的因为是中文在基本文法上有其特殊性,具体表现在:
1.中文词语之间没有分隔,而现代汉语中双字或多字词居多,一个字不等
同于一个词。
2.在中文里,“词”和“词组”边界模糊。现代汉语的基本表达单元虽然为“词”,且以双字或者多字词居多,但由于人们认识水平的不同,对词和短语的边界很难去区分。
3.中文分词的方法其实不局限于中文应用,也被应用到英文处理,如手写识
别,单词之间的空格就很清楚,中文分词方法可以帮助判别英文单词的边界。
(二)
主要研究方法
①
基于字位的中文分词研究方法
②
基于数据驱动的中文分词研究方法
③
基于中文文本分词的中文分词研究方法
④
基于优化最大匹配的中文分词研究方法
⑤基于无词库的中文分词研究方法
(三)主要存在问题
中文是一种十分复杂的语言,让计算机理解中文语言更是困难。在中文分词过程中,有两大难题一直没有完全突破。
1.歧义识别:歧义是指同样的一句话,可能有两种或者更多的切分方法。主要的歧义有两种:交集型歧义和组合型歧义。交集型歧义相对组合型歧义来说是还算比较容易处理,组合型歧义就必需根据整个句子来判断了。如果交集型歧义和组合型歧义计算机都能解决的话,在歧义中还有一个难题,是真歧义。真歧义意思是给出一句话,由人去判断也不知道哪个应该是词,哪个应该不是词。
2.新词识别:新词指那些在分词词典中没有收录,但又确实能称为词的那些词。最典型的是人名,除了人名以外,还有机构名、地名、产品名、商标名、简称、省略语等都是很难处理的问题,而且这些又正好是人们经常使用的词,因此对于搜索引擎来说,分词系统中的新词识别十分重要。新词识别准确率已经成为评价一个分词系统好坏的重要标志之一。
(四)现有解决方案
现有的分词算法可分为三大类:基于字符串匹配的分词方法、基于理解的分词法和基于统计的分词法。按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。
1.字符匹配:这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。
2.理解法:这种分词方法是通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它通常包括三个部分:分词子系统、句法语义子系统、总控部分。
3.统计法:从形式上看,词是稳定的字的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。因此字与字相邻共现的频率或概率能够较好的反映成词的可信度。可以对语料中相邻共现的各个字的组合的频度进行统计,计算它们的互现信息。
(五)应用
中文分词是其他中文信息处理的基础,搜索引擎只是中文分词的一个应用。其他的比如MT、自动分类、自动摘要、自动校对等等,都需要用到分词。因为中文需要分词,可能会影响一些研究,但同时也为一些企业带来机会。
分词准确性对搜索引擎来说十分重要,但如果分词速度太慢,即使准确性再高,对于搜索引擎来说也是不可用的,因为搜索引擎需要处理数以亿计的网页,如果分词耗用的时间过长,会严重影响搜索引擎内容更新的速度。因此对于搜索引擎来说,分词的准确性和速度,二者都需要达到很高的要求。
二,
模型方法
(一)基本原则
合并原则:
1、语义上无法由组合成分直接相加而得到的字串应该合并为一个分词单位。
2、语类无法由组合成分直接得到的字串应该合并为一个分词单位。
3、附着性语(词)素和前后词合并为一个分词单位。
4、使用频率高或共现率高的字串尽量合并为一个分词单位
。
5、双音节加单音节的偏正式名词尽量合并为一个分词单位。
6、双音节结构的偏正式动词应尽量合并为一个分词单位
切分原则:
1、有明显分隔符标记的应该切分之
。
2、内部结构复杂、合并起来过于冗长的词尽量切分
(二)汉语自动分词基本算法
1.
最大匹配法
(MM)
?①正向最大匹配算法
(FMM)
?②逆向最大匹配算法
(BMM)
?③双向最大匹配算法
(MM)
FMM
算法描述:
(1)
令
i=0,当前指针
pi
指向输入字串的初始位置,执行下面的操作:
(2)
计算当前指针
pi到字串末端的字数(即未被切分字串的长度)n,如果n=1,转(4),结束算法。否则,令
m=词典中最长单词的字数,如果n,边对应的词默认为
ck
(
k
=1,2,…,n)。
(2)
如果
w=
cici+1…cj
(0,边对应的词为
w。
(3)
重复步骤(2),直到没有新路径(词序列)产生。
(4)
从产生的所有路径中,选择路径最短的(词数最少的)作为最终分词结果。
3.
基于语言模型的分词方法
方法描述:
设对于待切分的句子S,W
=
w1w2……wk
(1£
k
£
n)
是一种可能的切分。
4.
基于HMM的分词方法
基本思想:
把输入字串(句子)S
作为HMM
m
的输入;切分后的单词串
Sw
为状态的输出,即观察序列
5.
由字构词
(基于字标注)的分词方法
基本思想:
将分词过程看作是字的分类问题。该方法认为,每个字在构造一个特定的词语时都占据着一个确定的构词位置(即词位)。假定每个字只有4个词位:词首(B)、词中(M)、词尾(E)和单独成词(S),那么,每个字归属一特定的词位。
6.生成式方法与区分式方法的结合
大部分基于词的分词方法采用的是生成式模型而基于字的分词方法采用区分式模型(Discriminative
model):
本次实验主要采用FMM
三,
系统设计
(一)系统的详细设计:
宋词语料的处理:
1.对宋词语料进行分词处理是该系统的第一步,分词处理的目的是初步形成分词语料以及了解如何进行中文分词。
2.宋词语料大,首先我们需要对其进行抽样调查,经调查发现其中除了全角字符外,还有一些半角字符以及不能识别字符等,为此我们需要对这些问题进行处理。
3.采用识别国标码来进行分析,第一步:取出半角字符,以ch来进行存储,在排序过程中采用优先队列可以方便排序,从而避免使用结构体处理过程中的繁琐。
4.采用优先队列排序时,采用默认方式由高到低进行,排序过程中由于是以int(及对应的次数作为排序依据)所以需调整为map。采用此方法处理时时间复杂度、空间复杂度较低。
5.由于采用的是国标码而非扩展国标码,因而存在语料中的字无法识别,统计结果与实际结果存在偏差;对于标点符号的的处理默认其范围在8000h——B000h之间,因而可能会存在一些标点未能处理。
6.为了提高系统的召回率,可以采用“最短路径法”、“基于语言模型的分词法”等等相结合的方法,这样可以让系统的召回率更高。
7.可以考虑添加识别未登陆此,采用宋词语料的处理方式,对出现次数大于某一个数的词默认其为一个新词,这样系统的找回率可能会进一步提高,但所需语料必须很大,才能保证新词的正确率。
四,
系统演示与分析
(一)
宋词语料
一)代码:
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
ifstream
infile;
ofstream
outfile;
mapwordnum1;
mapwordnum2;
mapwordnum3;
priority_queue,vector
>
>
queue1;//定义优先队列
priority_queue,vector
>
>
queue2;
priority_queue,vector
>
>
queue3;
int
total1=0,total2=0,total3=0;
void
init()//文本初始化
{
infile.open(“Ci.txt“,ios::in);
if(!infile)
{
cerr“>temp[i];
if(infile.eof())
break;
if(temp[i]>temp[i];
continue;
}
s1=““;
s1+=temp[i++];
infile>>temp[i];
s1+=temp[i++];
wordnum1[s1]++;//对应字频加1
total1++;
//第二个字不是汉字,则重新输入
infile>>temp[i];//逐个字符读入
if(infile.eof())
break;
if(temp[i]>temp[i];
continue;
}
s2=““;
s2+=temp[i++];
infile>>temp[i];
s2+=temp[i++];
wordnum1[s2]++;//对应字频加1
total1++;
wordnum2[s1+s2]++;//对应字频加1
total2++;
//第三个字不是汉字,则重新输入
print:
infile>>temp[i];//逐个字符读入
if(infile.eof())
break;
if(temp[i]>temp[i];
continue;
}
s3=““;//汉字,则进行统计
s3+=temp[i++];
infile>>temp[i];
s3+=temp[i++];
wordnum1[s3]++;//对应字频加1
total1++;
wordnum2[s2+s3]++;//对应字频加1
total2++;
s1+=(s2+s3);
wordnum3[s1]++;//对应字频加1
total3++;
s1=s2;//重新赋值,跳转移到print
s2=s3;
i=4;
s3=““;
goto
print;
}
}
void
output1()//输出单词总数及种类
{
outfile::iterator
iter=wordnum1.begin();iter!=wordnum1.end();iter++)
{
queue1.push(make_pair(iter->second,iter->first));
}
for(map::iterator
iter=wordnum2.begin();iter!=wordnum2.end();iter++)
{
queue2.push(make_pair(iter->second,iter->first));
}
for(map::iterator
iter=wordnum3.begin();iter!=wordnum3.end();iter++)
{
queue3.push(make_pair(iter->second,iter->first));
}
}
void
output4()//输出统计结果
{
pairtmp;
outfile>K1;
cout>K2;
cout>K3;
output1();
while(!queue1.empty()
queue1.pop();
outfile
#include
#include
#include
#include
#include
#include
using
namespace
std;
ifstream
infile1,infile2,infile3,infile4;
ofstream
outfile1,outfile2,outfile3;
mapwordnum;
priority_queue,vector
>
>
queue1;//定义优先队列
void
init()//文本初始化
{
infile1.open(“1998.txt“,ios::in);//读人民日报语料
if(!infile1)
{
cerr>a;
infile2.open(a,ios::in);//待处理语料读入
if(!infile4)
{
cerr“>temp[i];//逐个字符读入
if(infile1.eof())
break;
if(temp[i]>temp[i];
continue;
}*/
while((temp[i]!=
/
))//读取
{
if(temp[i]==
{
)
break;
s+=temp[i];
i++;
infile1>>temp[i];
}
wordnum[s]++;//对应字频加1
s=““;
}
s=““;
while(true)//要分词语料的处理
,添加未登陆字
{
infile2>>temp1[0];//逐个字符读入
if(infile2.eof())
break;
if(temp1[0]>=0x80)//GB2312下的汉字,最小是0XB0
{
s+=temp1[0];
infile2>>temp1[1];
s+=temp1[1];
}
else
{
s=““;
continue;
}
wordnum[s]++;//对应字频加1
outfile2::iterator
iter=wordnum.begin();iter!=wordnum.end();iter++)
{
queue1.push(make_pair(iter->second,iter->first));
}
}
void
output()//输出统计结果
,已添加未登录字
{
pairtmp;
while(!queue1.empty())
{
tmp=queue1.top();
queue1.pop();
outfile1arr1,arr2;//利用容器存储数据
string
text=““;//存储待处理文本
string
word=““;//中间量
while(getline(infile4,word))//要分词语料的读入
{
text+=word;
}
word=““;
while(getline(infile3,word))//读入查找字典
{
arr1.push_back(word);
}
//正向最大匹配算法部分
string
temp1=text;//存储中间结果
string
temp2=temp1;//头指针
int
p1=0;
while(temp2.length()!=0)//字符串长度不为0时,分词
{
for(int
i=temp2.length();i>=0;i-=2)
{
if(find(arr1.begin(),arr1.end(),temp1)!=arr1.end())//找到,则在其后添加“/“,调整指针
{
temp1+=“/“;
arr2.push_back(temp1);
p1=i;
break;
}
else//去掉最右边的字
{
temp1=temp2.substr(0,i-2);
}
}
temp2=temp2.substr(p1);//指向切分后的语料
temp1=temp2;
}
for(vector::iterator
iter=arr2.begin();iter!=arr2.end();++iter)
{
//cout<<*iter;
outfile3<<*iter;
}
outfile3< } int main() { init();//初始化文本 double t; t=start();//计时 count(); //统计汉字个数 sort1(); //排序 output(); chdic(); close(); end(t); //计时结束 system(“pause“); return 0; } 二)结果演示: (三)对错原因: 1.国标码处理汉字范围有限。 2.有一些未登录词没有做处理。 3.FMM算法本身有缺陷。 4.语料数量有限,及编程过程的简化处理。 5.系统设计是一些细节未能考虑。 (四)提高: 1.采用扩展国标码处理问题。 2.在采用识别未登录字的基础上添加未登录词的识别。 3.采用FMM算法与其他算法想结合的分词方法。 4.考虑算法的具体实现细节。 五, 对本门课的感想、意见和建议 (一)感想: 1.通过《自然语言理解》这门课的学习,我明白了自然语言理解是:计算机理解人类的自然语言的研究方法和研究结果。同时,我也中文分词有了初步的理解,理解了中文分词产生的背景以及其广阔的应用领域。 2.通过自己动手做实验编程,我对FMM算法等有了一些初步的认识,明白了该算法的利弊。 3.《自然语言理解》作为一门新兴的课程,利用计算机来理解人类语言,是人工智能等研究领域的基础。 4.通过老师的讲解,我也对:词法分析、机器翻译、语言模型等知识有所理解。 5.学无止境,学以致用——虽然自然语言理解的课程短暂,但我们的学习不能局限于课堂学习,在学习之余我们还有很多事可以做,比如可以继续完善我们的分词系统,并利用分词系统来处理实际生活中的语料,通过对实际语料的处理、分析,将其应用于相关的实际中,在实际训练中提高自我。 (二)意见: 1.学习可是太少,理论知识学得不是很多,尤其是在实际做实验的时候,刚开始无从下手。 2.理论的目的在于结合实际,课堂讲解更应从实际出发,循序渐进引出中文分词及自然语言理解的由来,以及其中涉及的一些技术。 3.课堂互动环节不是太多,由于课时少以及对有些知识理解不够,不能对所学知识形成体系。 (三)建议: 1.希望课时能有所增加,这样我们对理论知识的理解会更加透彻。 2.作为一门新兴的课程,希望老师在授课手法上能够进一步创新,可以采用小组学习方式,在课程之初给每个小组一个选题,组员合作共同完成工程报告。在授课过程中,可以结合每个小组工作情况,对症下药,讲解理论知识。 3.实验初期比较迷茫,一方面是自身编程能力有限,另一方面我们一直习惯于有实验指导书,希望老师能够编写电子版实验指导书,同时在知道书中,就一些重难点、创新点方面给予引导。