分词的简单算法
1.完全切分
即在字典中查找到某个词 ,就切分
2.正向切分
从左到右开始匹配最大长度词,例如北京真好玩,
i = 0 时:北、北京 (当前最大词)、北京真、北京真好、北京真好玩 i = i + length(longestWord) = 0 + 2 = 2
i = 2时:真、真好、真好玩(最大词)i = 5
3.逆向切分
从右到左开始匹配最大长度词,例如北京真好玩,
i = 4时,北京真好玩、京真好玩、真好玩(最大词)、好玩、玩 i = length(text) - length(longestWord) = 4-3 = 1
同理
4.双向切分
左右各切一遍,谁的结果分词数量少取谁,若分词数量一样,则取分词结果中单字少的结果。
5.提升分词器性能
嗯,还在研究中。。。。。。好难T T,大概就是用TreeMap存储字典的话,从TreeMap查询词的效率低,采用字典树存储字典,词的查询效率会明显提升,从而使得分词效率明显提升。https://blog.csdn.net/johnny901114/article/details/80711441 字典树的学习,But 该博客字典树的实现还是通过TreeMap实现的,所以大致了解一下思路就好。。。
6.分词器性能评估
主要指标有:P精确率、R召回率、F1调和平均值、OOV_R:未登录词的召回率、IV_R:登录词的召回率
因为P = TP/(TP+FP)即从预测的角度,计算预测的准确性,而R=TP/(TP+FN)即从事实的角度,计算现实正确的有多少被预测出。又因为在分词问题中,标准答案和分词结果的单词数不一定相等,而且混淆矩阵针对的是分类问题,而中文分词针对的是分块 问题,则将标准答案作为A(从事实的角度),分词结果作为B(从预测的角度),则两者重复的区域为TP,即预测对的区域。故有以下公式:
TP∪FN = A、TP∪FP = B、TP = A∩B
P = |A∩B|/|B|
R = |A∩B|/|A|
书上例子:
标准答案(A):结婚 的 和 尚未 结婚 的
分词结果(B):结婚 的 和尚 未结婚 的
重合部分(A∩B):结婚、的、的
则P = 3/5=0.6、R=3/6=0.5、F1=2*0.6*0.5/(0.6+0.5) = 0.55
7.代码实现
[分词器]
package HanLpTest;
import com.hankcs.hanlp.collection.trie.bintrie.BinTrie;
import com.hankcs.hanlp.corpus.io.IOUtil;
import com.hankcs.hanlp.dictionary.CoreDictionary;
import org.antlr.v4.runtime.ListTokenSource;
import java.io.IOException;
import java.util.*;
public class HanLpCut {
public static List<String> segementFully(String text,Map dictionary){
List<String> wordList = new LinkedList<String>();
for(int i=0;i<text.length();i++){
for(int j=i+1;j<text.length();j++){
String word = text.substring(i,j);
if (dictionary.containsKey(word)){
wordList.add(word);
}
}
}
return wordList;
}
public static List<String> maxPosMatch(String text,Map dictionary){
List<String> wordList = new LinkedList<String>();
for(int i=0;i<te