ICTCLAS代码学习笔记之CsegGraph类

来源:互联网 发布:深度触网 知乎 编辑:程序博客网 时间:2024/06/05 19:57
CsegGraph类的相关笔记,这个类为词图类,主要是词的有向图。提供两个核心函数,一个是原子切分,一个是生成词图。为了保存相关的信息,有三个成员变量m_sAtom,m_nAtomLength和m_nAtomPOS分别存储句中的词(字符串)、每个词的长度(字符串长度)及该词的词性。由于都是预定义大小的buffer,因此还需要一个无符号整型变量m_nAtomCount来记录切分后词的个数。另外,在粗分时可能产生的多个切分结果存储在一个动态数组CdynamicArray类的对象m_segGraph中。
这里的三个成员变量都是预定义大小的buffer。句子长度不超过2000个字符,而且词长不超过200。如果改用vector来存储则可以避免这种预定义在某些极端情况下造成访问越界的情况。可以考虑用一个vecotr<struct{}>来存储,其中结构体只需要两个变量,一个是string类型的词串,一个是其词性
nPOS,而原来需要的词长这个属性string本身就可以提供了。
词图要求为行优先存储。原子切分这个环节,原始的版本判断比较简单,将句子起始符号和结束符号当作一个整体切开,如果读入的类型是汉字(CT_CHINESE)、索引(CT_INDEX)、分割符(CT_DELIMITER)或者其他(CT_OTHER)则切开成一个单独的结点。否则(就是数字、单字节字符或者字母),如果类型相同则连在一起,否则就切开成单独的原子结点。将这些粗分好的结果分别存入三个成员变量中,而词性一行的值就直接为charType函数返回的结果,只是一个初步的判断。目前版本的函数中只会重置m_sAtom和m_nAtomLength而m_nAtomPOS在结束位没有相应置空,目前不会引起bug。
需要说明的是,原子切分这个环节,对于由汉字组成的数词串都切开了而在后面并不一定都能很好的合起来,一方面是概率竞争不过一方面是判断数词串的函数有不全面的部分。另外,由于我修改的版本引入了两个新的类型,因此在原子切分时需要特别处理一下。
GenerateWordNet函数根据核心词典将原始的句子生成词图并存储在m_segGraph中。首先会将句子进行原子切分,然后利用词典中的词及词性词频信息来置相应的权重值。第三个参数bOriginalFreq的默认取值为flase,当这个值为false时为非原始的频率值,一般采用默认值最大的或者0来设置,具体规则见后。如果为true则是利用词典中获取的频率值来做相应的设置。
对于粗切好的每个原子结点,在非原始频率的情况下,如果类型为汉字,则设置词图,其value值取log最大频率,词性为0即未知状态,词本身也不需要存储;如果为其他类型,则需要额外判断一下是不是一些特别的类型,比如说CT_INDEX、CT_NUM和CT_SINGLE_NUM都被判断为未处理数,设置相应的词性-27904及value值(0),分割符为30464而value值为最大频率等,不一一列举。value值为0而词性为修改后结果。
第二步词图生成是根据已有的词典,会有一个规则是不要把“月”和“份”切开,这个不太合时宜,呵呵。然后对于粗分后的每个词,如果在词典中找到最大匹配,则需要重新估算其频率值,同样的有一个对于组合数词的判断。如果生成的结果只有一个词性则更新value值时同时置这个明确的词性,否则只更新value。这一步是个最大匹配的过程,而且每个匹配的中间部分都会被记录下来。(粗分结果),在其中还会有一个关于时间词串的扩展规则,也不太合时时宜,主要是针对类似“1年内、1999年末”这种词,将末尾的诸如“末内中底前间初”的词处理一下。
词图类CSegGraph的总结:
根据论文,这是第五层和第四层、第三层的HMM过程,非常重要,是后续工作的基础。针对数词串的处理还不够完美,考虑是换个地方处理还是重新完善一下规则。
原创粉丝点击