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());
}

2006年11月2日 星期四

HOWTO Convert Char 2 LPCWSTR

強制轉換

char c[20]="abc";
LPCWSTR lc=(WCHAR *)c;

但是這樣會遺失資訊

利用 ATL Macro

參考此頁

下面是幾個例子:

#include
LPCWSTR lc = CA2W(c);

HANDLE fh = CreateFile(CA2W(file), access_mode, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,NULL);

USE_CONVERSION;
LPCWSTR lc = A2W(c);

LPCWSTR pw = T2W("Hello,world!"); // tchar -> wchar

LPCTSTR pt = W2T(L"Hello,world!"); // wchar -> tchar

其它參考

char* 轉換成 CString

若將 char* 轉換成 CString,除了直接賦值外,還可使用 CString::Format 進行。例如:

char chArray[] = "This is a test";
char * p = "This is a test";

LPSTR p = "This is a test";

或在已定義 Unicode 中

TCHAR * p = _T("This is a test");

LPTSTR p = _T("This is a test");
CString theString = chArray;
theString.Format(_T("%s"), chArray);
theString = p;

CString 轉換成 char*

若將 CString 類轉換成 char*(LPSTR) 類型,常常使用下列三種方法:

使用強制轉換

例如:

CString theString( "This is a test" );
LPTSTR lpsz =(LPTSTR)(LPCTSTR)theString;

需要說明的是,strcpy(或可移值 Unicode/MBCS 的 _tcscpy)的第二個參數是 const wchar_t* (Unicode) 或 const char* (ANSI),系統編譯器將會自動對其進行轉換。

使用 CString::GetBuffer

例如:

CString s(_T("This is a test "));
LPTSTR p = s.GetBuffer();

// 在這裏添加使用p的代碼
if(p != NULL) *p = _T('\0');
s.ReleaseBuffer();
// 使用完後及時釋放,以便能使用其他的CString成員函數

BSTR 轉換成 char*

使用 ConvertBSTRToString

例如:

#include
#pragma comment(lib, "comsupp.lib")
int _tmain(int argc, _TCHAR* argv[])
{
BSTR bstrText = ::SysAllocString(L"Test");
char* lpszText2 = _com_util::ConvertBSTRToString(bstrText);
SysFreeString(bstrText); // 用完釋放
delete[] lpszText2;
return 0;
}

使用 _bstr_t 的賦值運算符重載

例如:

_bstr_t b = bstrText;
char* lpszText2 = b;

char* 轉換成 BSTR

使用 SysAllocString 等 API 函數

例如:

BSTR bstrText = ::SysAllocString(L"Test");
BSTR bstrText = ::SysAllocStringLen(L"Test",4);
BSTR bstrText = ::SysAllocStringByteLen("Test",4);

使用 COleVariant 或 _variant_t

例如:

//COleVariant strVar("This is a test");
_variant_t strVar("This is a test");
BSTR bstrText = strVar.bstrVal;

使用 _bstr_t

這是一種最簡單的方法。例如:

BSTR bstrText = _bstr_t("This is a test");

使用 CComBSTR

例如:

BSTR bstrText = CComBSTR("This is a test");

CComBSTR bstr("This is a test");
BSTR bstrText = bstr.m_str;

使用 ConvertStringToBSTR

例如:

char* lpszText = "Test";
BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText);

CString 轉換成 BSTR

通常是通過使用 CStringT::AllocSysString 來實現。例如:

CString str("This is a test");
BSTR bstrText = str.AllocSysString();
// …
SysFreeString(bstrText); // 用完釋放

BSTR 轉換成 CString

一般可按下列方法進行:

BSTR bstrText = ::SysAllocString(L"Test");
CStringA str;
str.Empty();
str = bstrText;

ANSI、Unicode 和寬字元之間的轉換

可以使用 MultiByteToWideChar 將 ANSI 字元轉換成 Unicode 字元,或是使用 WideCharToMultiByte 將 Unicode 字元轉換成 ANSI 字元。

另外也可以使用“_T”將 ANSI 轉換成“一般”類型字串,使用“L”將 ANSI 轉換成 Unicode,而在託管 C++ 環境中還可使用 S 將 ANSI 字串轉換成 String* 物件。例如:

TCHAR tstr[] = _T("this is a test");
wchar_t wszStr[] = L"This is a test";
String* str = S”This is a test”;

此外,還能更方便的使用 ATL 7.0 的轉換類別。ATL7.0 在原有 3.0 基礎上完善和增加了許多字串轉換巨集以及提供相應的類別。

其中,第一個 C 表示“class”,以便於 ATL 3.0 相區別,第二個 C 表示常數,2 表示“to”,EX 表示要開闢一定大小的緩衝。SourceType 和 DestinationType 可以是 A、 T、W 和 OLE,其含義分別是 ANSI、Unicode、“一般”類型和 OLE 字串。例如,CA2CT 就是將 ANSI 轉換成一般類型的字串常數。下面是一些例子:

LPTSTR tstr= CA2TEX<16>("this is a test");
LPCTSTR tcstr= CA2CT("this is a test");
wchar_t wszStr[] = L"This is a test";
char* chstr = CW2A(wszStr);

參考