用CRF++開源工具做文本序列標註教程
來自專欄自然語言處理
本文只介紹如何快速的使用CRF++做序列標註,對其中的原理和訓練測試參數不做介紹。
官網地址:CRF++: Yet Another CRF toolkit
主要完成如下功能:
輸入 -> "周杰倫是誰"輸出 -> "[周杰倫:artist]是誰"
一、資源準備
下載鏈接中的內容:
鏈接:https://pan.baidu.com/s/16iw3WBSHI1U5U1G_xbikDA 密碼:cfqi
該文件夾裡面包含了以下內容:
1、CRF++-0.58.tar.gz,CRF++開源工具,這個是從CRF++官網上下載的。
2、data文件夾,訓練和測試需要的數據,這個是我自己寫的,其中:
- input文件夾,存放所需要的數據:train_data.txt,訓練數據,這裡只有幾條作為示例,實際工程中,需要上萬條數據;test_data.txt,測試數據;crf.template,特徵模板。
- output文件夾 -> 輸出的模型和測試結果。
3、code文件夾,C++調用CRF++介面的代碼示例,這個是我自己寫的。
二、CRF++的編譯
按照如下命令進行:
tar zxvf CRF++-0.58.tar.gzcd CRF++-0.58./configuremakesudo make install
這時候就編譯安裝成功了。
cd /usr/local/bin cd /usr/local/lib
切換到上面這兩個目錄,bin目錄下可以看到crf_learn和crf_test兩個可執行程序,分別用於模型的訓練和測試; lib目錄下是生成的CRF++庫。
//備註1:CRF++-0.58/.libs,這個目錄下也有生成上述可執行程序和庫。//備註2:如果不想安裝到上述目錄,或者沒有root許可權,在configure的時候指定安裝目錄即可。
三、模型訓練
按照如下命令進行:
cd CRF++_tutorial/data./train.sh
這樣,我們就得到了模型,即output/crf.mdl文件,這個文件是二進位的沒辦法查看。
train.sh腳本內容如下:
#/usr/local/bin/crf_learn: 前面編譯生成的crf++的訓練工具#input/crf.template: 特徵模板#input/train_data.txt: 訓練數據#output/crf.mdl: 訓練輸出的模型export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/usr/local/bin/crf_learn input/crf.template input/train_data.txt output/crf.mdl
訓練數據格式如下:
四、測試
按照如下命令進行:
cd CRF++_tutorial/data ./test.sh
這樣,我們就得到了預測的結果,即output/test_result.txt文件,可以打開看下預測結果。
test.sh腳本內容如下:
#/usr/local/bin/crf_test: 前面編譯生成的crf++的測試工具#-m output/crf.mdl: train.sh腳本訓練輸出的crf模型#input/test_data.txt: 測試數據#-o output/test_result.txt: 輸出測試結果 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/usr/local/bin/crf_test -m output/crf.mdl input/test_data.txt -o output/test_result.txt
測試數據格式如下(testdata和traindata需要用相同的編碼格式,不然沒法解析):
測試結果如下,雖然訓練數據只有幾條,但測試結果還是挺準的哈:
五、C++介面調用示例
按照如下命令進行:
cd CRF++_tutorial/codecmake .make./crf_test
程序輸出結果如下:
具體調用流程請參考CRF++_tutorial/code/main.cpp
代碼如下:
#include <iostream>#include <string>#include <vector>#include "crfpp.h"using namespace std;int main(){ //> 0.測試輸入 vector<string> query; query.push_back("周"); query.push_back("傑"); query.push_back("倫"); query.push_back("是"); query.push_back("誰"); //> 1.模型載入 cout << ">>>>>> Begin to load crf++ model……" << endl; CRFPP::Model* crf_model_ = CRFPP::createModel("-m ../data/output/crf.mdl -v 3"); cout << ">>>>>> Success to load crf++ model !" << endl; //> 2.創建CRF++對象 CRFPP::Tagger* tagger = crf_model_->createTagger(); //> 3.add query vector<string>::iterator it = query.begin(); for ( ; it != query.end(); it++){ tagger->add((*it).c_str()); } //< 4.對query進行標註 if (!tagger->parse()){ cout << ">>>>>> Fail to parse !" << endl; return -1; } //> 5.列印標註結果 cout << "標註結果: " << endl; for (size_t i = 0; i < tagger->size(); i++){ cout << query[i] << " " << tagger->y2(i) << endl; } return 0;}
推薦閱讀: