zoukankan      html  css  js  c++  java
  • 最短路径分词

    中文分词有很多方法,比如N-最短路径法,N元语言模型,CRF模型等等。大致可以分为两类:一是机械化的分词,二是用机器学习方法分词。最短路径算法可以划分到第一种。这个算法效果并不是最好的,大体和IK分词打成平手。今天用最简洁语言描述一下:这个算法主要分两步:第一,构造DAG(有向无环图),第二找出最优路径。以下图为例 "有意见分歧”进行分词。首先构造下图中的左边的DAG:节点用0~5来表示,每条边都有起点和终点构成有向图。比如从0节点开始,0~1和0~2构成了两条边,分别代表右图中的有和有意两个词。以此类推,1节点:1~2,1~3。其中,用词在词典中出现的频率来代表边的属性。构建完毕后,我们发现,从0~5有多条路径:0-1-3-5,0-1-2-4-5,0-1-2-3-5,0-1-2-3-4-5,……找出最优路径来,即找出频率之和最大的路径,也就是对应每个起点的边的属性最大。比如,从0开始,0-1的属性最大,然后以1为起点,1-3属性最大,再以3为起点,3-5属性最大。即最优路径:0-1-3-5.有 意见 分歧。下面用Python代码简单示例之:

     1 # encoding=utf-8
     2 
     3 class WordDictModel:
     4     def __init__(self):
     5         self.word_dict = {}
     6         self.stop_words = {}
     7 
     8     def load_data(self, filename):
     9         with open(filename, "r", encoding="utf-8") as fr:
    10             for line in fr:
    11                 words = line.split(" ")
    12                 for word in words:
    13                     if word in self.stop_words:
    14                         continue
    15                     self.word_dict[word] = self.word_dict.get(word,0) + 1
    16 
    17 class DAGSegger(WordDictModel):
    18     def build_dag(self, sentence):
    19         dag = {}
    20         for start in range(len(sentence)):
    21             tmp = []
    22             for stop in range(start+1, len(sentence)+1):
    23                 fragment = sentence[start:stop]
    24                 num = self.word_dict.get(fragment, 0)
    25                 if num > 0:
    26                     tmp.append((stop, num))
    27             dag[start] = tmp
    28         return dag
    29 
    30     def predict(self, sentence):
    31         wordList = []
    32         Len = len(sentence)
    33         route = []
    34         dag = self.build_dag(sentence)  # {i: (stop, num)}
    35         i = 0
    36         while i < len(sentence):
    37             end = max(dag[i], key=lambda x: x[1])[0]
    38             wordList.append(sentence[i:end])
    39             i = end
    40         return wordList
    41 
    42     def test(self):
    43         cases = [
    44             "有意见分歧"
    45         ]
    46         for case in cases:
    47             result = self.predict(case)
    48             for word in result:
    49                 print(word)
    50             print('')
    51 
    52 def main():
    53     dag_segger = DAGSegger()
    54     dag_segger.load_data("words.txt")
    55     print(dag_segger.word_dict)
    56     dag_segger.test()
    57 
    58 if __name__ == '__main__':
    59     main()

    模拟词典:

    有 见 分歧 有意 有 有 分 分 见分 见分 分歧 意见 分歧 分歧 见 有意 有 意见 见 有意

    从词典中统计出词的频率。这个算法对词典中的词频非常敏感。那么在消除歧义的过程中,比如,乒乓球拍卖完了,有很多路径,很显然,在中文词典中,乒乓球的频率大于乒乓球拍,所以结果是:乒乓球 拍卖 完了。和IK分词的基于非交叉词元链的消除歧义效果一样。这显然是不合理的。只考虑词频,不考虑上下文不可行。2元语法模型一阶马尔科夫链效果要强于这个算法。p(拍卖|乒乓球)的值在统计语料库中会非常低,所以准确度会大于这个算法。

  • 相关阅读:
    目前流行的缺陷管理工具
    高性能WEB开发之Web性能测试工具推荐
    测试工具
    简单的事件示例代码
    C#常用代码片段备忘
    C# 获取变量或对象的栈与堆地址
    C#常用的命名规则汇总
    C# 成员默认访问权限(public、private、protected、internal)
    C# 学习路线
    简单的异常例子
  • 原文地址:https://www.cnblogs.com/txq157/p/6850097.html
Copyright © 2011-2022 走看看