亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

利用統(tǒng)計進行中文分詞與詞性分析

系統(tǒng) 2237 0

利用統(tǒng)計進行中文分詞與詞性分析 - Iveely Liu - 博客園

利用統(tǒng)計進行中文分詞與詞性分析

今天,翻出了我以前在本科階段寫的一些論文,雖然有幾篇沒有發(fā)表。突然發(fā)現(xiàn)很多還是比較實用,雖然學術價值并不是很大,于是我重新整理了下,用最簡單的方式,摘要了部分出來拼成此文,當然拼的原料都是自己的,本文適合初學者,如若轉載,請著名版權。

中文分詞已經是老調重彈的話題了,傳統(tǒng)的基于詞庫的分詞技術應該是目前最基本的分詞技術,在這里我不去深入挖掘,什么好什么不好的問題,今天我只想根據(jù)我自己的經驗,來設計和實現(xiàn)一套中文分詞與詞性分析的一套系統(tǒng),系統(tǒng)其實已經實現(xiàn)與Iveely Search Engine中。

我們采用隱馬爾可夫模型(HMM)來實現(xiàn)中文分詞和詞性分析。在使用HMM之前,我們先了解下HMM的基本內容,然后在編碼上我們才知道為什么要這樣去寫(這對讀編碼非常重要)。當然會和code對比起來。

利用學院派的講解是這樣:隱馬爾可夫模型是馬爾可夫鏈的一種,它的狀態(tài)不能直接觀察到,但能通過觀測向量序列觀察到,每個觀測向量都是通過某些概率密度分布表現(xiàn)為各種狀態(tài),每一個觀測向量是由一個具有相應概率密度分布的狀態(tài)序列產生。也許看完這個,你一頭霧水,因為在N年前,我最開始接觸HMM的時候,也是領悟了一段時間,當然如果你很熟悉HMM,直接跳過。從工程的角度:

                  
                    HMM
                  
                  
                    的五元素(學術名
                  
                  
                    )
                  
                
                  
                    統(tǒng)計中含義(
                  
                  
                    工程含義)
                  
                
                  隱含狀態(tài)S
                
                  詞有的4種隱含狀態(tài):單字成詞、詞頭、詞中、詞尾
                
                  觀察狀態(tài)O
                
                  所有語料庫中的漢字
                
                  初始狀態(tài)概率矩陣Pi
                
                  詞中各種隱含狀態(tài)的初始概率
                
                  隱含狀態(tài)轉移概率矩陣A
                
                  4種隱含狀態(tài)的轉移概率,例如:詞頭到詞尾的轉移概率,是一個4*4的矩陣
                
                  觀察狀態(tài)轉移概率矩陣B
                
                  語料庫中每一個漢字到4種隱含狀態(tài)的概率。例如:漢字“我”到詞頭的概率,到詞尾的概率。
                

第一步:統(tǒng)計HMM五種元素值

通過上圖的表,你似乎可以開始工作了,但是你知道,沒有Corpus,這件事是做不好的,所以,Corpus的選擇,是非常好的,我們選用這個Corpus,下一步工作,我們就是利用工程學統(tǒng)計出上述五個元素的。

語料庫中的形式如下:

“...廢/B除/E ?存/B在/E ?的/S ?所/B有/M制/E ?關/B系/E ?并/S ?不/S ?是/S ?共/B產/M主/M義/E ?所/S ?獨/B具/E ?的/S ?特/B征/E...”

B表示:begin(詞頭),M表示:Middle(詞中),S表示Single(單字成詞),E表示End(詞尾),我想給你這樣一個語料庫,讓你統(tǒng)計上面五個元素的值,應該不是什么問題了。當然我也會附加上主要的代碼:

            
                   private
            
            
              void
            
             Train(
            
              string
            
            
               corpus)
        {
       
            
            
              string
            
            [] states = 
            
              new
            
            
              string
            
            [] { 
            
              "
            
            
              單字成詞
            
            
              "
            
            , 
            
              "
            
            
              詞頭
            
            
              "
            
            , 
            
              "
            
            
              詞中
            
            
              "
            
            , 
            
              "
            
            
              詞尾
            
            
              "
            
            
               };
        
            
            
              //
            
            
              添加隱含狀態(tài)
            
            
              this
            
            
              .AddStates(states);
            
            
            
              string
            
            [] sentences = corpus.Split(
            
              this
            
            
              .Delimiter.ToArray(), StringSplitOptions.RemoveEmptyEntries);
            
            
            
              string
            
             lastwordType = states[
            
              0
            
            
              ];
            
            
            
              string
            
             currentWordType = 
            
              string
            
            
              .Empty;
            
            
            
              foreach
            
             (
            
              var
            
             sentence 
            
              in
            
            
               sentences)
            {
                
            
            
              char
            
            [] list =
            
               sentence.ToArray();
                
            
            
              for
            
             (
            
              int
            
             i = 
            
              0
            
            ; i < list.Length; i = i + 
            
              3
            
            
              )
                {
                    
            
            
              string
            
             word =
            
               list[i].ToString(CultureInfo.InvariantCulture);
                    
            
            
              string
            
             wordType = list[i + 
            
              2
            
            
              ].ToString(CultureInfo.InvariantCulture).ToLower();
                    
            
            
              //
            
            
              添加觀察狀態(tài)元素
            
            
              this
            
            
              .AddObserver(word);
                    
            
            
              if
            
             (wordType.Equals(
            
              "
            
            
              s
            
            
              "
            
            
              ))
                    {
                        currentWordType 
            
            = states[
            
              0
            
            
              ];
                    }
                    
            
            
              else
            
            
              if
            
             (wordType.Equals(
            
              "
            
            
              e
            
            
              "
            
            
              ))
                    {
                        currentWordType 
            
            = states[
            
              3
            
            
              ];
                    }
                    
            
            
              else
            
            
              if
            
             (wordType.Equals(
            
              "
            
            
              m
            
            
              "
            
            
              ))
                    {
                        currentWordType 
            
            = states[
            
              2
            
            
              ];
                    }
                    
            
            
              else
            
            
              if
            
             (wordType.Equals(
            
              "
            
            
              b
            
            
              "
            
            
              ))
                    {
                        currentWordType 
            
            = states[
            
              1
            
            
              ];
                    }
                    
            
            
              //
            
            
              初始狀態(tài)轉移矩陣
            
            
                    AddInitialStateProbability(currentWordType, 
            
              1
            
            
              );
                    
            
            
              //
            
            
              觀察狀態(tài)轉移矩陣
            
            
                                  AddComplexProbability(currentWordType, word);
                    
            
            
              //
            
            
              隱含狀態(tài)轉移矩陣
            
            
                    AddTransferProbability(lastwordType, currentWordType, 
            
              1
            
            
              );
                    lastwordType 
            
            =
            
               currentWordType;
                }
            }
        }
            
          

第二步:維特比最佳路徑

?維特比是什么?維特比算法是一種動態(tài)規(guī)劃算法用于尋找最有可能產生觀測事件序列的-維特比路徑-隱含狀態(tài)序列,特別是在馬爾可夫信息源上下文和隱馬爾可夫模型中。術語“維特比路徑”和“維特比算法”也被用于尋找觀察結果最有可能解釋相關的動態(tài)規(guī)劃算法。例如在統(tǒng)計句法分析中動態(tài)規(guī)劃算法可以被用于發(fā)現(xiàn)最可能的上下文無關的派生(解析)的字符串,有時被稱為“維比特分析”。

有了上面維特比的基礎知識以及統(tǒng)計完HMM的基本五種元素之后,你會很納悶,這五種元素計算出來后,意義是什么?如何利用它解決分詞問題?下面的問題,我們以一個實例來解說:用戶輸入了關鍵字“Iveely 是一款開源的搜索引擎。” 我們該如何分詞(解碼過程)?

首先,將輸入詞組分為一個Array:

                  
                    Iveely
                  
                
                  
                
                  
                
                  
                
                  
                
                  
                
                  
                
                  
                
                  
                
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    S
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    B
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    M
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                
                  
                    E
                  
                

那么分詞的作用就是,在每一個詞有不同的狀態(tài)的時候,怎么使得他們的概率最大?這就變成了一個路徑選擇問題。我們可以不利用維特比算法來解決,因為暴力方法一定是一個解決思路,但是算法效率太低,每個字有4種狀態(tài),假設10個字,就有4的10次方計算量,然后取出概率最大的那一組就是我們所求的最佳路徑。但是我們需要高效率解決這些問題,所以維特比是一種常用的方式。維比特怎么解決這個問題的呢?參考 這里 ?(我開始寫了很多,但是都不如這位兄弟專業(yè),偷個小懶啦,哈哈?^_^)

當然,我不會吝嗇的保存自己的代碼,Share 給大家:

            
              public
            
            
              int
            
            [] Decode(
            
              string
            
            [] input, 
            
              out
            
            
              double
            
            
               probability)
        {
            
            
            
              int
            
             inputLength =
            
               input.Length;
            
            
            
              int
            
             stateCount = 
            
              this
            
            
              .state.Length;
            
            
            
              int
            
            
               minState;
            
            
            
              double
            
            
               minWeight;

            
            
            
              int
            
            [,] s = 
            
              new
            
            
              int
            
            
              [stateCount,inputLength];
            
            
            
              double
            
            [,] a = 
            
              new
            
            
              double
            
            
              [stateCount,inputLength];

            
            
            
              for
            
            (
            
              int
            
             i = 
            
              0
            
            ; i < stateCount; i++
            
              )
            {
                
            
            
              object
            
             obj = complex.Table[
            
              this
            
            .state[i]][input[
            
              0
            
            
              ]];
                
            
            
              if
            
            (obj != 
            
              null
            
            
              )
                {
                    a[i, 
            
            
              0
            
            ] = (
            
              1.0
            
            *Math.Log(initialState[
            
              this
            
            .state[i]])) -
            
              
                              Math.Log(
            
            
              double
            
            
              .Parse(obj.ToString()))
                        ;
                }
            }

            
            
            
              for
            
            (
            
              int
            
             t = 
            
              1
            
            ; t < inputLength; t++
            
              )
            {
                
            
            
              for
            
            (
            
              int
            
             j = 
            
              0
            
            ; j < stateCount; j++
            
              )
                {
                    minState 
            
            = 
            
              0
            
            
              ;
                    minWeight 
            
            = a[
            
              0
            
            , t - 
            
              1
            
            ] -
            
              
                                Math.Log(
            
            
              double
            
            .Parse(
            
              this
            
            .transition.Table[
            
              this
            
            .state[
            
              0
            
            ]][
            
              this
            
            
              .state[j]].ToString()));

                    
            
            
              for
            
            (
            
              int
            
             i = 
            
              0
            
            ; i < stateCount; i++
            
              )
                    {
                        
            
            
              double
            
             weight = a[i, t - 
            
              1
            
            ] -
            
              
                                        Math.Log(
            
            
              double
            
            .Parse(
            
              this
            
            .transition.Table[
            
              this
            
            .state[i]][
            
              this
            
            
              .state[j]].ToString()));
                        
            
            
              if
            
            (weight <
            
               minWeight)
                        {
                            minState 
            
            =
            
               i;
                            minWeight 
            
            =
            
               weight;
                        }
                    }
                    
            
            
              object
            
             obj = complex.Table[
            
              this
            
            
              .state[j]][input[t]];
                    
            
            
              if
            
            (obj != 
            
              null
            
            
              )
                    {
                        a[j, t] 
            
            = minWeight - Math.Log(
            
              double
            
            
              .Parse(obj.ToString()));
                        s[j, t] 
            
            =
            
               minState;
                    }
                 
                }
            }
            minState 
            
            = 
            
              0
            
            
              ;
            minWeight 
            
            = a[
            
              0
            
            , inputLength - 
            
              1
            
            
              ];
            
            
            
              for
            
            (
            
              int
            
             i = 
            
              1
            
            ; i < stateCount; i++
            
              )
            {
                
            
            
              if
            
            (a[i, inputLength - 
            
              1
            
            ] <
            
               minWeight)
                {
                    minState 
            
            =
            
               i;
                    minWeight 
            
            = a[i, inputLength - 
            
              1
            
            
              ];
                }
            }

            
            
            
              int
            
            [] path = 
            
              new
            
            
              int
            
            
              [input.Length];
            path[inputLength 
            
            - 
            
              1
            
            ] =
            
               minState;

            
            
            
              for
            
            (
            
              int
            
             m = inputLength - 
            
              2
            
            ; m >= 
            
              0
            
            ; m--
            
              )
            {
                path[m] 
            
            = s[path[m + 
            
              1
            
            ], m + 
            
              1
            
            
              ];
            }

            probability 
            
            = Math.Exp(-
            
              minWeight);
            
            
            
              return
            
            
               path;
        }
            
          

? ? 利用維特比算法,它返回了一個路徑數(shù)組,數(shù)組是一個長度跟我們輸入的字符串的長度一樣,數(shù)組值是0-3的隱含狀態(tài),表示該次更屬于哪一個狀態(tài),通過維特比算法處理后,將詞與狀態(tài)路徑合并,我們可以得到這樣的一張表:

                  Iveely
                
                  
                    
                      S
                    
                  
                
                  
                    
                      S
                    
                  
                
                  S
                
                  S
                
                  S
                
                  S
                
                  S
                
                  S
                
                  S
                
                  S
                
                  B
                
                  B
                
                  
                    
                      B
                    
                  
                
                  B
                
                  
                    
                      B
                    
                  
                
                  B
                
                  
                    
                      B
                    
                  
                
                  B
                
                  B
                
                  B
                
                  M
                
                  M
                
                  M
                
                  M
                
                  M
                
                  M
                
                  M
                
                  
                    
                      M
                    
                  
                
                  
                    
                      M
                    
                  
                
                  M
                
                  E
                
                  E
                
                  E
                
                  
                    
                      E
                    
                  
                
                  E
                
                  
                    
                      E
                    
                  
                
                  E
                
                  E
                
                  E
                
                  
                    
                      E
                    
                  
                

我想看到上面的表,你已經知道具體的含義了,不用我多說吧?呵呵,讓我們看看程序跑完的截圖吧:

利用統(tǒng)計進行中文分詞與詞性分析

? ? 上面,講完了基本的分詞后,你一定想知道,我們怎么做中文詞性分析,在自然語言處理(NLP)中,詞性分析難度是很大的,目前據(jù)我所知, 哈工大NLP實驗室 的,感覺還挺不錯,而且是開源。好了,繼續(xù)我們的詞性分析。

第一步:分詞

幸運的是,我們上面已經做好了分詞,那么用戶給定的輸入,我們已經切分好詞了:”iveely/是/一款/開源/搜索引擎/“。

第二步:統(tǒng)計學習

對,我們再次進行統(tǒng)計學習,依然利用HMM,不過語料庫變了,我們利用1998年01月份人民日報的語料庫,大致形式如下:

"...邁向/v ?充滿/v ?希望/n ?的/u ?新/a ?世紀/n ?——/w ?一九九八年/t ?新年/t ?講話/n ?(/w ?附/v ?圖片/n ?1/m ?張/q ?)/w ..."

每一個詞的后面都有一個詞性,詞性表?查看 這里 ?

是不是感覺跟分詞的時候統(tǒng)計類似?看看下表你就知道了:

                  
                    HMM
                  
                  
                    的五元素
                  
                  
                    (
                  
                  
                    學院名
                  
                  
                    )
                  
                
                  
                    統(tǒng)計中含義
                  
                  
                    (
                  
                  
                    工程含義
                  
                  
                    )
                  
                
                  隱含狀態(tài)S
                
                  詞有的N種隱含狀態(tài):名詞、動詞、介詞…
                
                  觀察狀態(tài)O
                
                  所有語料庫中的詞語
                
                  初始狀態(tài)概率矩陣Pi
                
                  詞中各種隱含狀態(tài)的初始概率
                
                  隱含狀態(tài)轉移概率矩陣A
                
                  N種隱含狀態(tài)的轉移概率,例如:動詞到到名詞的轉移概率。
                
                  觀察狀態(tài)轉移概率矩陣B
                
                  語料庫中每一個詞語到N種隱含狀態(tài)的概率。例如:漢字“我”是名詞的概率。
                

?  我想看到這里,大家都應該很清楚了。后面利用維特比算法解碼,算出給定的路徑,然后將詞性附加給我們的詞組。

作者說: HMM并不是一種很完美的方法,只是從某種角度,它可以做分詞,可以做詞性分析,所有的code,點擊 這里 查看, 當然效果需要不斷調整和修復 。還有很多網友發(fā)郵件問我,為何IveelySE 0.4.0還沒有發(fā)布,原因是很多方面的,最重要的是準確率上不去,不忍心將效果很差的智能搜索給大家,但是在繼續(xù)整改之后,我也期待早日和大家分享。 謝謝一直以來對IveelySE支持的朋友

------------------------------------------------------------

我的郵箱: liufanping@iveely.com

我的微博: weibo.com/liufanping

世界上最快樂的事情,莫過于為理想而奮斗

利用統(tǒng)計進行中文分詞與詞性分析


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产综合精品久久久久成人影 | 国产免费一区二区三区香蕉精 | 久久66热re国产毛片基地 | 天天色天天射综合网 | 伊人久久久综在合线久久在播 | 色视频在线免费观看 | 亚洲精品日本一区二区在线 | 青青青国产在线视频 | 国产精品美女一区二区三区 | 韩国午夜剧场 | 日韩女同视频 | 中国美女牲交一级毛片 | 热久久99影院 | 日本四虎影院 | 亚洲视频免| 国内精品久久久久丫网址 | 狠狠色狠狠色综合日日32 | 欧美 日韩 国产在线 | 夜色99| 嘿咻嘿咻免费区在线观看吃奶 | 天天干天天拍天天射 | 日本高清影院 | 老子午夜伦不卡影院 | 国产一区 在线视频 | 婷婷亚洲综合五月天在线 | 欧美日韩国产三级 | 国产成人99精品免费视频麻豆 | 欧美激情区 | 日韩性网 | 欧美亚洲国产精品第一页 | 在线免费精品视频 | 红色一级毛片 | 成人网欧美亚洲影视图片 | 99热精品6 | 五月天婷婷在线免费观看 | 中国一级特黄真人毛片免 | 成人综合网址 | 久操福利 | 亚洲va国产日韩欧美精品色婷婷 | 精品日韩一区二区 | 日韩国产精品欧美一区二区 |