hanlp2.0使用自定义词典结合模型使用,分词效果反而变差

本人在使用pipeline方式融合一些自定义词语后,发现当自定义词典语料过多时,即语料复杂,出现分词结果变差。例如:正要打牌九。当自定义词典有"要"、“打牌"等词,如果先通过自定义词典去分词,就会分出"要”、"打牌"等词,再通过模型进行分词,分出来的就是【“正”,“要”、“打牌”、“九”】,这样就没有达到预期的效果。请问类似这样的问题,我应该怎么处理呢。希望大家能提供一些更好的建议。谢谢!

1 Like

这里应该是还存在一个bug,Trie类的parse_longest函数。例:“密码设置"进行分词,假设自定义词库含有"密码”、"码"两个词,parse_longest会分出[“密码”, “码”, “设置”],这不是预期的效果,应该是[“密码”, “设置”]。

自定义的词典里应该也有“牌九”这个词语吧 没有的话可以手动加一下

当自定义词典有"牌九"这个词时,效果是【“正”,“要”、“打牌”、“牌九”】,这不是预期的。正确应该是【“正要”、“打”、“牌九”】。

你这是全搜索模式吧 相当于用ac算法扫描了一次“正要打牌九”中含有的词典词汇
看看哪里能切换一个模式的

我用jieba来做说明的话 cut_all开关打开的话就会出现你的这个结果

hanlp没有类似的开关,其本身是更灵活,需要自己去实现。

已经修复:

好的,谢谢何博士。但是我还是有个疑问,例如,自定义词库只有"码"这一个字,没有"密码"这一词,结果就是【“密”, “码”, “设置”】了,之前你们的例子在自定义词库与模型结合使用是行不通的。你觉得呢?

不太明白你的意思,请仿照这个例子把你的问题复现出来

- - coding:utf-8 - -

Author: hankcs

Date: 2019-12-28 21:25

from hanlp.common.trie import Trie

import hanlp

tokenizer = hanlp.load(‘PKU_NAME_MERGED_SIX_MONTHS_CONVSEG’)

text = ‘密码设置’

trie = Trie()

trie.update({‘码’})

def split_sents(text: str, trie: Trie):

    words = trie.parse_longest(text)

    sents = []

    pre_start = 0

    offsets = [] 

    for word, value, start, end in words:

        if pre_start != start:

            sents.append(text[pre_start: start])

            offsets.append(pre_start)

        pre_start = end

    if pre_start != len(text):

        sents.append(text[pre_start:])

        offsets.append(pre_start)

    return sents, offsets, words

def merge_parts(parts, offsets, words):

    items = [(i, p) for (i, p) in zip(offsets, parts)]

    items += [(start, [word]) for (word, value, start, end) in words]

    # In case you need the tag, use the following line instead

    # items += [(start, [(word, value)]) for (word, value, start, end) in words]

    return [each for x in sorted(items) for each in x[1]]

tokenizer = hanlp.pipeline() \

    .append(split_sents, output_key=(‘parts’, ‘offsets’, ‘words’), trie=trie) \

    .append(tokenizer, input_key=‘parts’, output_key=‘tokens’) \

    .append(merge_parts, input_key=(‘tokens’, ‘offsets’, ‘words’), output_key=‘merged’)

print(tokenizer(text)) # [“密”, “码”, “设置”]

好的,明白了,谢谢何博士的回答!

不错不错。支持pytorch不?