NLP: 中文分词---正向匹配 (Forward Matching)
2014-07-11 17:14
295 查看
在采用FMM (正向最大匹配) 进行中文分词的时候, 可能会存在比较多的交集歧义, 这个时候为了解决交集歧义的问题, 可以采用 FM (Forwar Matching, 正向匹配) 进行中文分词, 正向匹配会在最大匹配的路径上查找所有可能成词的term(这里所有可能成词的term的意思是在构建索引的时候所有切分出来的词, 因为不是路径上的所有节点都会是切分成的词)。
http://blog.csdn.net/watkinsong/article/details/37696389 这个文章中给出了FMM(正向最大匹配) 的算法实现。
算法描述如下图给出, 下面的图比较多, 但是描述的比较详细。 图后给出代码实现。
FM算法最大的问题就是切分的结果太琐碎, 因为在一次FMM(正向最大匹配)的过程中, 路径上所有是term的节点都会作为一个切分结果。 这样做的好处就是可以减少交集歧义的影响。
接下来根据算法给出代码。 代码假设已经存在索引, 并且索引采用trie树进行保存。
仍然是JS代码。。。
var lunr = require("./lunr.js")
var idxdata = require("./idx.json")
var idx = lunr.Index.load(idxdata)
var ii = idx.tokenStore
var query1 = "中国人民银行指出我国最近经济不景气"
var query2 = "习近平今日出席了中央气象台的联欢晚会"
var query3 = "中国银行今日出台了最新的贷款政策"
var query5 = "全部门"
var query6 = "互联网金宝"
var query7 = "上下级别"
var query8 = "确定期"
var query9 = "引领土完整"
query = query6
var result = tokenizer(ii.root, query)
console.log(result)
/* tokenizer */
function tokenizer(root, str) {
if ( root == null || root == undefined ) return []
if ( str == null || str == undefined || str.length == 0 ) return []
var out = []
while ( str.length > 0 ) {
var ret = forwardMatching(root, str)
out = out.concat(ret)
str = str.slice(1)
}
return out
}
/* FM, this will return all the possible terms in along the longest search path */
function forwardMatching(root, str) {
if ( root == null || root == undefined ) return
if ( str == null || str == undefined || str.length == 0 ) return
var out = []
var matches = ""
var currentNode = root
for( var i = 0; i < str.length; i++ ) {
if (str[i] in currentNode ) {
matches += str[i]
currentNode = currentNode[str[i]]
docs = currentNode.docs || {}
if ( Object.keys(docs).length ) {
// if current node is a term, add this term as a segment piece
out.push(matches)
}
} else {
if ( matches.length == 0 ) {
// un-board word found
out.push(str[i])
}
break
}
}
return out
}
function getAmbiguiousLength(root, str, word_length) {
var i = 1
while ( i < word_length && i < str.length ) {
var wid = tokenize(root, str.slice(i))
wid = wid[0]
var length = wid.length
if ( word_length < i + length ) word_length = i + length
//console.log("i = " + i + ",length=" + wid.length + ", wid :" + wid + ", word_length : " + word_length)
i += 1
}
return word_length
}
测试:
query: "互联网金宝"
切分结果: [ '互联网', '网', '网金宝', '金', '宝' ]
这里, 因为在切分 “联网金宝”子句时, “联” 在索引中出现, 但是并不是一个term, 所以跳过“联”, 进行下一次切分“网金宝”
http://blog.csdn.net/watkinsong/article/details/37696389 这个文章中给出了FMM(正向最大匹配) 的算法实现。
算法描述如下图给出, 下面的图比较多, 但是描述的比较详细。 图后给出代码实现。
FM算法最大的问题就是切分的结果太琐碎, 因为在一次FMM(正向最大匹配)的过程中, 路径上所有是term的节点都会作为一个切分结果。 这样做的好处就是可以减少交集歧义的影响。
接下来根据算法给出代码。 代码假设已经存在索引, 并且索引采用trie树进行保存。
仍然是JS代码。。。
var lunr = require("./lunr.js")
var idxdata = require("./idx.json")
var idx = lunr.Index.load(idxdata)
var ii = idx.tokenStore
var query1 = "中国人民银行指出我国最近经济不景气"
var query2 = "习近平今日出席了中央气象台的联欢晚会"
var query3 = "中国银行今日出台了最新的贷款政策"
var query5 = "全部门"
var query6 = "互联网金宝"
var query7 = "上下级别"
var query8 = "确定期"
var query9 = "引领土完整"
query = query6
var result = tokenizer(ii.root, query)
console.log(result)
/* tokenizer */
function tokenizer(root, str) {
if ( root == null || root == undefined ) return []
if ( str == null || str == undefined || str.length == 0 ) return []
var out = []
while ( str.length > 0 ) {
var ret = forwardMatching(root, str)
out = out.concat(ret)
str = str.slice(1)
}
return out
}
/* FM, this will return all the possible terms in along the longest search path */
function forwardMatching(root, str) {
if ( root == null || root == undefined ) return
if ( str == null || str == undefined || str.length == 0 ) return
var out = []
var matches = ""
var currentNode = root
for( var i = 0; i < str.length; i++ ) {
if (str[i] in currentNode ) {
matches += str[i]
currentNode = currentNode[str[i]]
docs = currentNode.docs || {}
if ( Object.keys(docs).length ) {
// if current node is a term, add this term as a segment piece
out.push(matches)
}
} else {
if ( matches.length == 0 ) {
// un-board word found
out.push(str[i])
}
break
}
}
return out
}
function getAmbiguiousLength(root, str, word_length) {
var i = 1
while ( i < word_length && i < str.length ) {
var wid = tokenize(root, str.slice(i))
wid = wid[0]
var length = wid.length
if ( word_length < i + length ) word_length = i + length
//console.log("i = " + i + ",length=" + wid.length + ", wid :" + wid + ", word_length : " + word_length)
i += 1
}
return word_length
}
测试:
query: "互联网金宝"
切分结果: [ '互联网', '网', '网金宝', '金', '宝' ]
这里, 因为在切分 “联网金宝”子句时, “联” 在索引中出现, 但是并不是一个term, 所以跳过“联”, 进行下一次切分“网金宝”
相关文章推荐
- NLP: 中文分词算法--正向最大匹配 Forward Maximum Matching
- NLP中文信息处理---正向最大匹配法分词
- NLP中文信息处理---正向最大匹配法分词
- python中文分词教程之前向最大正向匹配算法详解
- 中文分词基础原则及正向最大匹配法、逆向最大匹配法、双向最大匹配法的分析
- 中文分词基础原则及正向最大匹配法、逆向最大匹配法、双向最大匹配法的分析
- java中文分词之正向最大匹配法实例代码
- 中文分词 (机械传统方法 )正向最大匹配
- 一个简单最大正向匹配(Maximum Matching)MM中文分词算法的实现
- 正向最大匹配中文分词算法
- 中文分词——正向最大匹配法
- (2)中文分词——最大正向匹配算法及MMSEG分词算法
- 中文分词算法之最大正向匹配算法(Python版)
- 【分词】正向最大匹配中文分词算法
- 中文分词——正向最大匹配法
- 中文分词中的正向最大匹配与逆向最大匹配
- 【分词】正向最大匹配中文分词算法
- 一个简单最大正向匹配(Maximum Matching)MM中文分词算法的实现
- 正向最大匹配中文分词算法
- python 中文分词:正向最大匹配