您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 隐马尔科夫模型分词器
隐马尔科夫模型中文分词工程报告一,研究背景随着互联网技术的发展,计算机在人们的生产生活当中起着不可或缺的作用,而计算机对中文的分词,理解,以及翻译也随着社会生产力的发展,需求量也越来越大,而中文词汇多,语义繁杂,语法不清晰的问题也随之暴露出来,所以一个好的中文分词模型对建立中文分词系统起着至关重要的作用。二,模型方法本工程主要采用了隐马尔科夫模型。隐马尔可夫模型可以表示为一个五元组(S,O,A,B,)S是一组状态的集合。S={‘S’,‘I’,‘B’,‘E’}O是一组输出符号的集合。A是状态转移矩阵。符号B输出概是率分布B={P(vk|j)}P(vk|j)表示在状态j时输出符号vk的概率π是初始状态概率分布π={i}πi=P(q1=i)表示初始选择某个状态的概率。首先,在A矩阵中求出各个状态之间转移的概率,再算出B中在状态J时输出符号vk的概率,然后算出各种情况下的概率情况,最后所得的最大概率的序列就是中文分词的序列例如:模型的参数已知,评价某个分词结果我爱你程序员SSSBIEValue=½*P(S-S)*P(S-S)*P(S-B)*P(B-I)*P(I-E)*P(我|S)*P(爱|S)*P(你|S)*P(程|B)*P(序|I)*P(员|S)求得最佳的转换序列,再进行相应的匹配,就能得到所求的中文分词了三,系统设计首先,我们需要统计很多词语来用程序训练。选取人民日报上的语料库的格式如下:我们在一个单独的程序里一行一行的读入这些语料,并依据JAVA中String包的split()函数对这一行的许多元组按照”\\s+”来拆分成一个个小元组,例如:迈向/vt,充满/vt.然后对单个的小元组按照”/”来拆分,并统计重复的词的个数。最终在新的文件里形成:词组词性词出现的个数,这样的形式。所用到的源代码如下:VectorStringall=newVectorString();VectorStringvocabu=newVectorString();VectorStringgrammar=newVectorString();VectorIntegernum=newVectorInteger();Files=newFile(D:\\we.txt);Filew=newFile(D:\\result.txt);FileWriterfw=newFileWriter(w);FileReaderfr=null;fr=newFileReader(s);@SuppressWarnings(resource)BufferedReaderfis=newBufferedReader(fr);Stringstr=null;inti,j;while((str=fis.readLine())!=null){i=0;j=1;String[]sp=str.split(\\s+);for(i=0;isp.length;i++){all.add(i,sp[i]);}if(!all.isEmpty()){for(j=0;jall.size();j++){Stringcizu=all.elementAt(j);String[]sic=cizu.split(/);//System.out.println(sic[0]+);if(sic[0].length()15&&sic[0].length()0&&sic.length==2){intweizhi=vocabu.indexOf(sic[0]);//System.out.println(sic[0]);if(weizhi==-1){vocabu.add(sic[0]);grammar.add(sic[1]);num.add(1);}else{intcount=num.remove(weizhi);count=count+1;num.add(weizhi,count);}}}}//System.out.println(all);all.removeAllElements();//str=fis.readLine();}//System.out.println(vocabu);//System.out.println(grammar);//System.out.println(num);longnumber=0;for(intas=0;asnum.size();as++){number=number+num.get(as);}System.out.println(number);for(inte=0;evocabu.size();e++){Stringa0=String.valueOf(e+1);Stringa1=vocabu.get(e);Stringa2=grammar.get(e);Stringa3=String.valueOf(num.get(e));Stringa=a1+\t+a2+\t+a3+\r\n;char[]buffer1=newchar[a.length()];buffer1=a.toCharArray();fw.write(buffer1);}fw.close();fr.close();结果如下图所示:然后对每个词分析,如果是单字,则用S表示,如果是一个词,则词首用B表示,词尾用W表示,词中用E表示,并统计次数。例如迈向===BW中共中央===BEEW程序源代码如下:VectorStringvocabu=newVectorString();VectorIntegernum=newVectorInteger();Filew=newFile(D:\\result.txt);Files=newFile(D:\\Aun.txt);FileWriterfs2=newFileWriter(s);FileReaderfr=newFileReader(w);@SuppressWarnings(resource)BufferedReaderfis=newBufferedReader(fr);Stringstr=null;while((str=fis.readLine())!=null){String[]spr=str.split(\t);if(spr[0].length()==1){if(vocabu.contains(spr[0]++S)){inti=vocabu.indexOf(spr[0]++S);intj=num.remove(i);intm=j+Integer.parseInt(spr[2]);num.add(i,m);}else{vocabu.add(spr[0]++S);num.add(Integer.parseInt(spr[2]));}}else{if(vocabu.contains(String.valueOf(spr[0].charAt(0))++B)){inti=vocabu.indexOf(String.valueOf(spr[0].charAt(0))++B);intj=num.remove(i);intm=j+Integer.parseInt(spr[2]);num.add(i,m);}else{vocabu.add(String.valueOf(spr[0].charAt(0))++B);num.add(Integer.parseInt(spr[2]));}if(vocabu.contains(String.valueOf(spr[0].charAt(spr[0].length()-1))++W)){inti=vocabu.indexOf(String.valueOf(spr[0].charAt(spr[0].length()-1))++W);intj=num.remove(i);intm=j+Integer.parseInt(spr[2]);num.add(i,m);}else{vocabu.add(String.valueOf(String.valueOf(spr[0].charAt(spr[0].length()-1))++W));num.add(Integer.parseInt(spr[2]));}if(spr.length2){for(inte=1;espr[0].length();e++){if(vocabu.contains(String.valueOf(spr[0].charAt(e))++E)){inti=vocabu.indexOf(String.valueOf(spr[0].charAt(e))++E);intj=num.remove(i);intm=j+Integer.parseInt(spr[2]);num.add(i,m);}else{vocabu.add(String.valueOf(spr[0].charAt(e))++E);num.add(Integer.parseInt(spr[2]));}}}}}for(inte=0;evocabu.size();e++)//将更改后的VECTOR写入新的文件{Stringa1=vocabu.get(e);Stringa3=String.valueOf(num.get(e));Stringa=a1+\t+a3+\r\n;char[]buffer1=newchar[a.length()];buffer1=a.toCharArray();fs2.write(buffer1);}fs2.close();//并形成新的文件如下:根据这些SWEB来分析S-BB-ES-SB-WE-EE-WW-SW-B的次数,并得到A矩阵,A矩阵分别是以上SWEB的概率次数。A矩阵的代码如下:double[][]anun=newdouble[4][4];for(inti=0;isweb.size()-1;i++){Stringa=sweb.get(i);Stringb=sweb.get(i+1);if(a.equalsIgnoreCase(S)&&b.equalsIgnoreCase(S)){anun[0][0]+=1;}if(a.equalsIgnoreCase(S)&&b.equalsIgnoreCase(B)){anun[0][1]+=1;}if(a.equalsIgnoreCase(B)&&b.equalsIgnoreCase(E)){anun[1][2]+=1;}if(a.equalsIgnoreCase(B)&&b.equalsIgnoreCase(W)){anun[1][3]+=1;}if(a.equalsIgnoreCase(E)&&b.equalsIgnoreCase(W)){anun[2][3]+=1;}if(a.equalsIgnoreCase(W)&&b.equalsIgnoreCase(S)){anun[3][0]+=1;}if(a.equalsIgnoreCase(W)&&b.equalsIgnoreCase(B)){anun[3][1]+=1;}if(a.equalsIgnoreCase(E)&&b.equalsIgnoreCase(E)){anun[2][2]+=1;}}其中sweb为一个Vector向量,存储SWEB的序列。求得A矩阵后,我们输入一串中文字符,以每个字出现SWEB的次数来代替其概率构造出B矩阵。在B矩阵中,用魏特碧算法,从第二个字开始,计算前一个字的每一种状态的概率乘上后一个的某一种状态的概率再乘上A矩阵中对应的两中状态之间的概率。比较并取得最大值,依次计算存储并获得一个矩阵,定义为T1,然后将每种状态概率最大值对应的前一种状态记录(SWEB分别用0123代替)并存储为新的矩阵T2,最后在T1矩阵的最后一列中找到最大值,并在T2矩阵中找到对应的位置,依次向前取相应位置的值并记录,得到一个和输入的中文字符串长度一样的数字串。源代码如下:intj=zhongwen.length();doubleps[][]
本文标题:隐马尔科夫模型分词器
链接地址:https://www.777doc.com/doc-1956026 .html