一、前言

上节介绍了ansj的原子切分和全切分。切分完成之后,就要构建最短路径,得到分词结果。
以“商品和服务”为例,调用ansj的标准分词:
String str = "商品和服务" ;
Result result = ToAnalysis.parse(str);
System.out.println(result.getTerms());
先不管数字发现、人名识别、用户自定义词典的识别,暂时只考虑ToAnalysis类里面,构建最短路径的这行代码:
graph.walkPath();
上面这行代码执行前,已完成了全切分,构建了如下的有向无环图:

事实上,此时没有“务”这个节点

如上图所示,terms[4] = null。
不过这也没关系,后面给节点打分时,会填充这个null,这段代码位于Graph.merger(Term fromTerm, int to, Map<String, Double> relationMap):
char c = chars[to];
TermNatures tn = DATDictionary.getItem(c).termNatures;
if (tn == null || tn == TermNatures.NULL) {
tn = TermNatures.NULL;
}
terms[to] = new Term(String.valueOf(c), to, tn);
也就是说,给“和服”的后继节点打分时,发现其后继节点为null,那么就实例化一个Term,填充在terms[to]的位置。

二、理论基础

两个节点之间分之计算的代码位于MathUtil.compuScore(Term from, Term to, Map<String, Double> relationMap)
其中核心代码只有一行:
double value = -Math.log(dSmoothingPara * frequency / (MAX_FREQUENCE + 80000) + (1 - dSmoothingPara) * ((1 - dTemp) * nTwoWordsFreq / frequency + dTemp));
我们了探讨一下这行代码的理论基础。
首先,ansj使用二元语法模型(Bigram)进行分词。Bigram模型对应于一阶Markov假设,词只与其前面一个词相关,其对应的分词模型:
$arg\,max\prod_{m}^{i=1}P({w}_{i}|{w}_{i-1})\, =\,arg\,min-\sum_{m}^{i=1}logP({w}_{i}|{w}_{i-1})$
该等式将求解最大联合概率的问题转化为了求解有向无环图最短路径问题。
其中,数学符号arg表示使目标函数取最小值时的变量值。这里是指求解条件概率之积$\prod_{m}^{i=1}P({w}_{i}|{w}_{i-1})$取最大值时的分词结果。
对条件概率$P({w}_{i}|{w}_{i-1})$做如下的平滑处理:

\begin{aligned}
- \log P(w_{i} | w_{i-1}) & \approx - \log \left[ aP(w_{i-1}) + (1-a) P(w_{i}|w_{i-1}) \right] \\
& \approx - \log \left[ a\frac{f(w_i)}{N} + (1-a) \left( \frac{(1-\lambda)f(w_{i-1},w_i)}{f(w_{i-1})} + \lambda \right) \right]
\end{aligned}

其中,a = 0.1为平滑因子,N = 207997为训练语料中的总次数,$\lambda \,=\,\frac{1}{N}$。
第一个约等式是采用线性插值法(Linear Interpolation)(可参考自然语言处理:盘点一下数据平滑算法)进行平滑处理。
第二个约等式,我还没搞清楚是什么处理。

三、具体打分流程如下

代码位于Graph.walkPath(Map<String, Double> relationMap)。
Ansj采用了类似于Dijkstra的动态规划算法(作者称之为Viterbi算法)来求解最短路径。
如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点,那么(Vi...Vk)也必定是从i到k的最短路径。(可参考Dijkstra算法
1、从起始节点“始##始”开始,对其后继节点打分

设置“商”、“商品”的前驱节点(也就是Term类的from属性)为“始##始”。
2、计算“商”后继节点的分值

只有一个后继节点“品”。“商”和“品”的分值是13.509,因此从“始##始”到“品”的分值是19.56。
设置“品”的前驱节点为“商”。
3、计算“商品”后继节点分值

设置“和”、“和服”的前驱节点为“商品”。
4、计算“品”后继节点分值

以“和”为例,“和”有“商品”、“品”两个前驱节点。应该取分值最小的那个。因此,“和”的分值依然是8.92,前驱节点依然是“商品”。
同理,“和服”的前驱节点依然是“商品”。
对上图进行简化:

5、计算“和”后继节点分值

设置“服”、“服务”的前驱节点为“和”。
6、计算“和服”后继节点分值

设置“务”的前驱节点为“和服”。
对上图简化:

7、计算“服”后继节点分值

“务”以“服”为前驱,可以得到更小的分值。因此,更改“务”的前驱节点为“服”。
对上图简化:

8、计算“服务”后继节点分值

设置“末##末”的前驱节点为“服务”。
9、计算“务”后继节点分值

“末##末”以“服务”为前驱节点,分值更新。因此,“末##末”的前驱节点依然是“服务”。
对上图简化:

10、设置后继节点
目前已构建了最短路径,并且知道了每个节点的前驱节点。
例如,“末##末”的前驱节点是“服务”。但是并没有将“服务”的后继节点(也就是Term类的to属性)设置为“末##末”。
Graph.optimalRoot()就是设置后继节点的。执行完该方法后,terms被简化为了如下形式:

去掉null,就是分词结果了。

参考资料

ansj构造最短路径的更多相关文章

  1. ansj人名识别

    1.前言 ansj人名识别会用到两个字典,分别是:person/asian_name_freq.data.person/person.dic. 1.1.asian_name_freq.data 这是一 ...

  2. 关于Floyd-Warshall算法由前趋矩阵计算出的最短路径反映出了算法的执行过程特性的证明

    引言:Floyd-Warshall算法作为经典的动态规划算法,能够在O(n3)复杂度之内计算出所有点对之间的最短路径,且由于其常数较小,对于中等规模数据运行效率依然可观.算法共使用n此迭代,n为顶点个 ...

  3. 最短路径树:Dijstra算法

    一.背景 全文根据<算法-第四版>,Dijkstra算法.我们把问题抽象为2步:1.数据结构抽象   2.实现 二.算法分析 2.1 数据结构 顶点+边->图.注意:Dijkstra ...

  4. cocos2d-js版本A*算法

    [转]http://blog.csdn.net/realcrazysun1/article/details/43054229 A*算法的东西网上讲了很多~但还是不可避免的要去研究一下,cocos官网上 ...

  5. OSPF详解

    OSPF 详解 (1) [此博文包含图片] (2013-02-04 18:02:33) 转载 ▼ 标签: 端的 第二 以太 第一个 正在 目录 序言 初学乍练 循序渐进学习OSPF 朱皓 入门之前 了 ...

  6. 树链剖分-点的分治(点数为k且距离最长的点对)

    hdu4871 Shortest-path tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 130712/130712 K ( ...

  7. LeetCode--064--最小路径和

    给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入:[  [1,3,1], [1,5,1], ...

  8. Dijkstra算法构造单源点最短路径

    迪杰斯特拉(Dijkstra)算法 是求从某个源点到其余各顶点的最短路径,即对已知图 G=(V,E),给定源顶点 s∈V,找出 s 到图中其它各顶点的最短路径. 我总结下核心算法,伪代码如下: Dij ...

  9. BZOJ 4016 最短路径树问题 最短路径树构造+点分治

    题目: BZOJ4016最短路径树问题 分析: 大家都说这是一道强行拼出来的题,属于是两种算法的模板题. 我们用dijkstra算法算出1为源点的最短路数组,然后遍历一下建出最短路树. 之后就是裸的点 ...

随机推荐

  1. 图像边缘检测--OpenCV之cvCanny函数

    图像边缘检测--OpenCV之cvCanny函数 分类: C/C++ void cvCanny( const CvArr* image, CvArr* edges, double threshold1 ...

  2. XMPP系列(二)----用户注册和用户登录功能

    1.创建一个新工程 2.导入XMPP框架 最新的XMPP框架下载地址:https://github.com/robbiehanson/XMPPFramework 将XMPP的几个文件夹拖进工程中,需要 ...

  3. 猴子吃桃问题---C实现

    原题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了了一个.第二天早上又将剩下的桃子吃掉一半,又多吃了一个.以后每一天早上都吃前一天剩下桃子的一半零一个.到第十天早上想再吃时,发现 只剩下 ...

  4. 从开发者角度解析 Android N 新特性!

    大清早看到 Google 官方博客发布 Android N 的开发者预览版,立马从床上跳起来开始仔仔细细的读起来. 从开发者角度来看,Android N 的更新并不算大.网上之前流传的一些 Andro ...

  5. MASM中3中文本宏的使用与区别

    = 宏 格式 : name = exp 其中,exp只能为32位整数值,且用=宏定义的符号名称可以重定义: EQU 宏 格式1:name EQU exp exp为有效整数值,可以重定义: 格式2:na ...

  6. css选择器应用

    .mynav li:not(:last-child) { margin-right: 20px; }

  7. Windows上模拟Linux环境的软件Cygwin

    Windows上模拟Linux环境的软件Cygwin 2010-10-11 15:19      我要评论(0) 字号:T|T Cygwin是一个用于在Windows上 模拟Linux环境的软件.它可 ...

  8. 关于非现场审计软件的一些介绍(ACL、IEDA、Teammate)

    http://group.vsharing.com/Article.aspx?aid=661512 IDEA是由caseware开发的数据分析软件.caseware的网址如下:http://www.c ...

  9. SQL Server复制表结构和表数据生成新表的语句

    参考:http://topic.csdn.net/t/20020621/09/820025.html SELECT   *   INTO   newTableName   FROM   oldTabl ...

  10. 体育Bank2016会议笔记

    补注:会议全称应该是体育Bank2016体育投融资总裁年会 新华社体育部徐仁基 演讲主题:帮郭川找到大海-->帮民众找到自己真正的体育爱好 激发和培养体育市场是重中之重 将体育培养成生活习惯.生 ...