- 论坛徽章:
- 0
|
本帖最后由 huihui_2012 于 2012-06-16 13:19 编辑
WRSeg分词器的java工程模块
本文所实现的WRSeg分词器以java语言开发。主要步骤在ChineseSegment这个工程中实现。这个工程引用了Tools工程中的一些工具类。因此,在使用时,要将Tools导入到ChineseSegment中。源代码见附件。源代码内有已经训练好的分词器,用户可以直接使用。因为受附件大小的限制,原始的训练语料没有在源代码包中(训练语料用的是北大标注的1998年1月的语料)。
源代码仅供学术参考使用,若用于商业用途,请联系我:zhonghui830506@163.com
ChineseSegment项目的目录结构如下:
其中Count类是用来统计词频,进而计算成词概率的类;CountBiGram继承Count,专门对二元语法概率进行计算。
MergeNameEntity类是用于解决人名、地名、机构名等的词语粒度问题。在原始语料中,人名中姓和名字被当作是两个词语。如“江 泽民”中姓氏“江”和名字“泽民”被当作两个词语。但是,这往往不符合实际需求。在实际需求中,我们通常不希望将名字分割。在地名、机构名中也会存在类似的情况。MergeNameEntity类中提供方法将人名、地名、机构名中的各个组成部分合成一个单一的词语。
统计的成词概率结果放在数据结构类SegModel类的对象中。
UnigramSeg是利用Unigram语法,利用动态规划进行分词的类。BigramSeg是利用二元语法进行分词的类。
199801q.txt是原始训练语料,语料中的人名、地名和机构名都没有采取MergeNameEntity类中所提供的合并策略。词典.txt是前面所提到的外部词典,里面的词语不是来自于199801q.txt。
biWordRate.out,wordFrequence.out,wordRate.out都是已经训练好的分词模型。这些模型中都已经对人名中的姓氏和名字进行了合并,但是没有对地名和机构名进行MergeNameEntity类中所提供的合并。wordFrequence.out是基于wordfreq的一元语法,wordRate.out是基于wordrate的一元语法。biWordRate.out是基于二元语法,分词效果最好。
SplitSentence_seg是基于分词开发的一些工具方法,可以忽略。
调用示例
调用方法。下面的例子展示了如何调用本文所述的工程:
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.tseg.seg.SegModel;
import org.tseg.seg.BigramSeg;
public class ChineseSegment {
//假如原句是:
// 邓玉娇是湖北人,在09年是热点新闻人物
// 则分词后的结果是(返回结果的词语之间用空格隔开):
// 邓玉娇 是 湖北 人 , 在 09年 是 热点 新闻 人物
public String seg(String line){
//用单例方法来获得分词器,这样为了避免分词器的重复加载
BigramSeg seg = BigramSeg.getSeg();
return seg.segment(line);
}
//假如原句是:
// 邓玉娇是湖北人,在09年是热点新闻人物
// 则分词后的结果是(返回结果放在一个ArrayList中):
// [邓玉娇, 是, 湖北, 人, ,, 在, 09年, 是, 热点, 新闻, 人物]
public ArrayList<String> getSegList(String line){
//用单例方法来获得分词器,这样为了避免分词器的重复加载
BigramSeg seg = BigramSeg.getSeg();
return seg.getSegWordList(line);
}
// 给分词器加入新词
public BigramSeg seggerWithNewWords(Collection<String> newWords){
//没有用取得单例的方法来获得分词器,这是为了不让新生成的分词器影响别的应用
BigramSeg seg = new BigramSeg(SegModel.biWordRateType);
for(String word : newWords){
if(!seg.getModel().wordLogProb.containsKey(word)){
seg.getModel().wordLogProb.put(word, 0.0);
}
}
return seg;
}
//将加入了新词的新的分词器保存到文件中
public void save(BigramSeg seg, String segPath) throws IOException{
seg.getModel().writeModel(segPath);
}
//从文件中读取分词器
public BigramSeg read(String segPath) throws IOException{
return new BigramSeg(segPath);
}
public void segTest() throws IOException{
String line = "邓玉娇是湖北人,在09年是热点新闻人物";
System.out.println(this.seg(line));
System.out.println(this.getSegList(line));
line = "邓玉娇刺官案在社会上反响很大!";
System.out.println(this.getSegList(line));
// 输出结果:[邓玉娇, 刺, 官案, 在, 社会, 上, 反响, 很, 大, !]
Set<String> newWords = new HashSet<String>();
newWords.add("刺官案");
BigramSeg seg = this.seggerWithNewWords(newWords); //往分词器里加入新词,生成一个新的分词器
System.out.println(seg.getSegWordList(line));
// 输出结果:[邓玉娇, 刺官案, 在, 社会, 上, 反响, 很, 大, !]
String segPath = "D:/xing/seg.out";
this.save(seg, segPath); //保存新分词器
BigramSeg newSeg = this.read(segPath); //读取刚保存的新分词器
System.out.println(newSeg.getSegWordList(line));
// 输出结果:[邓玉娇, 刺官案, 在, 社会, 上, 反响, 很, 大, !]
}
public static void main(String args[]) throws IOException{
ChineseSegment cst = new ChineseSegment();
cst.segTest();
}
}
|
|