啊哈自然語言處理包,集成了HanLP 、 Word2Vec 、 Mate-Tools等項目,提供高質量的中文自然語言處理服務。
AHANLP目前提供的功能有:
最新版本ahanlp.jar和對應的基礎數據包AHANLP_base ,點擊這裡下載。配置文件ahanlp.properties和hanlp.properties放入classpath 即可,對於多數項目,只需放到src 目錄下,編譯時IDE 會自動將其複製到classpath 中。
AHANLP 沿用HanLP 的數據組織結構,代碼和數據分離,用戶可以根據自己的需要選擇相應的數據包下載:
dictionary目錄和model目錄存放到項目的data/目錄下。data/model/目錄下。python -m pip install xxx.whl安裝)。然後下載word_cloud (提取碼9jb6),將解壓出的word_cloud文件夾放到項目根目錄下。AHANLP 項目中的各項參數均讀取自配置文件(不建議用戶修改),下面僅作簡單說明。
主配置文件為ahanlp.properties ,需要配置Word2Vec 模型路徑等,默認為
word2vecModel = data/model/wiki_chinese_word2vec(Google).model
hanLDAModel = data/model/SogouCS_LDA.model
srlTaggerModel = data/model/srl/CoNLL2009-ST-Chinese-ALL.anna-3.3.postagger.model
srlParserModel = data/model/srl/CoNLL2009-ST-Chinese-ALL.anna-3.3.parser.model
srlModel = data/model/srl/CoNLL2009-ST-Chinese-ALL.anna-3.3.srl-4.1.srl.model
wordCloudPath = word_cloud/
pythonCMD = python
HanLP 配置文件為hanlp.properties ,只需要在第一行設置data 目錄所在路徑,默認為
root=./
注:語義角色標註模塊的內存佔用較高,如果要使用該功能,請將JVM 的最大內存佔用設置為4GB。
AHANLP幾乎所有的功能都可以通過工具類AHANLP快捷調用。並且推薦用戶始終通過工具類AHANLP 調用,這樣將來AHANLP 升級後,用戶無需修改調用代碼。
所有Demo 位於test.demo 下,比下方簡介文檔覆蓋了更多細節,強烈建議運行一遍,也可以查閱:
AHANLP 接口文檔。
String content = "苏州大学的周国栋教授正在教授自然语言处理课程。" ;
// 标准分词
List < Term > stdSegResult = AHANLP . StandardSegment ( content );
System . out . println ( stdSegResult );
//[苏州大学/ntu, 的/ude1, 周/qt, 国栋/nz, 教授/nnt, 正在/d, 教授/nnt, 自然语言处理/nz, 课程/n, 。/w]
// NLP分词
List < Term > nlpSegResult = AHANLP . NLPSegment ( content );
System . out . println ( nlpSegResult );
//[苏州大学/ntu, 的/u, 周国栋/nr, 教授/n, 正在/d, 教授/v, 自然语言处理/nz, 课程/n, 。/w]標準分詞(StandardSegment)封裝了HMM-Bigram 模型,使用最短路方法分詞(最短路求解採用Viterbi 算法),兼顧了效率和效果。 NLP分詞(NLPSegment)封裝了感知機模型,由結構化感知機序列標註框架支撐,會同時執行詞性標註和命名實體識別,準確率更高,適合生產環境使用。
分詞默認的返回結果包含詞語和詞性,可以分別通過AHANLP.getWordList(stdSegResult)和AHANLP.getNatureList(stdSegResult)來獲取詞語或詞性列表。詞性標註請參見《HanLP 詞性標註集》。
如果需要自定義詞性過濾,可以使用me.xiaosheng.chnlp.seg.POSFilter類,它還實現了過濾標點、保留實詞等常用方法。
// 过滤标点
POSFilter . removePunc ( stdSegResult );
// 保留名词
POSFilter . selectPOS ( stdSegResult , Arrays . asList ( "n" , "ns" , "nr" , "nt" , "nz" ));上面的分詞器都支持對停用詞的過濾,只需再帶上第二個參數,並且設為true 就可以了
List < Term > stdSegResult = AHANLP . NLPSegment ( content , true );
List < String > stdWordList = AHANLP . getWordList ( stdSegResult );
System . out . println ( stdWordList );
//[苏州大学, 周国栋, 教授, 正在, 教授, 自然语言处理, 课程]分詞支持用戶自定義字典,HanLP 中使用CustomDictionary類表示,是一份全局的用戶自定義詞典,影響全部分詞器。詞典文本路徑是data/dictionary/custom/CustomDictionary.txt ,用戶可以在此增加自己的詞語(不推薦)。也可以單獨新建一個文本文件,通過配置文件CustomDictionaryPath=data/dictionary/custom/CustomDictionary.txt; 我的词典.txt;來追加詞典(推薦)。
詞典格式:
[单词] [词性A] [A的频次] [词性B] [B的频次] ...如果不填詞性則表示採用詞典的默認詞性。全国地名大全.txt ns;如果詞典路徑後面空格緊接著詞性,則該詞典默認是該詞性。**注意:**程序默認從緩存文件(filename.txt.bin 或filename.txt.trie.dat 和filename.txt.trie.value)中讀取字典,如果你修改了任何詞典,只有刪除緩存才能生效。
List < List < Term >> segResults = AHANLP . seg2sentence ( "Standard" , content , true );
for ( int i = 0 ; i < senList . size (); i ++)
System . out . println (( i + 1 ) + " : " + AHANLP . getWordList ( results . get ( i )));對長文本按句子進行分詞也是常見用法,返回是由所有句子分詞結果組成的列表。通過第一個segType 參數控制分詞器的類型:“Standard”對應標準分詞,“NLP”對應NLP分詞。
當然也可以先手工斷句,再進行多句分詞。
List < String > senList = AHANLP . splitSentence ( content );
List < List < Term >> senWordList = AHANLP . splitWordInSentences ( "Standard" , senList , true );
for ( int i = 0 ; i < senWordList . size (); i ++)
System . out . println (( i + 1 ) + " : " + senWordList . get ( i )); String sentence = "2013年9月,习近平出席上合组织比什凯克峰会和二十国集团圣彼得堡峰会,"
+ "并对哈萨克斯坦等中亚4国进行国事访问。在“一带一路”建设中,这次重大外交行程注定要被历史铭记。" ;
List < NERTerm > NERResult = AHANLP . NER ( sentence );
System . out . println ( NERResult );
//[中亚/loc, 习近平/per, 上合组织/org, 二十国集团/org, 哈萨克斯坦/loc, 比什凯克/loc, 圣彼得堡/loc, 2013年9月/time]封裝了感知機和CRF模型,由結構化感知機序列標註框架支撐,識別出文本中的時間、地名、人名、機構名:人名per 、地名loc 、機構名org 、 time time 。
String sentence = "北京是中国的首都" ;
CoNLLSentence deps = AHANLP . DependencyParse ( sentence );
for ( CoNLLWord dep : deps )
System . out . printf ( "%s --(%s)--> %s n " , dep . LEMMA , dep . DEPREL , dep . HEAD . LEMMA );
/*
北京 --(主谓关系)--> 是
是 --(核心关系)--> ##核心##
中国 --(定中关系)--> 首都
的 --(右附加关系)--> 中国
首都 --(动宾关系)--> 是
*/
// 词语依存路径
List < List < Term >> wordPaths = AHANLP . getWordPathsInDST ( sentence );
for ( List < Term > wordPath : wordPaths ) {
System . out . println ( wordPath . get ( 0 ). word + " : " + AHANLP . getWordList ( wordPath ));
}
/*
北京 : [北京, 是]
是 : [是]
中国 : [中国, 首都, 是]
的 : [的, 中国, 首都, 是]
首都 : [首都, 是]
*/
// 依存句法树前2层的词语
List < String > words = AHANLP . getTopWordsInDST ( sentence , 1 );
System . out . println ( words );
// [北京, 是, 首都]依存句法分析是對HanLP 中NeuralNetworkDependencyParser 的封裝,使用的是基於神經網絡的高性能依存句法分析器。分析結果為CoNLL 格式,可以按CoNLLWord 類型進行迭代,如上所示, CoNLLWord.LEMMA為從屬詞, CoNLLWord.HEAD.LEMMA為支配詞, CoNLLWord.DEPREL為依存標籤,默認為中文標籤。
如果需要使用英文標籤,只需再帶上第二個參數,並且設為true 就可以了
CoNLLSentence enDeps = AHANLP.DependencyParse(sentence, true);
關於依存標籤的詳細說明,可以參見《依存標籤》。
String document = "我国第二艘航空母舰下水仪式26日上午在中国船舶重工集团公司大连造船厂举行。航空母舰在拖曳牵引下缓缓移出船坞,停靠码头。目前,航空母舰主船体完成建造,动力、电力等主要系统设备安装到位。" ;
List < String > wordList = AHANLP . extractKeyword ( document , 5 );
System . out . println ( wordList );
//[航空母舰, 动力, 建造, 牵引, 完成]extractKeyword函數通過第二個參數設定返回的關鍵詞個數。內部通過TextRank 算法計算每個詞語的Rank 值,並按Rank 值降序排列,提取出前面的幾個作為關鍵詞。具體原理可以參見《TextRank算法提取關鍵詞和摘要》。
String document = "我国第二艘航空母舰下水仪式26日上午在中国船舶重工集团公司大连造船厂举行。"
+ "按照国际惯例,剪彩后进行“掷瓶礼”。随着一瓶香槟酒摔碎舰艏,两舷喷射绚丽彩带,周边船舶一起鸣响汽笛,全场响起热烈掌声。"
+ "航空母舰在拖曳牵引下缓缓移出船坞,停靠码头。第二艘航空母舰由我国自行研制,2013年11月开工,2015年3月开始坞内建造。" + "目前,航空母舰主船体完成建造,动力、电力等主要系统设备安装到位。"
+ "出坞下水是航空母舰建设的重大节点之一,标志着我国自主设计建造航空母舰取得重大阶段性成果。" + "下一步,该航空母舰将按计划进行系统设备调试和舾装施工,并全面开展系泊试验。" ;
List < String > senList = AHANLP . extractKeySentence ( document , 5 );
System . out . println ( "Key Sentences: " );
for ( int i = 0 ; i < senList . size (); i ++)
System . out . println (( i + 1 ) + " : " + senList . get ( i ));
System . out . println ( "Summary: " );
System . out . println ( AHANLP . extractSummary ( document , 50 ));
/*
Key Sentences:
1 : 航空母舰主船体完成建造
2 : 该航空母舰将按计划进行系统设备调试和舾装施工
3 : 我国第二艘航空母舰下水仪式26日上午在中国船舶重工集团公司大连造船厂举行
4 : 标志着我国自主设计建造航空母舰取得重大阶段性成果
5 : 出坞下水是航空母舰建设的重大节点之一
Summary:
我国第二艘航空母舰下水仪式26日上午在中国船舶重工集团公司大连造船厂举行。航空母舰主船体完成建造。
*/extractKeySentence函數負責摘取關鍵句,第二個參數控制摘取的關鍵句數量。 extractSummary函數負責自動摘要,第二個參數設定摘要字數上限。內部通過TextRank 算法計算每個句子的Rank 值,並按Rank 值降序排列,提取出前面的幾個作為關鍵句。自動摘要類似,並且還考慮了句子在原文中的位置以及句子的長度。具體原理可以參見《TextRank算法提取關鍵詞和摘要》。
句子之間的相似程度(即TextRank 算法中的權值)使用Word2Vec 提供的函數計算,默認使用了維基百科中文語料訓練出的模型,也可以使用自定義模型。
System . out . println ( "猫 | 狗 : " + AHANLP . wordSimilarity ( "猫" , "狗" ));
System . out . println ( "计算机 | 电脑 : " + AHANLP . wordSimilarity ( "计算机" , "电脑" ));
System . out . println ( "计算机 | 男人 : " + AHANLP . wordSimilarity ( "计算机" , "男人" ));
String s1 = "苏州有多条公路正在施工,造成局部地区汽车行驶非常缓慢。" ;
String s2 = "苏州最近有多条公路在施工,导致部分地区交通拥堵,汽车难以通行。" ;
String s3 = "苏州是一座美丽的城市,四季分明,雨量充沛。" ;
System . out . println ( "s1 | s1 : " + AHANLP . sentenceSimilarity ( s1 , s1 ));
System . out . println ( "s1 | s2 : " + AHANLP . sentenceSimilarity ( s1 , s2 ));
System . out . println ( "s1 | s3 : " + AHANLP . sentenceSimilarity ( s1 , s3 ));
/*
猫 | 狗 : 0.71021223
计算机 | 电脑 : 0.64130974
计算机 | 男人 : -0.013071457
s1 | s1 : 1.0
s1 | s2 : 0.6512632
s1 | s3 : 0.3648093
*/ wordSimilarity和sentenceSimilarity分別是計算詞語和句子相似度的函數,計算過程都使用到了Word2Vec 模型預訓練好的詞向量,使用前需要下載word2vec 模型,然後將解壓出的模型文件存放到項目的data/model/目錄下。詞語相似度直接通過計算詞向量餘弦值得到,句子相似度求取方式可以參見Word2Vec/issues1。如果想自己訓練Word2Vec 模型,可以參考訓練Google 版模型。
注: sentenceSimilarity默認使用標準分詞對句子進行分詞,並過濾停用詞。
String sentence = "全球最大石油生产商沙特阿美(Saudi Aramco)周三(7月21日)证实,公司的一些文件遭泄露。" ;
List < SRLPredicate > predicateList = AHANLP . SRL ( sentence );
for ( SRLPredicate p : predicateList ) {
System . out . print ( "谓词: " + p . getPredicate ());
System . out . print ( " t t句内偏移量: " + p . getLocalOffset ());
System . out . print ( " t句内索引: [" + p . getLocalIdxs ()[ 0 ] + ", " + p . getLocalIdxs ()[ 1 ] + "] n " );
for ( Arg arg : p . getArguments ()) {
System . out . print ( " t " + arg . getLabel () + ": " + arg . getSpan ());
System . out . print ( " t t句内偏移量: " + arg . getLocalOffset ());
System . out . print ( " t句内索引: [" + arg . getLocalIdxs ()[ 0 ] + ", " + arg . getLocalIdxs ()[ 1 ] + "] n " );
}
System . out . println ();
}
/*
谓词: 证实 句内偏移量: 36 句内索引: [36, 37]
TMP: 周三(7月21日) 句内偏移量: 27 句内索引: [27, 35]
A0: 全球最大石油生产商沙特阿美(Saudi Aramco) 句内偏移量: 0 句内索引: [0, 26]
A1: 公司的一些文件遭泄露 句内偏移量: 39 句内索引: [39, 48]
谓词: 遭 句内偏移量: 46 句内索引: [46, 46]
A0: 公司的一些文件 句内偏移量: 39 句内索引: [39, 45]
A1: 泄露 句内偏移量: 47 句内索引: [47, 48]
*/封裝了Mate-Tools 中的SRL 組件(包括詞性識別器和依存句法分析器),能夠識別出文本中的謂詞predicate和對應的論元:施事者A0 、受事者A1 、時間TMP和地點LOC 。添加了對長文本的支持SRLParseContent(content)以及文本偏移量的匹配,可以通過謂詞和論元在文本中的位置和偏移量進行定位。
注:每一個謂詞對應的某一類別的論元都可能不止一個,例如謂詞”攻擊“可以對應多個施事者A0(攻擊者)。
int topicNum510 = AHANLP . topicInference ( "data/mini/军事_510.txt" );
System . out . println ( "军事_510.txt 最可能的主题号为: " + topicNum510 );
int topicNum610 = AHANLP . topicInference ( "data/mini/军事_610.txt" );
System . out . println ( "军事_610.txt 最可能的主题号为: " + topicNum610 );LDA 主題預測默認使用新聞LDA 模型進行主題的預測,輸出最大概率的主題編號。默認模型從搜狗新聞語料庫(SogouCS)中每個類別抽取1000 篇(可能不滿)新聞中訓練得到,共包含100 個主題。
用戶也可以通過ZHNLP.trainLDAModel()自己訓練LDA 模型,訓練好後,使用重載的topicInference方法來加載
AHANLP . trainLDAModel ( "data/mini/" , 10 , "data/model/testLDA.model" );
int topicNum710 = AHANLP . topicInference ( "data/model/testLDA.model" , "data/mini/军事_710.txt" );
System . out . println ( "军事_710.txt 最可能的主题号为: " + topicNum710 );
int topicNum810 = AHANLP . topicInference ( "data/model/testLDA.model" , "data/mini/军事_810.txt" );
System . out . println ( "军事_810.txt 最可能的主题号为: " + topicNum810 );如果你需要運行LDADemo.java 進行測試,還需要下載SogouCA_mini,將解壓出的mini文件夾存放到項目的data/目錄下。
String tc = AHANLP . convertSC2TC ( "用笔记本电脑写程序" );
System . out . println ( tc );
String sc = AHANLP . convertTC2SC ( "「以後等妳當上皇后,就能買士多啤梨慶祝了」" );
System . out . println ( sc );
/*
用筆記本電腦寫程序
“以后等你当上皇后,就能买草莓庆祝了”
*/簡繁轉換是對HanLP 中convertToTraditionalChinese和convertToSimplifiedChinese方法的包裝。能夠識別簡繁分歧詞,比如打印机=印表機;以及許多簡繁轉換工具不能區分的字,例如“以後”、“皇后”中的兩個“後”字。
String document = "我国第二艘航空母舰下水仪式26日上午在中国船舶重工集团公司大连造船厂举行。" + "中共中央政治局委员、中央军委副主席范长龙出席仪式并致辞。9时许,仪式在雄壮的国歌声中开始。"
+ "按照国际惯例,剪彩后进行“掷瓶礼”。随着一瓶香槟酒摔碎舰艏,两舷喷射绚丽彩带,周边船舶一起鸣响汽笛,全场响起热烈掌声。"
+ "航空母舰在拖曳牵引下缓缓移出船坞,停靠码头。第二艘航空母舰由我国自行研制,2013年11月开工,2015年3月开始坞内建造。" + "目前,航空母舰主船体完成建造,动力、电力等主要系统设备安装到位。"
+ "出坞下水是航空母舰建设的重大节点之一,标志着我国自主设计建造航空母舰取得重大阶段性成果。" + "下一步,该航空母舰将按计划进行系统设备调试和舾装施工,并全面开展系泊试验。"
+ "海军、中船重工集团领导沈金龙、苗华、胡问鸣以及军地有关部门领导和科研人员、干部职工、参建官兵代表等参加仪式。" ;
List < String > wordList = AHANLP . getWordList ( AHANLP . StandardSegment ( document , true ));
WordCloud wc = new WordCloud ( wordList );
try {
wc . createImage ( "D: \ test.png" );
} catch ( IOException e ) {
e . printStackTrace ();
} WordCloud使用一個詞語列表創建WordCloud 對象,然後調用createImage方法創建詞云圖片,並且將圖片的保存地址作為參數傳入。詞云按照詞頻來繪製每個詞語的大小,詞頻越高,詞語越大;顏色及位置隨機生成。

默認生成圖片尺寸為500x400,背景色為白色。也可以自定義圖片的背景色和圖片尺寸
WordCloud wc = new WordCloud ( wordList );
wc . createImage ( "D: \ test_black.png" , true ); // 黑色背景
wc . createImage ( "D: \ test_1000x800.png" , 1000 , 800 ); // 尺寸 1000x800
wc . createImage ( "D: \ test_1000x800_black.png" , 1000 , 800 , true ); // 尺寸 1000x800, 黑色背景再次向以下這些項目的作者致以敬意,正是這些開源軟件推動了自然語言處理技術的普及和運用。