生活随笔
收集整理的這篇文章主要介紹了
(转)OpenNLP进行中文命名实体识别(下:载入模型识别实体)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節介紹了使用OpenNLP訓練命名實體識別模型的方法,并將模型寫到磁盤上形成二進制bin文件,這一節就是將模型從磁盤上載入,然后進行命名實體識別。依然是先上代碼:
?
[java]?view plain
?copy ? import?java.io.File;??import?java.util.HashMap;??import?java.util.IdentityHashMap;??import?java.util.Map;??import?java.util.Map.Entry;????import?opennlp.tools.cmdline.namefind.TokenNameFinderModelLoader;??import?opennlp.tools.namefind.NameFinderME;??import?opennlp.tools.tokenize.SimpleTokenizer;??import?opennlp.tools.tokenize.Tokenizer;??import?opennlp.tools.util.Span;????public?class?NameEntityFindTester?{????????????private?double?probThreshold?=?0.6;????????private?String?modelPath;??????private?String?testFileDirPath;????????public?NameEntityFindTester()?{??????????super();??????????????}????????public?NameEntityFindTester(String?modelPath,?String?testFileDirPath)?{??????????super();??????????this.modelPath?=?modelPath;??????????this.testFileDirPath?=?testFileDirPath;??????}????????public?NameEntityFindTester(double?probThreshold,?String?modelPath,??????????????String?testFileDirPath)?{??????????super();??????????this.probThreshold?=?probThreshold;??????????this.modelPath?=?modelPath;??????????this.testFileDirPath?=?testFileDirPath;??????}????????????public?NameFinderME?prodNameFinder()?{??????????NameFinderME?finder?=?new?NameFinderME(??????????????????new?TokenNameFinderModelLoader().load(new?File(modelPath)));????????????return?finder;??????}????????????public?Map<String,?String>?cptBasicNameProb(NameFinderME?finder)??????????????throws?Exception?{??????????Map<String,?String>?basicNameProbResMap?=?new?IdentityHashMap<String,?String>();??????????String?testContent?=?NameEntityTextFactory.loadFileTextDir(this??????????????????.getTestFileDirPath());????????????????????Tokenizer?tokenizer?=?SimpleTokenizer.INSTANCE;??????????????????String[]?tokens?=?tokenizer.tokenize(testContent);??????????Span[]?names?=?finder.find(tokens);??????????double[]?nameSpanProbs?=?finder.probs(names);????????????System.out.println("tokens?size:?"?+?tokens.length);??????????System.out.println("names?size:?"?+?names.length);??????????System.out.println("name_span_probs?size:?"?+?nameSpanProbs.length);????????????for?(int?i?=?0;?i?<?names.length;?i++)?{??????????????String?testToken?=?"";??????????????for?(int?j?=?names[i].getStart();?j?<=?names[i].getEnd()?-?1;?j++)?{??????????????????testToken?+=?tokens[j];??????????????}??????????????String?testRes?=?names[i].getType()?+?":"??????????????????????+?Double.toString(nameSpanProbs[i]);????????????????????????????System.out.println("find?name:?\""?+?testToken?+?"\"?has?res:?"??????????????????????+?testRes);????????????????basicNameProbResMap.put(testToken,?testRes);??????????}????????????return?basicNameProbResMap;??????}????????????public?Map<String,?String>?filterNameProbRes(??????????????Map<String,?String>?basicNameProbResMap)?{??????????Map<String,?String>?filttedNameProbResMap?=?new?HashMap<String,?String>();??????????for?(Entry<String,?String>?entry?:?basicNameProbResMap.entrySet())?{??????????????String?token?=?entry.getKey();??????????????String?res?=?basicNameProbResMap.get(token);????????????????if?(Double.parseDouble(res.split(":")[1])?>=?this??????????????????????.getProbThreshold())?{??????????????????filttedNameProbResMap.put(token,?res);??????????????}??????????}????????????return?filttedNameProbResMap;??????}????????????public?Map<String,?String>?execNameFindTester()?{??????????try?{??????????????NameFinderME?finder?=?this.prodNameFinder();??????????????Map<String,?String>?basicNameProbResMap?=?this??????????????????????.cptBasicNameProb(finder);??????????????Map<String,?String>?nameProbResMap?=?this??????????????????????.filterNameProbRes(basicNameProbResMap);????????????????return?nameProbResMap;??????????}?catch?(Exception?e)?{??????????????????????????e.printStackTrace();????????????????return?null;??????????}??????}??}?? 大家依然可以從詳細的注釋上獲得很多的信息,設定的參數只有命名實體概率過濾的閾值,這個是可有可無的一個值,因為OpenNLP會自動過濾一波,但是如果有更高的要求,可以自己設定一個,我默認設定成0.6。然后再簡單介紹幾個重要的方法:1.prodNameFinder()是載入磁盤上的模型,直接傳入模型的磁盤地址;2.cptBasicNameProb()是進行命名實體識別的核心方法,結果映射Map選用IdentityHashMap,因為考慮一個實體有可能被定為多個類別的情況,首先制作一個內嵌的基礎分詞器,其實這個分詞器沒有意義,是針對英文的,這就是我們為什么一開始要講中文分詞結果中間隔上空格重新寫入文本的原因,基礎分詞器將文本內容按空格分開,放入一個String數組中,對finder的find()方法傳入這個數組,就得到了命名實體識別的結果,用finder的prob()方法可以得到識別結果的概率。這時得到的命名實體結果并不是直接的詞,而是一個二維數組,每一行代表識別出來的一個命名實體,該行的每一列存儲命名實體對應的詞元素在之前傳入的String數組中的下標,因為懂命名實體識別的人都知道,命名實體也可以是多個詞組成的詞組,不只是詞。返回的Map以這樣的形式存放結果:
?
?
[html]?view plain
?copy ? <Name,?Type:Probility>?? key是實體,后面是所屬的實體類別以及概率值;3.filterNameProbRes()方法傳入剛才得到的Map結果集,返回過濾后的新Map結果集。
隨便用了一些很少的關于電子詐騙的語料進行測試,最終識別出來的結果是這個樣子的,可以看到,識別出了1個person和10個action,基本上還都有那么點意思,還有person的訓練詞庫本身詞量就很少,導致這個結果。
同樣,源代碼開源在:https://github.com/Ailab403/ailab-mltk4j,test包里面對應有完整的調用demo,以及file文件夾里面的測試語料和已經訓練好的模型。
轉載于:https://www.cnblogs.com/mansiisnam/p/5360783.html
總結
以上是生活随笔為你收集整理的(转)OpenNLP进行中文命名实体识别(下:载入模型识别实体)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。