丁宇 | DING Yu

SPAM、Bayesian和中文 5 - 使b8贝叶斯算法支持中文

中文分词简介

在使用贝叶斯算法分类文本时,中文处理是个头疼的问题,这主要体现在中文分词上。所谓分词的意思就是让计算机能够拆分出一句话中的词,比如把“我们爱祖国”分为“我们”、“爱”和“祖国”,这是简单的情况,更复杂比如把“变态性心理”按上下文语境分别拆分为“变态性”“心理”和“变态”“性心理”[1]。由于词的定义、分词标准和词的判定都没有一个统一的共识,再加上计算机在处理语义上的困难,因此“汉语自动分词已经被研究了二十多年,但是目前仍然是制约汉语信息处理发展的一个瓶颈”[2]。目前公认的比较好的分词技术,来源于中科院计算所的“汉语词法分析系统ICTCLAS”,它提供了Windows和Linux平台下C#、C和Java JNI的API。

LT的简单做法:中文分字

不过本文并非讨论分词技术,因为这项技术本身已经超越了目前LT的需求。实际上,我们只要对b8做一些改动,让它在拆分文本时考虑到双字节字符(比如中文)的情况,并在实际拆分时以字为单位,就可以应付一般的情况。

LT从1月24日发布的0.4.4中开始使用改造过的b8贝叶斯算法,从实际运行情况来看,改造后的b8能够比较好的处理中文的情况。另外由于绝大部分SPAM都是英文,因此总的来说中文分字的做法可以接受。

改造b8

打开b8/lexer/lexer_default.php文件,首先修改lexer_default()这个constructor,在方法的最后添加如下代码:

//set the default encoding for mutil-byte characters
mb_internal_encoding('UTF-8');

接着修改getTokens(),第一是提取中文标点符号,在$tokens = "";一行代码下面添加如下代码:

//strip Chinese punctuation
$text = preg_replace('/[“”!◎#¥%……※×()——+§『』【】,。、‘’;:~·]/u', '', $text);

第二处理网址和IP地址,找到如下代码:

preg_match_all("/([A-Za-z0-9\_\-\.]+)/", $text, $raw_tokens);

将其修改为:

//exract all Chinese tokens
preg_match_all('/[一-龥]/u', $text, $raw_tokens_chinese);		

//exract all Latin tokens		
preg_match_all("/([A-Za-z0-9\_\-\.]+)/", $text, $raw_tokens_latin);

将提取出来的中文和拉丁字符合并在一起,组成raw tokens:

$raw_tokens = array_merge($raw_tokens_chinese[0], $raw_tokens_latin[0]);

第三继续提取剩余的中文和拉丁文字符,找到如下代码:

# Raw splitting of the remaining text

$raw_tokens = preg_split("/[^A-Za-z0-9!?\$дег'`─╓▄фЎ№▀╔щ╚ш╩ъ┴с└р┬т╙є╥Є╘Ї╟ч]/", $text);

将其修改为:

# Raw splitting of the remaining text

//exract all Chinese tokens, split each Chinese character with preg_match_all()
preg_match_all('/[一-龥]/u', $text, $raw_tokens_chinese);
		
//delete Chinese characters from the text, extract all Latin tokens
$raw_latin = $this->strip_whitespaces(preg_replace('/[一-龥]!?/u', ' ', $text));
$raw_tokens_latin = preg_split("/[^A-Za-z0-9!?\$дег'`─╓▄фЎ№▀╔щ╚ш╩ъ┴с└р┬т╙є╥Є╘Ї╟ч]/", $raw_latin);

//merge Chinese tokens and Latin's
$raw_tokens = array_merge($raw_tokens_chinese[0], $raw_tokens_latin);	

然后修改isValid(),找到如下代码:

# Check for a proper length
if(strlen($token) config['minSize'] or strlen($token) > $this->config['maxSize'])
	return FALSE;

将其修改为:

# Check for a proper length
//only when the token is NOT Chinese we need to do the check
if(!preg_match('/[一-龥]/u', $token))
{
	if(strlen($token) config['minSize'] or strlen($token) > $this->config['maxSize'])
	return FALSE;
}

至此b8的中文化改造和本系列文章都完成了,你可以试试效果:),抵御SPAM这块我也接触不久,有问题欢迎讨论。

 

文中的一些标注:

  1. “变态性心理”这个词组来源于陈思和主编、复旦出版的《中国当代文学史教程》,是用来形容郁达夫在旅日留学时的苦闷、矛盾和抑郁的心情,这些心情连同背后的生活经历都如实地反映在了其代表作《沉沦》中。我上学的时候一眼发现“变态性心理”这个有歧义的词组,和同学玩笑了半天,因此记忆犹新。( 回到文中
  2. 张春霞,郝天永。“汉语自动分词的研究现状与困难”。系统仿真学报 Vol. 17 No. 1 Jan. 2005。( 回到文中

  1. Bii @ 2009-06-14 03:35:43 +0800:

    請問可否分享修改後的檔案 ?

  2. 丁宇 @ 2009-06-18 05:27:14 +0800:

    @Bii 已经邮件发给你了。 [emoticon:clin_oeil]

  3. liupeng @ 2009-07-16 09:01:26 +0800:

    好像我改后不行,因为文件的编码我看到是unix下的ASC编码,而你添加的是utf编码,是不是要写一个PHP header,然后把文件的编码改成UTF-8呢?你有没有单独的B8改好了的?我想看看...谢谢

  4. JeremyWei @ 2009-07-30 22:03:34 +0800:

    麻烦分享下修改过的代码,谢谢。