標籤:analysis oar lag with exe system 語義理解 主題 架構
Python自然語言處理工具小結
白寧超
2016年11月21日21:45:26
1 Python 的幾個自然語言處理工具
- NLTK:NLTK 在用 Python 處理自然語言的工具中處於領先的地位。它提供了 WordNet 這種方便處理詞彙資源的借口,還有分類、分詞、除莖、標註、文法分析、語義推理等類庫。
- Pattern:Pattern 的自然語言處理工具有詞性標註工具(Part-Of-Speech Tagger),N元搜尋(n-gram search),情感分析(sentiment analysis),WordNet。支援機器學習的向量空間模型,聚類,向量機。
TextBlob:TextBlob 是一個處理文本資料的 Python 庫。提供了一些簡單的api解決一些自然語言處理的任務,例如詞性標註、名詞短語抽取、情感分析、分類、翻譯等等。
- Gensim:Gensim 提供了對大型語料庫的主題建模、檔案索引、相似性檢索的功能。它可以處理大於RAM記憶體的資料。作者說它是“實現無幹預從純文字語義建模的最強大、最高效、最無障礙的軟體。
- PyNLPI:它的全稱是:Python自然語言處理庫(Python Natural Language Processing Library,音發作: pineapple) 這是一個各種自然語言處理任務的集合,PyNLPI可以用來處理N元搜尋,計算頻率表和分布,建立語言模型。他還可以處理向優先隊列這種更加複雜的資料結構,或者像 Beam 搜尋這種更加複雜的演算法。
- spaCy:這是一個商業的開源軟體。結合Python和Cython,它的自然語言處理能力達到了工業強度。是速度最快,領域內最先進的自然語言處理工具。
- Polyglot:Polyglot 支援對海量文本和多語言的處理。它支援對165種語言的分詞,對196中語言的辨識,40種語言的專有名詞識別,16種語言的詞性標註,136種語言的情感分析,137種語言的嵌入,135種語言的形態分析,以及69中語言的翻譯。
- MontyLingua:MontyLingua 是一個自由的、訓練有素的、端到端的英文處理工具。輸入原始英文文本到 MontyLingua ,就會得到這段文本的語義解釋。適合用來進行資訊檢索和提取,問題處理,回答問題等任務。從英文文本中,它能提取出主動賓元組,形容詞、名詞和動詞短語,人名、地名、事件,日期和時間,等語義資訊。
- BLLIP Parser:BLLIP Parser(也叫做Charniak-Johnson parser)是一個整合了產產生分分析和最大熵排序的統計自然語言工具。包括 命令列 和 python介面 。
- Quepy:Quepy是一個Python架構,提供將自然語言轉換成為資料庫查詢語言。可以輕鬆地實現不同類型的自然語言和資料庫查詢語言的轉化。所以,通過Quepy,僅僅修改幾行代碼,就可以實現你自己的自然語言查詢資料庫系統。GitHub:https://github.com/machinalis/quepy
- HanNLP:HanLP是由一系列模型與演算法組成的Java工具包,目標是普及自然語言處理在生產環境中的應用。不僅僅是分詞,而是提供詞法分析、句法分析、語義理解等完備的功能。HanLP具備功能完善、效能高效、架構清晰、語料時新、可自訂的特點。文檔使用操作說明:Python調用自然語言處理包HanLP 和 菜鳥如何調用HanNLP
2
OpenNLP:進行中文具名實體識別
OpenNLP是Apach下的Java自然語言處理API,功能齊全。如下給大家介紹一下使用OpenNLP進行中文語料具名實體識別的過程。
首先是預先處理工作,分詞去聽用詞等等的就不囉嗦了,其實將分詞的結果中間加上空格隔開就可以了,OpenNLP可以將這樣形式的的語料照處理英文的方式處理,有些關於字元處理的注意點在後面會提到。
其次我們要準備各個具名實體類別所對應的詞庫,詞庫被存在文字文件中,文檔名即是具名實體類別的TypeName,下面兩個function分別是載入某類具名實體詞庫中的詞和載入具名實體的類別。
/** * 載入詞庫中的具名實體 * * @param nameListFile * @return * @throws Exception */public static List<String> loadNameWords(File nameListFile)throws Exception {List<String> nameWords = new ArrayList<String>();if (!nameListFile.exists() || nameListFile.isDirectory()) {System.err.println("不存在那個檔案");return null;}BufferedReader br = new BufferedReader(new FileReader(nameListFile));String line = null;while ((line = br.readLine()) != null) {nameWords.add(line);}br.close();return nameWords;}/** * 擷取具名實體類型 * * @param nameListFile * @return */public static String getNameType(File nameListFile) {String nameType = nameListFile.getName();return nameType.substring(0, nameType.lastIndexOf("."));}
因為OpenNLP要求的訓練語料是這樣子的:
XXXXXX<START:Person>????<END>XXXXXXXXX<START:Action>????<END>XXXXXXX
被標註的具名實體被放在<START><END>範圍中,並標出了實體的類別。接下來是對具名實體識別模型的訓練,先上代碼:
import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.StringReader;import java.util.Collections;import opennlp.tools.namefind.NameFinderME;import opennlp.tools.namefind.NameSample;import opennlp.tools.namefind.NameSampleDataStream;import opennlp.tools.namefind.TokenNameFinderModel;import opennlp.tools.util.ObjectStream;import opennlp.tools.util.PlainTextByLineStream;import opennlp.tools.util.featuregen.AggregatedFeatureGenerator;import opennlp.tools.util.featuregen.PreviousMapFeatureGenerator;import opennlp.tools.util.featuregen.TokenClassFeatureGenerator;import opennlp.tools.util.featuregen.TokenFeatureGenerator;import opennlp.tools.util.featuregen.WindowFeatureGenerator;/** * 中文具名實體識別模型訓練組件 * * @author ddlovehy * */public class NamedEntityMultiFindTrainer {// 預設參數private int iterations = 80;private int cutoff = 5;private String langCode = "general";private String type = "default";// 待設定的參數private String nameWordsPath; // 具名實體詞庫路徑private String dataPath; // 訓練集已分詞語料路徑private String modelPath; // 模型儲存路徑public NamedEntityMultiFindTrainer() {super();// TODO Auto-generated constructor stub}public NamedEntityMultiFindTrainer(String nameWordsPath, String dataPath,String modelPath) {super();this.nameWordsPath = nameWordsPath;this.dataPath = dataPath;this.modelPath = modelPath;}public NamedEntityMultiFindTrainer(int iterations, int cutoff,String langCode, String type, String nameWordsPath,String dataPath, String modelPath) {super();this.iterations = iterations;this.cutoff = cutoff;this.langCode = langCode;this.type = type;this.nameWordsPath = nameWordsPath;this.dataPath = dataPath;this.modelPath = modelPath;}/** * 產生定製特徵 * * @return */public AggregatedFeatureGenerator prodFeatureGenerators() {AggregatedFeatureGenerator featureGenerators = new AggregatedFeatureGenerator(new WindowFeatureGenerator(new TokenFeatureGenerator(), 2, 2),new WindowFeatureGenerator(new TokenClassFeatureGenerator(), 2,2), new PreviousMapFeatureGenerator());return featureGenerators;}/** * 將模型寫入磁碟 * * @param model * @throws Exception */public void writeModelIntoDisk(TokenNameFinderModel model) throws Exception {File outModelFile = new File(this.getModelPath());FileOutputStream outModelStream = new FileOutputStream(outModelFile);model.serialize(outModelStream);}/** * 讀出標註的訓練語料 * * @return * @throws Exception */public String getTrainCorpusDataStr() throws Exception {// TODO 考慮入持久化判斷直接載入標註資料的情況 以及增量式訓練String trainDataStr = null;trainDataStr = NameEntityTextFactory.prodNameFindTrainText(this.getNameWordsPath(), this.getDataPath(), null);return trainDataStr;}/** * 訓練模型 * * @param trainDataStr * 已標註的訓練資料整體字串 * @return * @throws Exception */public TokenNameFinderModel trainNameEntitySamples(String trainDataStr)throws Exception {ObjectStream<NameSample> nameEntitySample = new NameSampleDataStream(new PlainTextByLineStream(new StringReader(trainDataStr)));System.out.println("**************************************");System.out.println(trainDataStr);TokenNameFinderModel nameFinderModel = NameFinderME.train(this.getLangCode(), this.getType(), nameEntitySample,this.prodFeatureGenerators(),Collections.<String, Object> emptyMap(), this.getIterations(),this.getCutoff());return nameFinderModel;}/** * 訓練組件總調用方法 * * @return */public boolean execNameFindTrainer() {try {String trainDataStr = this.getTrainCorpusDataStr();TokenNameFinderModel nameFinderModel = this.trainNameEntitySamples(trainDataStr);// System.out.println(nameFinderModel);this.writeModelIntoDisk(nameFinderModel);return true;} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();return false;}}}
註:
- 參數:iterations是訓練演算法迭代的次數,太少了起不到訓練的效果,太大了會造成過擬合,所以各位可以自己試試效果;
- cutoff:語言模型掃描視窗的大小,一般設成5就可以了,當然越大效果越好,時間可能會受不了;
- langCode:語種代碼和type實體類別,因為沒有專門針對中文的代碼,設成“普通”的即可,實體的類別因為我們想訓練成能識別多種實體的模型,於是設定為“預設”。
說明:
- prodFeatureGenerators()方法用於產生個人訂製的特徵產生器,其意義在於選擇什麼樣的n-gram語義模型,代碼當中顯示的是選擇視窗大小為5,待測具名實體詞前後各掃描兩個詞的範圍計算特徵(加上自己就是5個),或許有更深更準確的意義,請大家指正;
- trainNameEntitySamples()方法,訓練模型的核心,首先是將如上標註的訓練語料字串傳入產生字元流,再通過NameFinderME的train()方法傳入上面設定的各個參數,訂製特徵產生器等等,關於源實體映射對,就按預設傳入空Map就好了。
原始碼開源在:https://github.com/Ailab403/ailab-mltk4j,test包裡面對應有完整的調用demo,以及file檔案夾裡面的測試語料和已經訓練好的模型。
3 StanfordNLP:實現中文具名實體識別
使用Stanford Word Segmenter and Stanford Named Entity Recognizer (NER)實現中文具名實體識別 - 以家為家,以鄉為鄉,以國為國,以天下為天下 - 部落格頻道 - CSDN.NET
1、分詞介紹
斯坦福大學的分詞器,該系統需要JDK 1.8+,從上面連結中下載stanford-segmenter-2014-10-26,解壓之後,如所示進入data目錄,其中有兩個gz壓縮檔,分別是ctb.gz和pku.gz,其中CTB:賓州大學的中國樹庫訓練資料 ,PKU:中國北京大學提供的訓練資料。當然了,你也可以自己訓練,一個訓練的例子可以在這裡面看到http://nlp.stanford.edu/software/trainSegmenter-20080521.tar.gz2、NER介紹斯坦福NER是採用Java實現,可以識別出(PERSON,ORGANIZATION,LOCATION),使用本軟體發表的研究成果需引用下述論文:在:http://nlp.stanford.edu/~manning/papers/gibbscrf3.pdf在NER頁面可以下載到兩個壓縮檔,分別是stanford-ner-2014-10-26和stanford-ner-2012-11-11-chinese將兩個檔案解壓可看到預設NER可以用來處理英文,如果需要處理中文要另外處理。3、分詞和NER使用在Eclipse中建立一個Java Project,將data目錄拷貝到項目根路徑下,再把stanford-ner-2012-11-11-chinese解壓的內容全部拷貝到classifiers檔案夾下,將stanford-segmenter-3.5.0加入到classpath之中,將classifiers檔案夾拷貝到項目根目錄,將stanford-ner-3.5.0.jar和stanford-ner.jar加入到classpath中。最後,去http://nlp.stanford.edu/software/corenlp.shtml下載stanford-corenlp-full-2014-10-31,將解壓之後的stanford-corenlp-3.5.0也加入到classpath之中。最後的Eclipse中結構如下:Chinese NER:這段說明,很清晰,需要將中文分詞的結果作為NER的輸入,然後才能識別出NER來。同時便於測試,本Demo使用junit-4.10.jar,下面開始上代碼
import edu.stanford.nlp.ie.AbstractSequenceClassifier; import edu.stanford.nlp.ie.crf.CRFClassifier; import edu.stanford.nlp.ling.CoreLabel; /** * * <p> * ClassName ExtractDemo * </p> * <p> * Description 載入NER模組 * */ public class ExtractDemo { private static AbstractSequenceClassifier<CoreLabel> ner; public ExtractDemo() { InitNer(); } public void InitNer() { String serializedClassifier = "classifiers/chinese.misc.distsim.crf.ser.gz"; // chinese.misc.distsim.crf.ser.gz if (ner == null) { ner = CRFClassifier.getClassifierNoExceptions(serializedClassifier); } } public String doNer(String sent) { return ner.classifyWithInlineXML(sent); } public static void main(String args[]) { String str = "我 去 吃飯 , 告訴 李強 一聲 。"; ExtractDemo extractDemo = new ExtractDemo(); System.out.println(extractDemo.doNer(str)); System.out.println("Complete!"); } }
import java.io.File; import java.io.IOException; import java.util.Properties; import org.apache.commons.io.FileUtils; import edu.stanford.nlp.ie.crf.CRFClassifier; import edu.stanford.nlp.ling.CoreLabel; /** * * <p> * Description 使用Stanford CoreNLP進行中文分詞 * </p> * */ public class ZH_SegDemo { public static CRFClassifier<CoreLabel> segmenter; static { // 設定一些初始化參數 Properties props = new Properties(); props.setProperty("sighanCorporaDict", "data"); props.setProperty("serDictionary", "data/dict-chris6.ser.gz"); props.setProperty("inputEncoding", "UTF-8"); props.setProperty("sighanPostProcessing", "true"); segmenter = new CRFClassifier<CoreLabel>(props); segmenter.loadClassifierNoExceptions("data/ctb.gz", props); segmenter.flags.setProperties(props); } public static String doSegment(String sent) { String[] strs = (String[]) segmenter.segmentString(sent).toArray(); StringBuffer buf = new StringBuffer(); for (String s : strs) { buf.append(s + " "); } System.out.println("segmented res: " + buf.toString()); return buf.toString(); } public static void main(String[] args) { try { String readFileToString = FileUtils.readFileToString(new File("澳門141人食物中毒與進食“問題生蠔”有關.txt")); String doSegment = doSegment(readFileToString); System.out.println(doSegment); ExtractDemo extractDemo = new ExtractDemo(); System.out.println(extractDemo.doNer(doSegment)); System.out.println("Complete!"); } catch (IOException e) { e.printStackTrace(); } } }
注意一定是JDK 1.8+的環境,最後輸出結果如下:
Python自然語言處理工具小結