中国の単語のpythonを達成するために、ビタビアルゴリズム

この記事はより転載:  https://zhuanlan.zhihu.com/p/58163299 

私は最近、NLPは、NLP私たちの最初のステップは、言葉を信用していることをすべて知っているが、言葉≠自然言語処理と信じて学びました。セグメンテーションツールと方法は、インターネットをたくさん使用しています。単語の性質を探求とともに、その吃音ワードコアである私は共有したいと思います。

(1)文の場合には単語にすべての可能な文字を生成する、接頭語に対して辞書図効率的なスキャンをベース非循環有向グラフを構成

DAG(有向非巡回グラフ)とは何ですか?

例えば、文章DAG {0に対応する "北京をプレイする" [0]、1:[2,4]、2 [2] 3:[3,4]、4 [4]、 5:[5]}。DAG {0:[0]} 0即ち、dictののワード(各ワードの頻度を記録する辞書データベース)内の「OUT」、〜0であるワードに対応する位置を表すが用語です。DAG {1:[2,4]}、開始位置から発現される、2,4位置であるワード1〜4の2,1の1,1のすなわち「北」「北京「」北京大学「これは三つの言葉がDictのに表示されています。「再生する北京大学に、」文DAGは、すべての後に、比較的短い一目アウトすることができ、今別の文は、どのようにそれをDAG取得する「意見の相違があることが多い」、来ますか?この時間は、それがコードを達成する必要があります。

辞書= { "しばしば" 0.1 "による":0.05、 "はい":0.1 "ノーマル":0.001、 "持っています":0.1 "差別":0.001、 "意見":0.2 "差": 0.2、 "見る" 0.05 "を意味する" 0.05 "を参照の違い" 0.05 "点":0.1} 
DEF DAG(文):
        有向非巡回DAGを構成するために使用されるDAG = {} #DAG空の辞書を、図
        N = lenは(文)
        の範囲内のK用の(N):
            tmplist = []   
            I = K 
            フラグ・文= [K] 
            しばらくI <N:
                IF dictののFRAGにおいて:
                    tmplist.append(I)   
                。I + = 1        
                FRAG =文[K:I + 1]   
            IFないのtmplist:
                tmplist。APPEND(k)は
            DAG [K] = tmplist 
        リターンDAGの
印刷(DAG() "はしばしば同意しません")

 出力:

{0:[0、1]、1 [1]、2:[2,4]、3 [3、4]、4:[4,6]、5 [5、6]、6:[ 6]}

各単語辞書の発生確率は、すべての可能な経路(ワード)、次の図を得ることができます。

                            図に示すDAG

ロングワード表示されるように、単語が表示されない、それはコードを実行することにより、単一の単語として分離することはできません「しばしば」、私たちは「多くの場合、意見の相違を持っている」を取得することができDAGとして、分割することができます

{0:[0、1]、1 [1]、2:[2,4]、3 [3、4]、4:[4,6]、5 [5、6]、6:[ 6]}

簡単かつDAGの直感的な理解、我々はプロセスのパスを探しに問題があり、それは私が道に歩いて頂上赤い線を取ったような、あなたが得ることができ、最初から最後まで、図に示すの上にある[常に|持っている|コメント|分割]ワードケースそのスコアは、それらが= 0.6、S = 0.1 + 0.1 + 0.2 + 0.2のパス、Iは、他の経路を取るのと同じ方法を獲得するために加算値の各ステップの確率【分割|しばしば| |コメントを有することによって]する場合S = 0.05 + .0.001 + 0.1 + 0.2 = 0.351。これは、DAGの文を構築するためのコードを通して私たちの最初のステップです。

(2)単語頻度の最大値の組み合わせに基づいてセグメントを見つけるために、最大確率経路を見つけるための動的プログラミングを使用します。

最初のステップでは、DAGを取得し、あなたはまた、各パスのスコアSを得ることができ、私たちは言葉状況を探している状況の確率の最大値である最大スコアを、見つけます。すべてのパスが通過する場合は、各パスを検索し、各Sを見つけ、最大のSを削除し、もちろん、あなたは私たちが望む結果を得るが、より多くのブルートフォースすることができます。我々は、動的なプログラミングのアイデアを使用しようとすることができ、ビタビアルゴリズムを直接地図上、

注文ソリューションビタビ・アルゴリズム

给每个节点编号1~8,开始到结束,f(a)代表该节点的所有得分值,每一步单个的箭头都有其对应的概率值,c(a~b)代表的是a节点到b节点的值,如c(1~3)是“经常”的概率值,为什么有的节点如f(6)有三个值?那是因为6这个节点有三个箭头指向它,也就是说有多少个箭头指向该节点,该节点就有多少个得分值,如分f(3)有2个值、f(4)有一个值......。按1~8的顺序,计算出每个节点的所有得分值,计算后面节点的时候要用到前面节点得分值都取(max)最大的,以保证最后计算到f(8)时是全局的最大值,例如计算f(4)中f(3)取的就是0.1。算到最后,我们知道f(8)=f(6) +c(6~8) =0.4+0.2=0.6 (max),接着把f(6)展开,f(8)=f(4) +c(4~6) +c(6~8) ,同理,把所有的f()换成c(),f(8)=c(1~3) +c(3~4) +c(4~6) +c(6~8) 。直到等式右边没有f(),c(1~3)、c(3~4)、c(4~6)、c(6~8)分别代表啥各位看图去吧。

回到开始,假如用蛮力一个一个列出所有路径,不累死也得列的头晕,用动态规划的思想可以把一个大问题拆分到每一步的小问题,下一步的小问题只需要在之前的小问题上再进一步,动态规划的思想就像是小问题站巨人肩膀上,然后大问题莫名其妙就解决了。刚说的是从开始到结束的顺序解法,要是从8节点到1节点逆序解法怎么解?

维特比算法的逆序解法

发现没,最后最大都是0.6=f(1)=c(1~3) +c(3~4) +c(4~6) +c(6~8),而且直接都是看出来了,再一次说明了最大的路径就是这条路径。说了这么多,上代码

sentence ="经常有意见分歧"
N=len(sentence)
route={}
route[N] = (0, 0)
DAG={0: [0, 1], 1: [1], 2: [2, 4], 3: [3, 4], 4: [4, 6], 5: [5, 6], 6: [6]}
for idx in range(N - 1, -1, -1):
    distance = (((Dict.get(sentence[idx:x + 1]) or 0) + route[x + 1][0], x) for x in DAG[idx])
    route[idx] = max(distance)                    
            # 列表推倒求最大概率对数路径
            # route[idx] = max([ (概率值,词语末字位置) for x in DAG[idx] ])
            # 以idx:(概率最大值,词语末字位置)键值对形式保存在route中)
            # route[x+1][0] 表示 词路径[x+1,N-1]的最大概率值,
            # [x+1][0]即表示取句子x+1位置对应元组(概率对数,词语末字位置)的概率对数
print(route) 

输出结果:

{7: (0, 0), 6: (0.001, 6), 5: (0.2, 6), 4: (0.25, 4), 3: (0.4, 4), 2: (0.5, 2), 1: (0.501, 1), 0: (0.6, 1)}

这是一个自底向上的动态规划(逆序的解法),从sentence的最后一个字开始倒序遍历每个分词方式的得分。然后将得分最高的情况以(概率得分值,词语最后一个字的位置)这样的tuple保存在route中。看route的0: (0.6, 1)中的0.6,不就是我们求到的f(1)的max, 1: (0.501, 1)中的0.501不就是f(2)......后面大家对着看图找规律吧。最后小操作一波,就可以把我们要的分词结果打印出来了,结果和手推的是一样的c(1~3) +c(3~4) +c(4~6) +c(6~8)。

 

x = 0
segs = []
while x < N:
    y = route[x][1] + 1
    word = sentence[x:y]
    segs.append(word)
    x = y
print(segs)
#输出结果:['经常', '有', '意见', '分歧']

 

上面只是一些核心的思路,好多地方可以继续优化的,比如把概率值转换成-log(概率值),目的是为了防止下溢问题,只是我举例的概率值比较大,如果是一个超大的Dict,为了保证所有词的概率之和约等于1,那每个词对应的概率值会特别小。

(3)中文分词以后得攻克的难点

1、分词的规范,词的定义还不明确,没有一个公认的、权威的标准。

2、歧义词的切分。这也从侧面证实了中华文化博大精深。

3、未登录的新词。就是咱们的Dict里没有的词,对于3这个比2对分词的影响大多了,目前结巴分词对此采取的方法是:基于汉字成词能力的HMM模型,使用维特比算法。

参考:

1、贪心学院nlp

2、自然语言处理理论与实战 唐聃

3、jieba分词源码解读二 

 

 

おすすめ

転載: www.cnblogs.com/carlber/p/12152177.html