SegWord 的进展--词库结构

 词库结构:关于trie和hash的问题

   看到词库的研究发展已到了一定的水平,感到很高兴.在网上看到了几个帖子,是关于词库结构的讨论,我个人觉得很有意思,进一步研究,有可能取得不错的成果,现将原帖及其讨论转载如下:

percylee的原帖:

目前对于词库结构的建立,一种普遍的倾向是使用trie结构,该结构使得对词库中词语的访问速度和词库规模无关(若词语的长度为n,则查询该词语的复杂度为O(­n);和词库规模m无关).而且,若双向建立,则机械分词的正向和逆向最大匹配都是极容易实现而且复杂度较低的.

如果这种trie结构不使用链式结构,而是使用堆(数组)内建立,则词库在导入的时候不需要重建,速度非常的快.

由于这些原因,计算所,清华大学以及我们单位都提到或正在使用这样的词库结构.例如我们单位,原词库结构就是堆式trie结构,前一段时间我写它的归并算法,有­如下一个简单的测试输出:

index1.string:  lee lieve life and zoe
index2.string:  love book zero a land
index3 = index1 + index2

***************index1***************

WordIndex:
a       [0,1)
l       [2,4)
z       [10,11)

HeapIndex:
0       n       0       [1,2)
1       d       -1      [0,0)
2       e       0       [4,5)
3       i       0       [5,7)
4       e       -1      [0,0)
5       e       0       [7,8)
6       f       0       [9,10)
7       v       0       [8,9)
8       e       -1      [0,0)
9       e       -1      [0,0)
10      o       0       [11,12)
11      e       -1      [0,0)

***************index2***************

WordIndex:
a                       1ch_word
b       [0,1)
l       [3,5)
z       [9,10)

HeapIndex:
0       o       0       [1,2)
1       o       0       [2,3)
2       k       -1      [0,0)
3       a       0       [5,6)
4       o       0       [7,8)
5       n       0       [6,7)
6       d       -1      [0,0)
7       v       0       [8,9)
8       e       -1      [0,0)
9       e       0       [10,11)
10      r       0       [11,12)
11      o       -1      [0,0)

***************index3***************

WordIndex:
a       [0,1)           1ch_word
b       [2,3)
l       [5,9)
z       [19,21)

HeapIndex:
0       n       0       [1,2)
1       d       -1      [0,0)
2       o       0       [3,4)
3       o       0       [4,5)
4       k       -1      [0,0)
5       a       0       [9,10)
6       e       0       [11,12)
7       i       0       [12,14)
8       o       0       [17,18)
9       n       0       [10,11)
10      d       -1      [0,0)
11      e       -1      [0,0)
12      e       0       [14,15)
13      f       0       [16,17)
14      v       0       [15,16)
15      e       -1      [0,0)
16      e       -1      [0,0)
17      v       0       [18,19)
18      e       -1      [0,0)
19      e       0       [21,22)
20      o       0       [23,24)
21      r       0       [22,23)
22      o       -1      [0,0)
23      e       -1      [0,0)

Press any key to continue

虽然有这样的特点,但如果对此种结构的数据做动态调整,比如添加,删除或归并,即对于动态词库的需求而言,则效率是很值得考虑的.

通常,一个好的hash算法,对于词语的查询也是和词库规模无关的,而且,若算法足够的好,其时间效率与trie结构查询应该差不多:).同时,对于动态词库,­hash结构是更容易做调整的.添加删除的效率应该能满足动态词库的需求;当然,这也只是一个良好的设想.
    问题是,hash运算对于串的毗邻运算不满足分配率,即

               hash(str1 + str2) != hash(str1) + hash(str2)

那么,对于机械分词的最大匹配算法,应该如何在hash词库上进行实现呢?另外还有一些特殊的需求,我们也遇到过,即对于词汇的通配符查询,例如查
"中*人",则'中'和'人'之间可以有任意多个字符,此种需求又该如何做呢?

我们做词库的结构,应该说着重要考虑的是查询效率,动态调整需求;在保证这些的前提下,再考虑该结构的计算普适性:).

 

偶和li yuan的讨论,给大家做参考:)
---------------------------------------------------------------------------­-----------------------------------------
li($)yuan {节食} 说:
恩, 我看过了, 呵呵, tire结构很适合search的, 但空间有时候需求很大
水天一色 说:
静态检索trie的确很合适
li($)yuan {节食} 说:
对, 这种结构很好的,我以前看过很多这种搜索结构的东西, 比如AC就是其中的一种,以及相关很多变种,DAWG等
li($)yuan {节食} 说:
日本一个教授提出用Double-array来实现这种很类似tire的结构
水天一色 说:
哦,有没有对动态词库进行搜索的相关讨论,~~~
水天一色 说:
double-array好象在一个资料上看到过
li($)yuan {节食} 说:
动态词库? 你指的是哪些方面的?
水天一色 说:
我指的是检索的结构随时都可能发生调整,类似于这种需求
li($)yuan {节食} 说:
动态检索树 rbtree avl这些在实际的应用中效果不算太好,因为new 操作会开销很大
水天一色 说:
所以这个结构在添加,删除以及移动等操作也要有良好的表现
li($)yuan {节食} 说:
其实我认为你们的分词的这种词库 不适合用动态的来搞 因为词库本身不可能是经常变化, 或者可以定期制作,采用固定的存储很合适, 一旦涉及到动态出入, 那么就有开销了,或者你可以将一个基本已固定的词库做成静态的,然后一小部分新的做成动态
水天一色 说:
这个问题我也在考虑,因为词库虽然有很多东西需要调整,但基本的词形(key)可能是一个具有稳定内容的东西,或者,有一个稳定的内核
li($)yuan {节食} 说:
你有没有看过foxmail的antispam的文件夹里有一个词库的,他里面存储的形式就是单个词, 那么它在初始化的时候不管用hash表 还是tire 肯定会很大开销的
水天一色 说:
不过刚开始是想,是否有一个结构能够满足整体调整的需求,而不必考虑这个结构是否要做成一个复合结构(有些调整,有些不调整,以及调整与不调整部分是否有交流机­制等等),

你是说词库load时开销很大是吗
水天一色 说:
若结构需要重建的话,load时无可避免需要这部分时间与空间消耗

li($)yuan {节食} 说:
分词的词库,相对来说会有一个基本的很大一部分词可以一次性做成一个表的, 那么其实你可以把它做成特殊的静态表, 那么在初始化的时候copy、就可以了, 这样查找的效率是非常高的, 以后有新词加入, 那么做一个工具可以生成这种表
水天一色 说:
这对于一般的分词思路是足够的,可是现在我们想做的是,你把词语知识库load以后,经过分词---你的词语知识是已经发生改变了的,可能是增加了意义描述,也­可能是增加了部分关联,也可能删除了一些东西;若把分词看成学习程序,则分词本身会影响你所依据的知识,即词表那些东西
li($)yuan {节食} 说:
什么意思? 我有点不太明白, 你的意思是你将一篇文章切词后,每个词要构建成像语法树的那种形式吗?
水天一色 说:
不是,是分词过程也是学习过程,可以影响词表及其知识表示内容

水天一色 说:
这一个对于用户来讲可以是透明的,他所能感觉到的,是这个程序越运行越好用,
li($)yuan {节食} 说:
你想给词计一个使用频率?
水天一色 说:
不光是使用频率,词语的知识表示曾在 知识表达体系
那个调研中做了部分考察
水天一色 说:
原则上讲是词汇的语言知识以及世界知识的综合
li($)yuan {节食} 说:
欧,那这种估计就要动态调整了, 现在的输入法里有一种简单的学习功能就是动态将你经常使用的词根据使用频率动态调整靠近树的根部, 这样明显提高查找速度,但其实如果像输入法的这种方式也可以额外建一个表来记录使用情况, 那么这个就相当于一个cache机制了
水天一色 说:
基于这样一个考虑所以想找这样一个结构,仅对于中文词库而非一个通用领域;不过若最终发现是难以实现的,则估计还要考虑设计为一个复合结构,有静有动
水天一色 说:
恩,输入法那个调整估计不影响词表结构
li($)yuan {节食} 说:
欧, 开始实现的时候不要考虑那么复杂嘛, 会影响的
水天一色 说:
哦,我猜想他那个是把所有相关词形load进行成为一个局部结构,局部结构随时都要排序以调整表现,但对于大词表是没有影响的吧?
水天一色 说:

是啊,或许开始的时候不要想这么复杂;不过这也算这个项目的出发点了.若是一般的来做,做一个可用的东西,就比较快了
li($)yuan {节食} 说:
其实这种输入法的简单模型就是, 树的节点带有一个频率计数, 然后每次根据频率计数调整节点,频率越大越靠近根节点
li($)yuan {节食} 说:
其实最好的做法是,先实现出来一个简单的,然后再在这个基础上做最大的优化
水天一色 说:
 对于工程项目的确需要如此
li($)yuan {节食} 说:
因为开始的时候的复杂化导致后期很难调整, 不如开始简单化等大体框架已定再去改某个小部分
好 恩
水天一色 说:
不过科研类型的项目一般都是瞄着某个(些)问题去的
一般都是根据问题探索方案,而不选择一个通用方案快速实现一个结果---因为这样的结果早已经被多次得到了
li($)yuan {节食} 说:

水天一色 说:

我们这边常因为把工程问题科学化被总经理骂,公司和研究院不一样啊
li($)yuan {节食} 说:

水天一色 说:
偶把谈话放group了,给大家一些思路
怎么样?
li($)yuan {节食} 说:
也好, 不过我对分词这些只了解一点, 有很多你说出的术语我也不太清楚, 呵呵
水天一色 说:
不过你对各种检索结构很熟
水天一色 说:
真希望你在北京啊,那我们就能聚会了
li($)yuan {节食} 说:
恩 我们这的主要的核心算法就这么点检索的东西
li($)yuan {节食} 说:
是啊, 我以后会去北京的, 但还不能确定什么时候 呵呵
水天一色 说:
 好啊,下次你来的时候通知偶,请你吃饭
li($)yuan {节食} 说:
  好 有机会一定去!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值