IKAnalyzer结合Lucene使用和单独使用例子 简单性能测试

使用到的Jar包: 结合Lucene使用 直接通过Analyzer进行分词 使用IKSegmenter进行分词 性能测试:

IKAnalyzer是一个开源基于JAVA语言的轻量级的中文分词第三方工具包,采用了特有的“正向迭代最细粒度切分算法“,支持细粒度和智能分词两种切分模式。刚开始使用的时候,发现不能支持中文和字母混合的分词,例如:iPhone5s土豪金。后来发现在2012版本,词典支持中文,英文,数字混合词语,并且优化了词典存储,内存更小的占用。支持用户词典扩展定义。为了更好的测试,这里就使用了IKAnalyzer2012_u6这个版本。

使用到的Jar包:
  • IKAnalyzer2012_u6.jar
  • lucene-core-3.6.0.jar

把 IKAnalyzer中的IKAnalyzer.cfg.xml, ext.dic(如果找不到,可以手动创建一个该文件), stopword.dic文件放到代码的根目录中。

结合Lucene使用

下载下来的Jar包是包含了结合Lucene使用的例子,先把要检索的内容,写入Lucene索引,然后根据需要查找的关键词,通过Lucene的QueryParser对象进行解析查找,构造该QueryParser对象的时候,传入了IKAnalyzer,进而通过IKAnalyzer进行分词:

Analyzer analyzer = new IKAnalyzer(true);
QueryParser qp = new QueryParser(Version.LUCENE_34, fieldName, analyzer);

ext.dic词典如下:

iPhone5s土豪金
2014巴西世界杯

完整代码如下:

// 使用Lucene分词  
//Lucene Document的域名
String fieldName = "text";
//检索内容
String text = "据说WWDC要推出iPhone6要出了?与iPhone5s土豪金相比怎样呢?";
//实例化IKAnalyzer分词器
Analyzer analyzer = new IKAnalyzer(true);

Directory directory = null;
IndexWriter iwriter = null;
IndexReader ireader = null;
IndexSearcher isearcher = null;
try {
    //建立内存索引对象
    directory = new RAMDirectory();     

    //配置IndexWriterConfig
    IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_34 , analyzer);
    iwConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
    iwriter = new IndexWriter(directory , iwConfig);
    //写入索引
    Document doc = new Document();
    doc.add(new Field("ID", "10000", Field.Store.YES, Field.Index.NOT_ANALYZED));
    doc.add(new Field(fieldName, text, Field.Store.YES, Field.Index.ANALYZED));
    iwriter.addDocument(doc);
    iwriter.close();

    //搜索过程**********************************
    //实例化搜索器   
    ireader = IndexReader.open(directory);
    isearcher = new IndexSearcher(ireader);            

    String keyword = "iPhone5s土豪金";            
    //使用QueryParser查询分析器构造Query对象
    QueryParser qp = new QueryParser(Version.LUCENE_34, fieldName, analyzer);
    qp.setDefaultOperator(QueryParser.AND_OPERATOR);
    Query query = qp.parse(keyword);
    System.out.println("Query = " + query);

    //搜索相似度最高的5条记录
    TopDocs topDocs = isearcher.search(query , 5);
    System.out.println("命中:" + topDocs.totalHits);
    //输出结果
    ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    for (int i = 0; i < topDocs.totalHits; i++){
        Document targetDoc = isearcher.doc(scoreDocs[i].doc);
        System.out.println("内容:" + targetDoc.toString());
    }

} catch (CorruptIndexException e) {
    e.printStackTrace();
} catch (LockObtainFailedException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (ParseException e) {
    e.printStackTrace();
} finally{
    if(ireader != null){
        try {
            ireader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    if(directory != null){
        try {
            directory.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

执行结果:

加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
Query = text:iphone5s土豪金
命中:1
内容:Document<stored,indexed<ID:10000> stored,indexed,tokenized<text:据说WWDC要推出iPhone6要出了?与iPhone5s土豪金相比怎样呢?>>
直接通过Analyzer进行分词

如果我们不需要建立Lucene索引文件,而是单纯的对一段文本进行分词,可以直接创建一个org.apache.lucene.analysis.Analyzer分词对象(org.wltea.analyzer.lucene.IKAnalyzer IK分词主类,基于Lucene的Analyzer接口实现)进行遍历分词数据。

下面演示下,并且在分词之前额外的添加一些单词到字典中。ext.dic词典如下:

iPhone5s土豪金
2014巴西世界杯

代码如下:

// 检索内容
String text = "据说WWDC要推出iPhone6要出了?与iPhone5s土豪金相比怎样呢?@2014巴西世界杯 test中文";
List<String> list = new ArrayList<String>();
list.add("test中文");

// 尚未初始化,因为第一次执行分词的时候才会初始化,为了在执行分此前手动添加额外的字典,需要先手动的初始化一下
Dictionary.initial(DefaultConfig.getInstance());
Dictionary.getSingleton().addWords(list);

//创建分词对象  
Analyzer analyzer = new IKAnalyzer(true);       
StringReader reader = new StringReader(text);  

TokenStream ts = analyzer.tokenStream("", reader);  
CharTermAttribute term = ts.getAttribute(CharTermAttribute.class);  
//遍历分词数据  
try {
    while(ts.incrementToken()){  
        System.out.print(term.toString()+"|");  
    }
} catch (IOException e) {
    e.printStackTrace();
} finally{
    reader.close();
}

执行结果:

加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
据说|wwdc|要|推出|iphone6|要|出了|与|iphone5s土豪金|相比|怎样|呢|2014巴西世界杯|test中文|
使用IKSegmenter进行分词

另外,如果想不结合Lucene(不使用lucene-core-3.6.0.jar),而是仅仅单独的使用IKAnalyzer,可以直接使用IK分词器的核心类,真正分词的实现类IKSegmenter分词器进行分词,代码如下:

// 单独使用
// 检索内容
String text = "据说WWDC要推出iPhone6要出了?与iPhone5s相比怎样呢?@2014巴西世界杯";

// 创建分词对象  
StringReader reader = new StringReader(text);

IKSegmenter ik = new IKSegmenter(reader,true);// 当为true时,分词器进行最大词长切分
Lexeme lexeme = null;
try {
    while((lexeme = ik.next())!=null)
        System.out.println(lexeme.getLexemeText());
} catch (IOException e) {
    e.printStackTrace();
} finally{
    reader.close();
}
性能测试:

检测目标:在单独使用IKAnalyzer的情况下,尽量往扩展字典添加词组,测试十几万长度的文本的分词效率。

扩展词库添加搜狗词库:

http://pinyin.sogou.com/dict/cell.php?id=11640
词条 大小 检索内容字数
392790个 13737KB 158453

代码如下:

// 计算载入字典时间
long startLoadDict = System.currentTimeMillis();
Dictionary.initial(DefaultConfig.getInstance());
long endLoadDict = System.currentTimeMillis();

// 创建分词对象  
StringReader reader = new StringReader(text);
Lexeme lexeme = null;
int hintTimes = 0;
IKSegmenter ik = new IKSegmenter(reader,true);// 当为true时,分词器进行最大词长切分
long start = System.currentTimeMillis();
try {
    while((lexeme = ik.next())!=null)
        hintTimes ++;
} catch (IOException e) {
    e.printStackTrace();
} finally{
    reader.close();
}
long end = System.currentTimeMillis();
System.out.println("载入字典时间:" + (endLoadDict - startLoadDict)/1000.0);
System.out.println("处理文本字数:" + text.length());
System.out.println("获取词元次数:" + hintTimes);
System.out.println("执行总时间:" + (end - start)/1000.0 + "s");
System.out.println("处理速度:" + text.length() / ((end - start)/1000.0) + "字/秒");
System.out.println("本次获取词元速度:" + hintTimes / ((end - start)/1000.0) + "词/秒");

IKAnalyzer本身有27W的词库,加上扩展词典,经过优化的方式存储到内存空间中的。

结果:

加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
载入字典时间:2.51
处理文本字数:158453
获取词元次数:54424
执行总时间:0.46s
处理速度:344463.04347826086字/秒
本次获取词元速度:118313.04347826086词/秒
======================================================================

   
   
   
   
原文地址: http://www.itzhai.com/ikanalyzer-lucene-demo-performance-test.html






你可能感兴趣的:(IKAnalyzer结合Lucene使用和单独使用例子 简单性能测试)