2006年11月17日 星期五

Maximum Entropy Modeling Toolkit

bbME

我客製化過後的 ME

  1. 啟用 LBFGS
  2. 預設 300 iteraction
  3. .NET CLR library 實做讀檔

注意事項

將 cutoff 設成 0 和設成 1 是一樣的,因為不會有 0 次的 event 啊!

另外,若是設的數值過大,比如 2000,但是在 train 資料中沒有出現超過 2000 的 event,那麼程式會出錯!如下的錯誤訊息:

 IFLAG= -3
IMPROPER INPUT PARAMETERS (N OR M ARE NOT POSITIVE)

使用方式

Train

依據 train.txt 建立一個名為 test.model 的 model 檔,並設定 iteraction 為 30(預設會啟用 L-BFGS):

MEMT.exe/maxent.exe train.txt -m model1 -i 30

假若指定 -b 參數,那麼 model 在儲存時會以 binary 的方式儲存,如此可以增進載入和儲存的速度(相較於 text mode)。在載入時,會自動判斷 model 的格式,因此不需要額外指定 -b 參數。

預設 MEMT 會使用 mmap() 系統呼叫來讀取檔案;若是無法順利的讀取,則請在參數中加上: --nommap。

若是指定 -v 則會印出 verbose 訊息。

Predict

進行 predict 並輸出 predict accuracy:

MEMT.exe/maxent -p  -m 

進行 predict 並輸出 label 到指定的檔案:

MEMT.exe/maxent -p -m  -o  

另外加上 --detail,會輸出完整的描述。

其它特殊使用

在 train.txt 上執行 10-fold cross-validation,並回報正確率:

MEMT.exe/maxent.exe -n 10 train.txt

編譯法

編譯 Maximum Entropy Modeling Toolkit for Python and C++

在編譯前,必須先安裝好 Intel 的 Fortran Compiler(可在此下載)。安裝完後,在 Visual Studio 環境中會多出開發 Fortran 的功能。

利用整合好的環境,編譯 src/lbfgs.f 檔,產生 static library。或是直接使用安裝好的 Intel Fortran Compiler Environment,在命令列下達:

ifort  -c -O3 lbfgs.f

這樣會產生 lbfgs/obj 檔。將該檔直接加到專案的檔案列表中。(拉到 IDE 內即可)

接著把所有的 C++ source code 匯入 C++ 專案後,修改 hash_map 和 hash_set 的定義(在編譯時會出錯,將它們的 namespace 改為 stdext 即可)。接著加入額外的 Include 目錄:lib(裡面含有 boot 目錄和其它標頭檔),並在連結器選項中加入 Intel Fortran 的 lib 作為額外的程式庫目錄。若是在編譯時發生:Strings.h 找不到時,請定義 HAVE_STRING_H 的前置處理器定義。

接著進行編譯。若是遇到 LIBCMTD.lib(crt0dat.obj) : error LNK2005: _exit 已經在 MSVCRTD.lib(MSVCR71D.dll) 中定義,等類似錯誤時,請在專案選項中的:「C/C++→程式碼產生→執行階段程式庫」將之修改為:多執行緒偵錯(/MTd),並且在「連結器→輸入」 中,將 LIBCMT.lib 加到忽略的特定程式庫中。

這是最後產生的專案檔。參考壓縮檔內的 build 目錄。要啟用 LBFGS 支援,則多定義 HAVE_FORTRAN 標頭。

CreateFile 失敗?

在編譯時,我習慣把 .c 檔設定為編譯為 C 程式碼。這似乎會造成呼叫 CreateFile 失敗。若是遇到該問題時,請將該 source code 修改成「C/C++→進階→編譯成為 C++ 程式碼/TP」。

此外,若遇到無法將 const char* 轉換為 LPCWSTR 的問題時,請參考本文。下面是一個修改範例:

// add by hongjie for CA2W
#include 

// ...
// modify by hongjie
//fh = CreateFile(file, access_mode, FILE_SHARE_READ, NULL,
fh = CreateFile(CA2W(file), access_mode, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS,NULL);

Link Error: unresolved external symbol iob ?

注意,用這種方式 compile 出來的為 dynamic link,因此目標電腦上必須安裝好 Intel Fortran!

參考本文

節錄如下:

Whatever your reason was for ignoring these libs, ignoring them is the reason you're getting linker errors. It looks like you're going to have to figure out why you are forced to ignore those libs, and correct it from there.

LNK2001s/LNK2019s are usually a result of mixing debug libs with release libs (or libs compiled with another version of Visual Studio). It can also be caused by static libraries not using the same runtime library (project properties -> c/c++ -> code generation -> runtime library -> should be /MDd for debug and /MD for release).

以這裡為例,在 compile LBFGS 時,應該再加上 -MD 參數;如下:

ifort  -c -O3 /Qvc8  -MD lbfgs.f
/MD
use dynamically-loaded, multithread runtime
/MDs
use dynamically-loaded, single thread runtime

convert System::String to std:string

參考原文

方法如下:

#include 
#include 
#include 
using namespace System;
bool To_CharStar( String^ source, char*& target )
{
pin_ptr wch = PtrToStringChars( source );
int len = (( source->Length+1) * 2);
target = new char[ len ];
return wcstombs( target, wch, len ) != -1;
}

bool To_string( String^ source, string &target )
{
pin_ptr wch = PtrToStringChars( source );
int len = (( source->Length+1) * 2);
char *ch = new char[ len ];
bool result = wcstombs( ch, wch, len ) != -1;
target = ch;
delete ch;
return result;
}

convert std:string to System::String

System::String* std2gc(const std::string& s)
{
return new System::String(s.c_str());
}

沒有留言: