前段時間使用了HanLP一個純JAVA分詞工具包,後來老大說分詞效果不是很好,須要換一個分詞工具。因而推薦了一個分詞工具——NLPIR,它是中科院XXX研發的一個分詞工具。這個分詞工具只用C/C++寫的,可是它提供了JAVA,C#等調用接口。因而我但願是的經過java來調用。使用java調用C/C++的代碼須要用到JNA,因此工程須要添加JNA的依賴包。java
這裏面官網上介紹的不是特別清楚,裏面有些坑,第一次使用的人還真須要一段時間解決,下面將我踩的坑記錄一下:linux
一、首先進官網:http://ictclas.nlpir.org/ 下載相應的安裝包,我下載的是:git
20160907102816_ICTCLAS2016分詞系統下載包.zipgithub
解壓以後會出現以下文件目錄:安全
其中,主要的幾個目錄是:函數
(1)Data,這個目錄是放了license(NLPIR.user)在裏面,這個若是你配置成功,初始化失敗,通常都是license過時了。這個license目前是一個月更新一次。工具
(2)lib ,這個目錄存放了linux和window下,運行須要的dll文件和.so文件。其中分別有對應的位數:spa
(3)sample,這個目錄下面有多個語言實現的example。因爲我這裏使用的是java,因此就選擇java,選擇JNA,在選擇JnaTest_NLPIR。在這個java工程就是提供的一個例子。操作系統
能夠將例子導入工程中,代碼以下:scala
package code; import java.io.UnsupportedEncodingException; import utils.SystemParas; import com.sun.jna.Library; import com.sun.jna.Native; public class NlpirTest { // 定義接口CLibrary,繼承自com.sun.jna.Library public interface CLibrary extends Library { // 定義並初始化接口的靜態變量 CLibrary Instance = (CLibrary) Native.loadLibrary( "NLPIR", CLibrary.class); //這裏須要注意,這個位置就設置爲NLPIR是不可以改變,這裏折騰我很久了,原來是這個NLPIR文件是不能改變。 // printf函數聲明 public int NLPIR_Init(byte[] sDataPath, int encoding, byte[] sLicenceCode); public String NLPIR_ParagraphProcess(String sSrc, int bPOSTagged); public String NLPIR_GetKeyWords(String sLine, int nMaxKeyLimit, boolean bWeightOut); public void NLPIR_Exit(); } public static String transString(String aidString, String ori_encoding, String new_encoding) { try { return new String(aidString.getBytes(ori_encoding), new_encoding); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } public static void main(String[] args) throws Exception { String argu = ""; // String system_charset = "GBK";//GBK----0 String system_charset = "GBK"; int charset_type = 1; // int charset_type = 0; // 調用printf打印信息 int init_flag = CLibrary.Instance.NLPIR_Init(argu .getBytes(system_charset), charset_type, "0" .getBytes(system_charset)); if (0 == init_flag) { System.err.println("初始化失敗!"); return; } String sInput = "據悉,質檢總局已將最新有關狀況再次通報美方,要求美方增強對輸華玉米的產地來源、運輸及倉儲等環節的管控措施,有效避免輸華玉米被未經我國農業部安全評估並批准的轉基因品系污染。"; String nativeBytes = null; try { nativeBytes = CLibrary.Instance.NLPIR_ParagraphProcess(sInput, 3); System.out.println("分詞結果爲: " + nativeBytes); int nCountKey = 0; String nativeByte = CLibrary.Instance.NLPIR_GetKeyWords(sInput, 10,false); System.out.print("關鍵詞提取結果是:" + nativeByte); CLibrary.Instance.NLPIR_Exit(); } catch (Exception ex) { // TODO Auto-generated catch block ex.printStackTrace(); } } }
此時這樣設置以後,接下來須要區分window和linux:
(1)如果在window下,只須要將NLPIR.dll文件拷貝到工程目錄下便可,就能夠在IDE裏面運行。如果在控制檯的話,一樣須要將NLPIR.dll文件拷貝到jar包同目錄下便可。
(2)如果在linux下,只須要將libNLPIR.so文件拷貝到當前jar包的目錄下便可。
下面說說我踩得坑:
坑一、如上述描述,很是簡單的使用,硬是給我搞了一天才搞定,這說明什麼?剛開始我所遇到的是CLibrary Instance = (CLibrary) Native.loadLibrary( "NLPIR", CLibrary.class);這句究竟是加載什麼路徑下的庫文件。費了很大的勁,最後採用的是使用相對路徑。只須要填寫「NLPIR」便可。而且這個名字是不能夠改變的。
坑二、當你將NLPIR.dll文件添加到工程後,覺得應該是能夠了,可是仍是報錯,報以下錯誤:
這個錯誤主要緣由是dll文件位數與操做系統的位數不一致所形成的。因爲我是64位的操做系統,因此講NLPIR.dll文件換成64位的便可。
坑三、當你上面都搞定了,運行以後,會報"初始化失敗"的錯誤,這個錯誤剛開始搞了很久,沒弄明白,由於以爲本身都配置好了,爲何仍是初始化失敗,這也是我花費時間最長的地方。後來網上一查發現,原來是有一個license。它是有時間的限制的。因而須要更換最新的license。去哪裏更換呢?我在網上找到一我的的電話,直接打電話過去問的,聽過那人介紹,原來在下載的時候,有標明license下載的地方。以下所示:https://github.com/NLPIR-team/NLPIR/tree/master/License
license原來是在這裏下載。搞了半天,license放到了這麼隱蔽的位置。
坑四、如上所示,也更換了最新的license,能夠運行了。可是接下來,個人想法是將這個東西打jar包,在linux上運行,搞了半天不知道怎麼回事,總是報錯,最後的緣由是在設置坑1的時候路徑問題。由於一開始我設置的是絕對路徑,老是報錯,後來直接用相對路徑。就不報錯了。
坑五、本地是能夠運行ICTCLAS了,可是因爲NLP處理的預料都是比較大的數據,想法是提交到集羣上去運行。那麼如何實現呢?這裏須要解決兩個問題:
(1)libNLPIR.so文件的問題,因爲ICTCLAS是C/C++寫的代碼,利用java/scala調用相應的API的時候,都是經過JNA調用.so裏面的庫函數來實現的。因此要想提交到集羣上去運行,首先要解決的是各個節點如何能讀取到libNLPIR.so文件?
解決的辦法:將libNLPIR.so文件放在全部的節點的同一個目錄下:/lib64/libNLPIR.so ,而且修改該.so文件的權限爲777.
(2)Data中的配置文件和license文件在集羣中如何加載?
解決的辦法:再次查看ICTCLAS的參考手冊,發現函數NLPIR_Init是有一個參數能夠指定Data的路徑的。因而借鑑上面的思路,即將Data目錄放到全部的節點相同的目錄下/dic/Data。這裏須要注意點,函數NLPIR_Init的表示形式是:
bool NLPIR_Init(const char * sInitDirPath=0,int encoding=GBK_CODE,const char*sLicenceCode=0);
這裏的參數sInitDirPath只須要傳遞Data的父目錄便可。即:/dic 便可。(一開始我傳入的參數是/dic/Data,最後結果仍是報「初始化失敗」的錯誤。)
至此,就能夠在集羣上運行ICTCLAS分詞了。
坑六、利用ICTCLAS在集羣上分詞,爲了提升運行速度,咱們一般是考慮增長運行集羣資源,如CPU,內存。但這樣形成以下錯誤:
在datanote節點上出現以下兩個錯誤:
形成以上兩個錯誤的緣由是:當咱們在增長運行資源的同時,集羣會在同個節點上分配兩個或者兩個以上的executor,而在程序運行的過程當中,當一個executor釋放資源時,會致使另一個executor的資源也釋放了。從而引起上面的錯誤。
解決的辦法是:減小運行的資源,從而保證每一個節點只運行一個executor。