海量分词方法揭密 — 思考和计算的大狗

(献给当年我们一起废寝忘食同事们的,绝大多数还在,都成了海量的中层高层干部,怀念一下那段令人难忘的日子)

海量分词方法揭密之前言:97年初生牛犊不惧虎,想把情报分析和二级市场投资结合起来,但不想和那帮拍脑门抖机灵的股评家们同流,读书时老师讲过几个案例很有启发:

中情局当年预测勃列日涅夫上台使用的是文本分析的方法,中情局一位年轻特工使用公开资料,拼接出原子弹的全部资料。在投资实践中,也赚了。

六度空间,情报数学杨晓书老师第一讲就是六度空间,主要意思是天底下投有你不能认识的人,没有你不能获得的情报,情报不是谍报,谍报的时代很快会过去,情报的辉煌指日可待。靖继鹏教授情报学第一课也重申了这个意思,向我的授业老师们致敬。

情报分析的圣殿兰德公司,一切不以海量数据分析为基础的情报分析都是耍流氓,当时是这么认为的。情报过程很简单,定题、采集、传递、证认、分析、报告、管理,其他都好解决就是建库和搜索比较麻烦,但咱专业学过情报,检索、倒排、菊池法都学过。

开始没想自己做,不是有数据库吗?一用不灵,没有这功能,而且当时的sqlserver还有编码问题,开始琢磨怎么办呢?此时一个操盘的机会来了,一个朋友在上家证券公司认识的,当时刚做完大连基金,不知道有没有人知道,大连基金被炒飞了,从一元多做到几元,这样 带着疑惑到了海南。

海南是个文化的沙模,报纸上居然有错别字,把情报分析用于股票投资的机会正合适,边分析边实践,没事写个小程序,连续五年看盘,经验积累了不少,果断在亚洲金融危机前一周离场,三亚吃角虾红花蟹去了。

回天津后,只想做情报研究所,不想再工作,便白天炒股,一早一晚带儿子,晚上在阁楼上和作职写程序。到凌晨,早上作职乘班车上班,我继续贡献交易量。真正有触动的高同学的教科书,上面赫然写到中文分词是中文信息处理的瓶颈,二十多年投有解决的世界性难题。

分词确实挺难的,试过很多种方法,都不成,但那时我没想用词典,觉得用词典靠不住,也没有地方查资料,99年家里装了互联网才查到几个名字和分词相关:刘开瑛,黄昌宁,王永成,孙茂松,只有简单的介绍,没有论文资料。

分词尝试方法之一:结晶法,在没有词典的情况切分是不好下刀的。一次给儿子调奶粉(三鹿)突然想起物理中的结晶是从某个点开始,那分词如果能找到第一结晶点不就找到第一切分的点了,只要能切除第一个词,就能切除第二个第三个,果然,熬了个通宵,第一个同形串产生,分出不少词来,很高兴。

结晶法的问题:123,就不细说了。这次实践留下了一个同形串,后来命名为内部词典分析器。

再次陷入迷茫中,分出的词忽长忽短,没法用啊,当时的daydream是中文从字符到语义,分词是关键,解决不了,情报的事最多是在本土完儿,中文的信息情报知识流转将大幅落后,现在想来就是这些白日梦把我拉离了证券,拉离了情报,渐渐被自己营造的使命感催眠。

双向扫描,最大匹配法,在后来的六个月里,逐渐摸索出,正向或单纯的逆向都有部分交叉歧义不能解决,用最大匹配效果要好,整理出了1000多个常用词。

分词规范,后来作职不知怎么找到的,忘了。我们当时觉得有点沮丧,原来细节n多,太坑爹了。但我个人的韧性很强,不属于那种不撞南墙不回头的主,而是属于要把南墙撞穿的主,主要的得益于家乡彪悍的民风,淑华把我们称为静海国人。

突破性进展,内心中总想找个统一的方法来解决所有问题,99年10月的一个晚上,作职有事没来,我12点多眯在沙发上看电视,正好前教育部副部长韦钰讲中国科学家如何使用自己的方法进行基因测序,利用基因功能和结构对的特性,堆砌,校验,整体求优。这不和分词遇到的问题一样吗。词形也要对应词用。

砌词与求优后来成了海量分词的核心方法,当时我还取了个很虾的名,无缝指数。做股票的后遗症。

未登录词问题,未登录词是分词种中最复杂的问题之首,早期的研究都在歧义上下功夫,交叉歧义和组合歧义,也分伪歧义和真歧义,我个人认为孙茂松老师对伪歧义的研究价值最高,歧义占比不大。

未登录词涉及面太广,只能逐个击破,海量的次序如下,中国汉族人名,欧美译名,其他译名,日本人名,中国少数民族人名。解决人名问题基础还是比较扎实,当时买了一个数据库600W企业名录,有法人,公司名,地址,中国的事一并全解决了。

但是国外的译名是个大麻烦,这里采用了一个新维度:音标。语言先有音后有文字,我的二外是德语,对德语的音有很深的印象,形音一致,还有饶舌音,找到这个方法就等于找到了西文汉译的奥秘,果然很完美的解决,海量词典除了五个领袖外,没有其他任何人名,每次和人PK是挑新浪体育。

未登录词光有内部结构是远远不行滴,还需要构造外部语境,当时解决这部分东胜、小宋功劳大大,这时经常会遇到数据稀疏问题,又造了个新词,语义等价体,现在应该叫实体等价体,在同样使用人民日报6个月数据做训练和分析,结果进步很大。

02年在Intel中国研究中心一个日本东京大学教授和一位富士通的研究员也遇到未登录词识别构建统计学模型时数据稀疏问题,我讲了该方法后两人狂记,等轮到我问他们时,一句都不说,搞得周博士很郁闷,后来我再不和日本人交流,08年韩国人来访,我就装傻,回来给支到其他公司那去了。

再次提升扫描算法,裂变扫描:分词无论正向还是逆向,双向,当时的评测样本中都有2%的句子错误,正好这时有个项目要Unix版,迁移的话时间来不及,用户急等着用,准确率可以先低一些。当时我自己先用VB写了一版,基于裂变的快速剪枝的算法,方案总数比双向扫描还少了34%,正确方案的召回率终于到了99.8%。

然后一个小伙子用c++翻写,三周时间,准确率97.8%;后来东胜用汇编把底层效率低的代码优化了,基于芯片的字节序又优化了一遍,现在一直在用,我人生最大的幸运就是当时遇到东胜。后来小伙子很得意分词不难吗,但是接下来的数量词和重叠词,几乎要了他的命,发誓再也不做分词了。

前后缀问题,中文是够复杂的,一波刚平一波又起。日本人名的遗憾,本来是可以更上层楼,我当时还看了不少日本小说,但是实在找不到懂日语讲讲构词法和句法,日后有哪位有兴趣把这块补上。

重构,堆了太多东西,看着就不爽。记得看报纸读到中国科学家如何研究神经毒气的解毒剂的,好像是沙林,据说比芥子气难解,用了复方的方法,解决了。这时候我觉得对分词中的各种问题都基本摸了一遍(埋下伏笔还有几劫)准确率在人民日报语料上99.7%,开放语料99.1%,对外时报为了保险起见还故意低报了一些。

后来有人说用同样的语料测过,没那么高,但是说这话的人没有认真研究过该语料,这份语料分六个月,有一个月准确率奇低,而且自身错误千分之大几,前后不一致处也有千份之几,我是用了五审五校的方法重新修正的语料。是买的价格的十倍不止。

重构,如果我把分词的几个难题分解,每处都用几个不同源的方法,最后变成一个求优问题不就行了吗,结果是可想而知地,调优时复杂度比原先高了很多。但总算成了。

实战第一劫,自定义词典问题,在闷头做的时候没想到,几乎是场噩梦,自定义词典要支持增删改查,支持实时reload,打乱了原来的扫描模式,交叉歧义激增,几乎重新翻写。

实战第二劫,可进化性不强,这时我遇到了一位高人,南开大学机器智能研究所所长王庆人教授,当时他己经移居美国,他给我讲了他们是如何保护ocr的知识产权的,模式训练机与应用机分离,知识与算法分离。这提醒了我知识与算法分离重构,所以现在有专人训练海量分词的母机,程序不改,但准确率还能提升。

实战第三劫,分词不一致问题,初期的分词主要用于检索,但是创建索引时分的是整篇文章,在检素框里是短串,语境不一致,分词,分词颗粒度与面向应用的规范,多方案输出。最后都搞定。

第四劫,天雷劫。到市场上没人知道分词为何物?有什么用处?南开的一位院长断言,毫无价值。

海量云分词概述

海量云分词是由海量信息技术有限公司提供的免费的在线中文分词云计算服务。

何为分词? 中文分词与其他的分词又有什么不同呢?

分词就是将连续的字序列按照一定的规范重新组合成词序列的过程. 我们知道, 在英文的行文中, 单词之间是以空格作为自然分界符的, 而中文只是字、句和段可以通过明显的分界符来简单划界, 唯独词没有一个形式上的分界符, 虽然英文也同样存在短语的划分问题, 但是在词这一层上, 中文比之英文要复杂的多、困难的多。

海量云分词的应用领域:

在所有需要计算机对中文文字信息进行进一步分析处理的领域均能应用分词技术, 如: 信息检索、信息挖掘、自动分类、自动聚类、自动校对、机器翻译、语音识别与合成等人工智能领域。

免费申请海量云分词服务:

只需关注 @海量云分词服务 官方微博,并通过私信索取账号即可免费使用。

海量云分词主要提供以下功能:

1. 中文分词

支持对输出颗粒的控制,可以输出普通颗粒与用于检索的小颗粒;同时输出词串所在句号、段号、词号、词性等信息。

关于分词输出颗粒,我们认为各种应用对分词要求的颗粒度是不同的. 比如自动分类、关键词抽取比搜索需要的分词颗粒度要大, 因为这样表示文本语义特征时效果会更好, 而检索有一个查全率的要求, 就需要把分词单位做的更为细致, 不然就会造成漏查。

海量系统现在提供了两种颗粒的规则, 其中, 默认的为大颗粒接口, 主要用于自动分类、信息挖潜、机器翻译、语音合成、人工智能等领域, 用于提升信息分析的有效性和准确性; 另外一种应用为小颗粒度分词也叫检索优化分词接口, 用于信息检索领域, 用于提升查全率。

例如:

对"中华人民共和国"进行分词:

大颗粒度分词(默认方式)结果为: 中华人民共和国

小颗粒度分词(检索优化)结果为: 中华 人民 共和 国

2. 词性标注 :

可提供基于北大语料的30种词性辨识、输出。

API接口使用说明

海量云分词提供了基于REST协议的API,其请求URL地址为:

http://freeapi.hylanda.com/rest/se/segment/realtime

此接口地址提供了全部的分词技术相关功能,具体功能模块的调用控制,均在参数xmlparam中实现。

API调用示意图:

参数表:

另:除上述参数外,还需从 @海量云分词服务 微博申请获得私钥,方可正常使用各API接口。

xmlparam参数说明

输入XML格式

云分词所要处理信息的输入,计算相关参数的设置,均由API参数xmlparam中的XML来控制。

输入XML格式参见下图:

注意:上图中XML标签名称 均 大小写敏感!

Input

Input标签内表示是待处理信息的各字段信息,Property 标签的Name属性为字段名,Property 标签间的值为字段内容

通常,待处理信息至少包含一个正文字段(名称可以为Content),也可以包含标题(Title)。

ProcessList

ProcessList 表示本次调用采用的计算处理模块列表(当前仅有云分词模块),Template属性表示可以直接使用在服务端预设的某个模板(可忽略)。

内含的多个Resource 标签,每一个Resource 表示一个计算模块(当前仅有云分词模块)。

Resource

Resource标签中,ID属性为对一个处理模块的唯一编号,不可与其他模块重复;

Adapter属性表示所使用模块的名称(参见各模块说明);

OutputXml属性表示当前模块的计算结果是否输出到结果xml中,true表示输出,false表示不输出;

IgnoreFailed属性表示当前模块计算识别,是否忽略此失败,继续后续的计算,默认为true;

Resource标签内的Param 子标签,表示当前模块的控制参数,其中Name属性为参数名,Value属性为参数值(详情参见云分词模块参数说明)

示例

云分词模块调用,xmlparam参数XML输入示例:

输入XML格式示例:

云分词模块名称为:DA_HLSegment
1. 参数

Input:输入待分词处理的原文字段名称,如Title,Content
Output:输出结果的名称,可以任意命名,如:HLSegment_Result;
CustomCalcSign:定制计算标志,此参数不填写则为默认,直接填写下面的字符串,多个用半角逗号分隔:
POS_TAG 表示分词后对结果进行词性标注;
OPT_SEARCH 表示分词结果按检索优化输出,检索优化后分词颗粒会变小,如三字的中文人名“张小四”会切分为两个词“张” “小四”
OutputFieldSign:分词结果其他附加信息是否输出控制参数,直接填写下面的字符串,多个用半角逗号分隔:
StartOffset 输出每个分词结果偏移开始位置
EndOffset 输出每个分词结果偏移的结束位置
ExtSign 输出每个分词结果的词性标志

2. 输出说明

Annotations/Item 中的 ExtSign属性表示一个词的词性标记,是一个32位数,用标志位来表示,需用位的与运算来判断;

词性标志位宏定义如下:

//共30种词性
#define NATURE_D_A 0x40000000 // 形容词 形语素
#define NATURE_D_B 0x20000000 // 区别词 区别语素
#define NATURE_D_C 0x10000000 // 连词 连语素
#define NATURE_D_D 0x08000000 // 副词 副语素
#define NATURE_D_E 0x04000000 // 产品词
#define NATURE_D_F 0x02000000 // 方位词 方位语素
#define NATURE_D_I 0x01000000 // 成语
#define NATURE_D_L 0x00800000 // 习语
#define NATURE_A_M 0x00400000 // 数词 数语素
#define NATURE_D_MQ 0x00200000 // 数量词
#define NATURE_D_N 0x00100000 // 名词 名语素
#define NATURE_D_O 0x00080000 // 拟声词
#define NATURE_D_P 0x00040000 // 介词
#define NATURE_A_Q 0x00020000 // 量词 量语素
#define NATURE_D_R 0x00010000 // 代词 代语素
#define NATURE_D_S 0x00008000 // 处所词
#define NATURE_D_T 0x00004000 // 时间词
#define NATURE_D_U 0x00002000 // 助词 助语素
#define NATURE_D_V 0x00001000 // 动词 动语素
#define NATURE_D_W 0x00000800 // 标点符号
#define NATURE_D_X 0x00000400 // 非语素字
#define NATURE_D_Y 0x00000200 // 语气词 语气语素
#define NATURE_D_Z 0x00000100 // 状态词
#define NATURE_A_NR 0x00000080 // 人名
#define NATURE_A_NS 0x00000040 // 地名
#define NATURE_A_NT 0x00000020 // 机构团体
#define NATURE_A_NX 0x00000010 // 外文字符
#define NATURE_A_NZ 0x00000008 // 其他专名
#define NATURE_D_H 0x00000004 // 前接成分
#define NATURE_D_K 0x00000002 // 后接成分

附:一段简单判别词性的JAVA代码

String strExtSign = new String("从Item的ExtSign属性获得的数字串");
int nPOS = Integer.parseInt(strExtSign);
int NATURE_D_A = 0x40000000;

if((nPOS & NATURE_D_A) == NATURE_D_A)
{//判断成功,则当前词性 包含"形容词"
//To Do...
}

1. 返回XML格式说明

返回XML分为两种,一种是处理失败返回错误信息,一种是语义计算结果的返回信息;

错误信息XML,较为易懂,暂不深入说明。

语义计算结果返回信息,XML格式参见下图:

ret
ret内的值表示服务返回值,0表示成功,其他表示错误号。 msg
msg内的值表示服务返回的错误信息串,成功时为空。 Resource
Resource 标签内表示一个处理模块的全部处理结果信息;AnalyzeResult 标签内表示某个处理模块的一个原始输入字段的全部处理结果信息; Resource 和 AnalyzeResult 均可以并列存在多个。 Annotations
Annotations是表示对一个内容字段的信息标引结果,通常这样的标引结果均有在原文中的起始与结束下标;下面可以包含多个Item,每一个Item表示一个标引结果。 Item中的属性含义分别如下:
StartOffset表示一个标引结果在原文中的起始偏移(为UNICODE字符偏移);
EndOffset表示一个标引结果在原文中的结束偏移(为UNICODE字符偏移);
ExtSign表示一个标引结果的扩展标志,参见各模块说明;
Text表示一个标引结果在原文中的原始字符串;

客户端软件包及样例代码下载

点击下载JAVA调用样例代码压缩包。

点击下载PHP调用样例代码压缩包。