天天看點

OpenNLP:駕馭文本,分詞那些事

opennlp是為何物?

官方文檔:apache的opennlp庫是自然語言文本的處理基于機器學習的工具包。它支援最常見的nlp任務,如斷詞,句子切分,部分詞性标注,命名實體提取,分塊,解析和指代消解。這些任務通常需要建立更先進的文字處理服務。opennlp還包括最大熵和基于感覺機器學習。該opennlp項目的目标是創造上述任務的成熟工具包。一個附加的目的是提供一種大量預模組化型為各種語言,以及這些模型衍生自注釋文本資源。

開發狀态: active

使用:其支援windows、linux等多個作業系統,本文主要介紹windows下:

1 指令行界面(cli):opennlp腳本使用java_cmd和java_home變量,以确定哪些指令用來執行java虛拟機。opennlp腳本使用opennlp_home變量來确定opennlp的二進制分發的位置。建議這個變量指向目前opennlp版本和更新path變量的二進制分發版包括$opennlp_home/bin or %opennlp_home%\bin。這樣的配置允許友善調用opennlp。下面的例子假設這個配置已經完成。使用如下:當工具被執行這種方式,模型是裝載和工具正在等待來自标準輸入的輸入。此輸入處理,并列印到标準輸出。

1

<code>$ opennlp toolname lang-model-name.bin &lt; input.txt &gt; output.txt</code>

2 java在控制台:進行其api的調用,以下代碼示範均采用此法。

OpenNLP:駕馭文本,分詞那些事

解壓檔案:(如:savepath\apache-opennlp-1.5.3\lib)将lib下檔案拷貝項目中

OpenNLP:駕馭文本,分詞那些事
OpenNLP:駕馭文本,分詞那些事
OpenNLP:駕馭文本,分詞那些事

然後去建立java程式做相應處理,諸如:分詞、詞性标注等。

3 示例:至此完成java配置,然後相對 "the quick, red fox jumped over the lazy, brown dogs." 一條句子進行分詞,正常方法采用空格分詞代碼如下:

2

3

4

5

6

7

8

9

<code>//英文切詞:空格或者換行符</code>

<code>public</code> <code>static</code> <code>void</code> <code>ensplit(string str)</code>

<code>{</code>

<code>    </code><code>string[] result=str.split(</code><code>"\\s+"</code><code>);</code>

<code>    </code><code>for</code><code>(string s:result){</code>

<code>        </code><code>system.</code><code>out</code><code>.println(s+</code><code>" "</code><code>);</code>

<code>    </code><code>}</code>

<code>    </code><code>system.</code><code>out</code><code>.println();</code>

<code>}</code>

 分詞結果:

OpenNLP:駕馭文本,分詞那些事

随着需求的改變,假如我想把标點也分開。實際這也是有意義的,可以通過标點确定句子的邊界。下面opennlp将采用其方式完成,由此引入本文正題。

功能介紹:

句子檢測器是用于檢測句子邊界。

句子探測器傳回一個字元串數組。

api:句子探測器還提供了一個api來培養一個新的句子檢測模型。三個基本步驟是必要的訓練它:

應用程式必須打開一個示例資料流

調用sentencedetectorme.t​​rain方法

儲存sentencemodel到檔案或直接使用它

代碼實作:

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<code>/**</code>

<code> </code><code>* 1.句子探測器:sentence detector</code>

<code> </code><code>* @deprecated sentence detector is for detecting sentence boundaries. given the following paragraph:</code>

<code> </code><code>* hi. how are you? this is mike.</code>

<code> </code><code>* 如:hi. how are you? this is mike.将傳回如下:</code>

<code> </code><code>* hi. how are you?</code>

<code> </code><code>* this is mike.</code>

<code> </code><code>* @throws ioexception</code>

<code> </code><code>* @throws invalidformatexception</code>

<code> </code><code>*/</code>

<code>public</code> <code>static</code> <code>void</code> <code>sentencedetector(string str) throws invalidformatexception, ioexception</code>

<code>    </code><code>//always start with a model, a model is learned from training data</code>

<code>    </code><code>inputstream </code><code>is</code> <code>= </code><code>new</code> <code>fileinputstream(</code><code>"./nlpbin/en-sent.bin"</code><code>);</code>

<code>    </code><code>sentencemodel model = </code><code>new</code> <code>sentencemodel(</code><code>is</code><code>);</code>

<code>    </code><code>sentencedetectorme sdetector = </code><code>new</code> <code>sentencedetectorme(model);</code>

<code> </code> 

<code>    </code><code>string sentences[] = sdetector.sentdetect(str);</code>

<code>    </code><code>system.</code><code>out</code><code>.println(sentences[0]);</code>

<code>    </code><code>system.</code><code>out</code><code>.println(sentences[1]);</code>

<code>    </code><code>is</code><code>.close();</code>

<code>    </code><code>system.</code><code>out</code><code>.println(</code><code>"---------------1------------"</code><code>);</code>

運作結果:

OpenNLP:駕馭文本,分詞那些事

功能介紹:該opennlp斷詞段輸入字元序列為标記。常是這是由空格分隔的單詞,但也有例外。例如,“isn't”被分割為“is”與“n't",因為它是aa簡要格式”isn't“我們的句子分為以下标記:符号通常是詞語,标點符号,數字等opennlp提供多種标記生成器的實作:

空白标記生成器 - 一個空白标記生成器,非空白序列被确定為符号

簡單的标記生成器 - 一個字元類标記生成器,同樣的字元類的序列标記

可學習标記生成器 - 一個最大熵标記生成器,檢測基于機率模型符号邊界

api:的斷詞可以被內建到由定義的api的應用程式。該whitespacetokenizer的共享執行個體可以從靜态字段whitespacetokenizer.instance進行檢索。該simpletokenizer的共享執行個體可以在從simpletokenizer.instance相同的方式進行檢索。執行個體化tokenizerme(中可以學習标記生成器)符号模型必須先建立。

<code> </code><code>* 2.标記生成器:tokenizer</code>

<code> </code><code>* @deprecated tokens are usually words which are separated by space, but there are exceptions.  for example, "isn't" gets split into "is" and "n't, since it is a a brief format of "is not". our sentence is separated into the following tokens:</code>

<code> </code><code>* @param str</code>

<code>public</code> <code>static</code> <code>void</code> <code>tokenize(string str) throws invalidformatexception, ioexception {</code>

<code>    </code><code>inputstream </code><code>is</code> <code>= </code><code>new</code> <code>fileinputstream(</code><code>"./nlpbin/en-token.bin"</code><code>);</code>

<code>    </code><code>tokenizermodel model = </code><code>new</code> <code>tokenizermodel(</code><code>is</code><code>);</code>

<code>    </code><code>tokenizer tokenizer = </code><code>new</code> <code>tokenizerme(model);</code>

<code>    </code><code>string tokens[] = tokenizer.tokenize(str);</code>

<code>    </code><code>for</code> <code>(string a : tokens)</code>

<code>        </code><code>system.</code><code>out</code><code>.println(a);</code>

<code>    </code><code>system.</code><code>out</code><code>.println(</code><code>"--------------2-------------"</code><code>);</code>

OpenNLP:駕馭文本,分詞那些事

功能介紹:名稱查找器可檢測文本命名實體和數字。為了能夠檢測實體名稱搜尋需要的模型。該模型是依賴于語言和實體類型這是訓練。所述opennlp項目提供了許多這些各種免費提供的語料庫訓練有素預訓練名取景模式。他們可以在我們的模型下載下傳頁進行下載下傳。要查找原始文本的文本必須分割成符号和句子的名字。較長的描述中的一句話探測器和标記生成器教程中給出。其重要的,對于訓練資料和輸入的文本的标記化是相同的。根據不同的模型可以查找人名、地名等實體名。

api:從應用程式中訓練名字發現者的建議使用教育訓練api而不是指令行工具。三個基本步驟是必要的訓練它:

調用namefinderme.t​​rain方法

儲存tokennamefindermodel到檔案或資料庫

<code> </code><code>* 3.名稱搜尋:name finder</code>

<code> </code><code>* @deprecated by its name, name finder just finds names in the context. check out the following example to see what name finder can do. it accepts an array of strings, and find the names inside.</code>

<code>public</code> <code>static</code> <code>void</code> <code>findname() throws ioexception {</code>

<code>    </code><code>inputstream </code><code>is</code> <code>= </code><code>new</code> <code>fileinputstream(</code><code>"./nlpbin/en-ner-person.bin"</code><code>);</code>

<code>    </code><code>tokennamefindermodel model = </code><code>new</code> <code>tokennamefindermodel(</code><code>is</code><code>);</code>

<code>    </code><code>namefinderme namefinder = </code><code>new</code> <code>namefinderme(model);</code>

<code>    </code><code>string[] sentence = </code><code>new</code> <code>string[]{</code>

<code>            </code><code>"mike"</code><code>,</code>

<code>            </code><code>"tom"</code><code>,</code>

<code>            </code><code>"smith"</code><code>,</code>

<code>            </code><code>"is"</code><code>,</code>

<code>            </code><code>"a"</code><code>,</code>

<code>            </code><code>"good"</code><code>,</code>

<code>            </code><code>"person"</code>

<code>            </code><code>};</code>

<code>    </code><code>span namespans[] = namefinder.find(sentence);</code>

<code>    </code><code>for</code><code>(span s: namespans)</code>

<code>        </code><code>system.</code><code>out</code><code>.println(s.tostring());  </code>

<code>    </code><code>system.</code><code>out</code><code>.println(</code><code>"--------------3-------------"</code><code>);</code>

OpenNLP:駕馭文本,分詞那些事

功能介紹:語音标記器的部分标記符号與基于符号本身和符号的上下文中它們的相應字類型。符号可能取決于符号和上下文使用多個pos标簽。該opennlp pos标注器使用的機率模型來預測正确的pos标記出了标簽組。為了限制可能的标記的符号标記字典可以使用這增加了捉人者的标記和運作時性能。

api:部分的詞類打标簽訓練api支援一個新的pos模式的教育訓練。三個基本步驟是必要的訓練它:

調用postagger.train方法

儲存posmodel到檔案或資料庫

代碼實作1:

<code> </code><code>* 4.pos标注器:pos tagger</code>

<code> </code><code>* @deprecated hi._nnp how_wrb are_vbp you?_jj this_dt is_vbz mike._nnp</code>

<code>public</code> <code>static</code> <code>void</code> <code>postag(string str) throws ioexception {</code>

<code>    </code><code>posmodel model = </code><code>new</code> <code>posmodelloader().load(</code><code>new</code> <code>file(</code><code>"./nlpbin/en-pos-maxent.bin"</code><code>));</code>

<code>    </code><code>performancemonitor perfmon = </code><code>new</code> <code>performancemonitor(system.err, </code><code>"sent"</code><code>);</code><code>//顯示加載時間</code>

<code>    </code><code>postaggerme tagger = </code><code>new</code> <code>postaggerme(model);</code>

<code>    </code><code>objectstream&lt;string&gt; linestream = </code><code>new</code> <code>plaintextbylinestream(</code><code>new</code> <code>stringreader(str));</code>

<code>    </code><code>perfmon.start();</code>

<code>    </code><code>string line;</code>

<code>    </code><code>while</code> <code>((line = linestream.read()) != </code><code>null</code><code>) {</code>

<code>        </code><code>string whitespacetokenizerline[] = whitespacetokenizer.instance.tokenize(line);</code>

<code>        </code><code>string[] tags = tagger.tag(whitespacetokenizerline);</code>

<code>        </code><code>possample sample = </code><code>new</code> <code>possample(whitespacetokenizerline, tags);</code>

<code>        </code><code>system.</code><code>out</code><code>.println(sample.tostring());</code>

<code>        </code><code>perfmon.incrementcounter();</code>

<code>    </code><code>perfmon.stopandprintfinalresult();</code>

<code>    </code><code>system.</code><code>out</code><code>.println(</code><code>"--------------4-------------"</code><code>);</code>

運作結果1:

OpenNLP:駕馭文本,分詞那些事

代碼實作2:

25

<code> </code><code>* opennlp詞性标注工具的例子:最大熵詞性标注器pos-maxent</code>

<code> </code><code>* jj形容詞、jjs形容詞最進階、jjr形容詞比較級</code>

<code> </code><code>* rb副詞、rbr副詞最進階、rbs副詞比較級</code>

<code> </code><code>* dt限定詞</code>

<code> </code><code>* nn名稱、nns名稱複試、nnp專有名詞、nnps專有名詞複數:</code>

<code> </code><code>* prp:人稱代詞、prp$:物主代詞</code>

<code> </code><code>* vb動詞不定式、vbd過去式、vbn過去分詞、vbz現在人稱第三人稱單數、vbp現在非第三人稱、vbg動名詞或現在分詞</code>

<code>public</code> <code>static</code> <code>void</code> <code>posmaxent(string str) throws invalidformatexception, ioexception</code>

<code>    </code><code>//給出詞性模型所在的路徑</code>

<code>    </code><code>file posmodefile=</code><code>new</code> <code>file(</code><code>"./nlpbin/en-pos-maxent.bin"</code><code>);</code>

<code>    </code><code>fileinputstream posmodestream=</code><code>new</code> <code>fileinputstream(posmodefile);</code>

<code>    </code><code>posmodel model=</code><code>new</code> <code>posmodel(posmodestream);</code>

<code>    </code><code>//将句子切分成詞</code>

<code>    </code><code>postaggerme tagger=</code><code>new</code> <code>postaggerme(model);</code>

<code>    </code><code>string[] words=simpletokenizer.instance.tokenize(str);</code>

<code>    </code><code>//将切好的詞的句子傳遞給标注器</code>

<code>    </code><code>string[] result=tagger.tag(words);</code>

<code>    </code><code>for</code> <code>(</code><code>int</code> <code>i=0; i&lt;words.length;i++){</code>

<code>        </code><code>system.</code><code>out</code><code>.print(words[i]+</code><code>"/"</code><code>+result[i]+</code><code>" "</code><code>);</code>

  運作結果2:

OpenNLP:駕馭文本,分詞那些事

功能介紹:文本分塊由除以單詞句法相關部分,如名詞基,動詞基的文字,但沒有指定其内部結構,也沒有其在主句作用。

api:該概括化提供了一個api來培養新的概括化的模式。下面的示例代碼示範了如何做到這一點:

26

27

28

29

30

31

32

33

34

35

<code> </code><code>* 5.序列标注:chunker</code>

<code> </code><code>* @deprecated 通過使用标記生成器生成的tokens分為一個句子劃分為一組塊。what chunker does is to partition a sentence to a set of chunks by using the tokens generated by tokenizer.</code>

<code>public</code> <code>static</code> <code>void</code> <code>chunk(string str) throws ioexception {</code>

<code>    </code><code>//performancemonitor perfmon = new performancemonitor(system.err, "sent");</code>

<code>    </code><code>//perfmon.start();</code>

<code>    </code><code>string whitespacetokenizerline[] = </code><code>null</code><code>;</code>

<code>    </code><code>string[] tags = </code><code>null</code><code>;</code>

<code>        </code><code>whitespacetokenizerline = whitespacetokenizer.instance.tokenize(line);</code>

<code>        </code><code>tags = tagger.tag(whitespacetokenizerline);</code>

<code>            </code><code>//perfmon.incrementcounter();</code>

<code>    </code><code>//perfmon.stopandprintfinalresult();</code>

<code>    </code> 

<code>    </code><code>// chunker</code>

<code>    </code><code>inputstream </code><code>is</code> <code>= </code><code>new</code> <code>fileinputstream(</code><code>"./nlpbin/en-chunker.bin"</code><code>);</code>

<code>    </code><code>chunkermodel cmodel = </code><code>new</code> <code>chunkermodel(</code><code>is</code><code>);</code>

<code>    </code><code>chunkerme chunkerme = </code><code>new</code> <code>chunkerme(cmodel);</code>

<code>    </code><code>string result[] = chunkerme.chunk(whitespacetokenizerline, tags);</code>

<code>    </code><code>for</code> <code>(string s : result)</code>

<code>        </code><code>system.</code><code>out</code><code>.println(s);</code>

<code>    </code><code>span[] span = chunkerme.chunkasspans(whitespacetokenizerline, tags);</code>

<code>    </code><code>for</code> <code>(span s : span)</code>

<code>        </code><code>system.</code><code>out</code><code>.println(s.tostring());</code>

<code>    </code><code>system.</code><code>out</code><code>.println(</code><code>"--------------5-------------"</code><code>);</code>

OpenNLP:駕馭文本,分詞那些事

功能介紹:嘗試解析器最簡單的方法是在指令行工具。該工具僅用于示範和測試。請從我們網站上的英文分塊解析器模型,并用以下指令啟動解析工具。

36

37

<code> </code><code>* 6.分析器: parser</code>

<code> </code><code>* @deprecated given this sentence: "programcreek is a very huge and useful website.", parser can return the following:</code>

<code> </code><code>* (top (s (np (nn programcreek) ) (vp (vbz is) (np (dt a) (adjp (rb very) (jj huge) (cc and) (jj useful) ) ) ) (. website.) ) )</code>

<code> </code><code>* (top</code>

<code> </code><code>*     (s</code>

<code> </code><code>*        (np</code>

<code> </code><code>*           (nn programcreek)</code>

<code> </code><code>*        )</code>

<code> </code><code>*        (vp</code>

<code> </code><code>*           (vbz is)</code>

<code> </code><code>*           (np</code>

<code> </code><code>*              (dt a)</code>

<code> </code><code>*              (adjp</code>

<code> </code><code>*                   (rb very)</code>

<code> </code><code>*                   (jj huge)</code>

<code> </code><code>*                   (cc and)</code>

<code> </code><code>*                   (jj userful)</code>

<code> </code><code>*              )</code>

<code> </code><code>*           )</code>

<code> </code><code>*        (. website.)</code>

<code> </code><code>*     )</code>

<code> </code><code>* )</code>

<code>public</code> <code>static</code> <code>void</code> <code>parse() throws invalidformatexception, ioexception {</code>

<code>    </code><code>inputstream </code><code>is</code> <code>= </code><code>new</code> <code>fileinputstream(</code><code>"./nlpbin/en-parser-chunking.bin"</code><code>);</code>

<code>    </code><code>parsermodel model = </code><code>new</code> <code>parsermodel(</code><code>is</code><code>);</code>

<code>    </code><code>parser parser = parserfactory.create(model);</code>

<code>    </code><code>string sentence = </code><code>"programcreek is a very huge and useful website."</code><code>;</code>

<code>    </code><code>opennlp.tools.parser.parse topparses[] = parsertool.parseline(sentence, parser, 1);</code>

<code>    </code><code>for</code> <code>(opennlp.tools.parser.parse p : topparses)</code>

<code>        </code><code>p.show();</code>

OpenNLP:駕馭文本,分詞那些事