hanlp训练一元、二元语法模型


所谓一元语法模型,就是统计单词在语料库中出现的频数。
二元语法模型,就是连续的两个单词在语料库中出现的频数啦!

在汉语言处理中,要训练一元、二元语法模型,所使用的语料库必须是经过单词拆分后的句子哦。

二元语法模型的训练

下面,我们将使用微软提供的数据集 MSR ,训练一个一元、二元语法模型,代码如下:

rom pyhanlp import *
NatureDictionaryMaker = SafeJClass('com.hankcs.hanlp.corpus.dictionary.NatureDictionaryMaker')
CorpusLoader = SafeJClass('com.hankcs.hanlp.corpus.document.CorpusLoader')

corpus_path = r'E:\Anaconda3\Lib\site-packages\pyhanlp\static\data\test\icwb2-data\training\msr_training.utf8'    #数据集所在路径。可用txt文件
model_path = r'D:\桌面\比赛\msr_model'    #模型保留路径
def train_bigram(corpus_path, model_path):
    sents = CorpusLoader.convert2SentenceList(corpus_path)    #读取语料库(数据集)
    for sent in sents:
        for word in sent:
            if word.label is None:
                word.setLabel("n")
    maker = NatureDictionaryMaker()    #模型生成器(字典生成器)
    maker.compute(sents)    #训练一元语法和二元语法模型
    maker.saveTxtTo(model_path)  # 保存模型到'D:\桌面\比赛\msr_model' 中
    ```
    
    运行上述代码(需要等待相当一段时间),可以从模型路径中得到以下三个文件:  
![运行结果图](https://img-blog.csdnimg.cn/20200502145745388.png)
我们打开 msr_model.ngram(二元语法),可以看到模型:
![二元语法模型展示图](https://img-blog.csdnimg.cn/20200502145900221.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjE0MTM5MA==,size_16,color_FFFFFF,t_70)##使用二元语法模型进行分词

在使用上述模型拆分单词的时候,往往将目标句子与语法模型对应起来,构成一个**词网**进而对应一个词图(有向图,每个节点代码模型中的单词)。根据节点间的距离,按照维特比算法,或Dijstik算法,找到最合理的分词手段。

为了进行分词,首先我们需要将模型加载到 HanLP.Config.CoreDictionaryPath 中。若是用二元语法来分词,则需要将模型加载到 BiGramDictionaryPath 中:
```python
ViterbiSegment = JClass('com.hankcs.hanlp.seg.Viterbi.ViterbiSegment')
DijkstraSegment = JClass('com.hankcs.hanlp.seg.Dijkstra.DijkstraSegment')
CoreDictionary = LazyLoadingJClass('com.hankcs.hanlp.dictionary.CoreDictionary')
CoreBiGramTableDictionary = SafeJClass('com.hankcs.hanlp.dictionary.CoreBiGramTableDictionary')

def load_bigram(model_path):
    HanLP.Config.CoreDictionaryPath = model_path + ".txt"  # 加载一元语法模型
    HanLP.Config.BiGramDictionaryPath = model_path + ".ngram.txt"  # 加载二元语法模型
    
    # 以下部分为兼容新标注集,不感兴趣可以跳过
    HanLP.Config.CoreDictionaryTransformMatrixDictionaryPath = model_path + ".tr.txt"  # 词性转移矩阵,分词时可忽略
    if model_path != msr_model:
        with open(HanLP.Config.CoreDictionaryTransformMatrixDictionaryPath, encoding='utf-8') as src:
            for tag in src.readline().strip().split(',')[1:]:
                Nature.create(tag)

根据需要,可以分别使用维特比算法Dijkstra算法,来生成汉语分词模型,代码如下:

segment_1 = ViterbiSegment()    #使用维特比算法,字典已经在HanLP的Config中设置过了。
segment_1.enableAllNamedEntityRecognize(False)    #开启命名实体识别
segment_1.enableCustomDictionary(False)     #不挂载用户词典

segment_2 = DijkstraSegment()
segment_2.enableAllNamedEntityRecognize(False)
segment_2.enableCustomDictionary(False)

当然,也可以在生成模型的同时,直接加载词典。并通过 seg 接口,来实现单词的拆分:

a = ViterbiSegment(model_path + ".ngram.txt")
print(a.seg('我爱你'))

与用户词典的集成

一元语法模型、二元语法模型的分词比起字典分词,虽然有其优点。但对于网络新词,未录入词(OOV)的拆分仍乏善可陈。因此,能否集成字典与语法模型,来进行分词呢?HanLP 实现了这一点

集成用户词典有两种方式:

  • 其1为低优先级,即首先在不考虑用户词典的情况下,由语法模型分词。最后根据用户词典,将结果再次合并。
  • 其2为高优先级,其首先考虑用户词典,但具体实现由语法模型自行决定。

两种集成方法如下所示:

from pyhanlp import *

ViterbiSegment = SafeJClass('com.hankcs.hanlp.seg.Viterbi.ViterbiSegment')
#一下内容参考何晗老师的新书《自然语言处理入门》
segment = ViterbiSegment()    
sentence = "社会摇摆简称社会摇"
segment.enableCustomDictionary(False)
print("不挂载词典:", segment.seg(sentence))
CustomDictionary.insert("社会摇", "nz 100")
segment.enableCustomDictionary(True)
print("低优先级词典:", segment.seg(sentence))
segment.enableCustomDictionaryForcing(True)
print("高优先级词典:", segment.seg(sentence))

猜你喜欢

转载自blog.csdn.net/weixin_42141390/article/details/105890511