n-gramメモ

今日は自然言語処理の基本n-gramについて勉強した。n-gramというのは日本語文等の自然言語を解析するために使われる手法の一つで、例えば3-gramならある文章を3文字づつに区切って解析する。

3-gramの例(『例えばこんな風に行われる』という文の3-gram表現):

例えば
 えばこ
  ばこん
   こんな
    んな風
     な風に
      風に行
       に行わ
        行われ
         われる
          れる。

n-gramによって解析する内容は単純で、区切った文の中で何回同じ文がでてきたかを数えるというもの。上の例では、1つも同じ文がでてこなかった(『例えば』と『えばこ』とでは一致しないというように)のであんまり意味がないけど、解析する文が長くなればなるほど同じ文は増えて、どのような内容なのかある程度分かるようになる。


ところでいま勉強してる本には1-gramと3-gramのプログラム例が載っているのだけど、なぜか実行ができない(´・ω・`)コマンドプロンプトから実行するようなプログラムだとよく分からないから、プログラムを今使ってるVisual C++から実行できるように改造してみようと頑張ってみたけど全然うまくいかない。もっとやさしいプログラミング本からやり直した方がいいのかな・・・。


一応3-gramのプログラムを載せてみる。
ちなみに解析の精度を上げるためにgetwidechar関数で日本語だけを抽出している。

#include<stdio.h>
#define MAX 65535*3

/*テキストを読み込む*/
int getsource(char *s) {
	int n = 0;//文字数のカウンタ
	while((s[n++] = getchar()) != EOF) ;
	return n;
}

/*全角文字のみ取り出す*/
void getwidechar(char *t, char *s, int n) {
	int in = 0; //入力データのポインタ
	int out = 0; //出力データのポインタ
	int d;
	while(in < n) {
		d = (unsigned char)s[in];
		if(((d > 0x7F) && (d < 0xA0)) || (d > 0xDF) && (d < 0xF0)) { //2バイト文字
			t[out++] = s[in++];
			t[out++] = s[in++];
		}
		else ++in;
	}
	t[out] = '\0'; //文字列の終端
}

/*3-gramの出力*/
void outputtarget(char *target) {
	int i = 0;	
	while((target[i] != '\0') && (target[i+4] != '\0')) {
     //1文字めの出力
	putchar(target[i++]);
	putchar(target[i++]);
         //2文字めの出力
	putchar(target[i]);
	putchar(target[i+1]);
         //3文字めの出力
	putchar(target[i+2]);
	putchar(target[i+3]);
	putchar('\n');
	}
}

int main() {
	char source[MAX]; //入力データ
	char target[MAX]; //出力データ
	int numchar; //入力文字数

	/*テキストを読み込む*/
	numchar = getsource(source);

	/*全角文字のみ取り出す*/
	getwidechar(target, source, numchar);

	/*3-gramの出力*/
	outputtarget(target);

	return 0;
}

実行結果としてはあるファイルに書かれている文字を読み込んで

こんな
風に表
示され
るはず
なんだ
けど・
・・。

どうすれば実行できるのかねえ・・・。とりあえず時間はあるからもうちょっと考えてみるつもり。できなきゃとばせばいいや( ^ω^)読み進めていくうちに何かヒントが見つかるかもしれないしね。