自然语言处理hanlp------7-1双数组字典树

本文涉及的产品
NLP自然语言处理_高级版,每接口累计50万次
NLP自然语言处理_基础版,每接口每天50万次
NLP 自学习平台,3个模型定制额度 1个月
简介: 自然语言处理hanlp------7-1双数组字典树

前言

上一节的BinTrie的接口做到了1000万字每秒的速度,比Python的64万字每秒提高了两个数量级。但我们是算法工程师,要做到挑战极限。


提示:以下是本篇文章正文内容,下面案例可供参考


一、双数组字典树(DAT)是什么?

Trie树本质是一个确定的有限状态自动机(DFA),核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。


但由于Trie树的稀疏现象严重,空间利用率较低为了让Trie树实现占用较少的空间,同时还要保证查询的效率,最后提出了用2个线性数组来进行Trie树的表示,即双数组Trie(Double Array Trie).

双数组Trie(Double-ArrayTrie)是trie树的一个简单而有效的实现,由两个整数数组构成,一个是base[],另一个是check[]。


base数组的每个元素表示一个Trie节点,即一个状态(分为空闲状态和占用状态)

check数组的每个元素表示某个状态的前驱状态


公式如下:

p = base[b] + c
check[p] = base[b]


若不满足此条件,则状态转移失败。举个例子,当前状态为自然(状态由一个整数下标表示,下同),我们想知道是否可以转移到自然人。那么我们先执行自然人=base [自然]+人,然后检查 check [ 自然人]==base[自然]是否成立,据此判断转移是否成功。

也就是说,我们仅仅执行一次加法和一次整数比较就能进行状态转移,因而只花费了常数时间。


二、了解一下源码

1.定义一个双数组

代码如下(示例):

class DoubleArrayTrie(object):
    def __init__(self, dic: dict) -> None:
        m = JClass('java.util.TreeMap')()
        for k, v in dic.items():
            m[k] = v
        DoubleArrayTrie = JClass('com.hankcs.hanlp.collection.trie.DoubleArrayTrie')
        dat = DoubleArrayTrie(m)
        self.base = dat.getBase()
        self.check = dat.getCheck()
        self.value = dat.getValueArray([''])

这里的双数组的构造直接由Hanlp实现,直接拿到对应的base,check,value值


2.状态转移

前面有讲述,Python的散列值不适合字符,所以直接借用 javahashcode()

代码如下(示例):

@staticmethod
    def char_hash(c) -> int:
        return JClass('java.lang.Character')(c).hashCode()

此处根据java的character对象创建字符并用hashcode方法取得其散列值


考虑到不是所有节点都对应词语终点,只有字典树中的终点节点(蓝色节点)才对应一个词语。为了区分它们,实现上可以借鉴C语言中的设计,在每个字符串末尾添加一个散列值等于0的\0,也就是说,\0充当了蓝色节点的角色,这样普通节点就不需要分配内存标记自己的颜色了。考虑到用户输入的文本中也可能含有\0,为了避免与此混淆,HanLP采用将文本字符的hashCode加一。一个兼容\0的转移函数的实现如下:

def transition(self, c, b) -> int:
        """
        状态转移
        :param c: 字符
        :param b: 初始状态
        :return: 转移后的状态,-1表示失败
        """
        p = self.base[b] + self.char_hash(c) + 1
        if self.base[b] == self.check[p]:
            return p
        else:
            return -1

除了额外加一的技巧外,这段代码与双数组字典树一致。


3.查询

有了状态转移函数,我们再对键取值查询就方便多了,带上多出来的+1(\0),也就是状态转移至多是len(key)+1次。

def __getitem__(self, key: str):
        b = 0
        for i in range(0, len(key)):  # len(key)次状态转移
            p = self.transition(key[i], b)
            if p is not -1:
                b = p
            else:
                return None
        p = self.base[b]  # 按字符'\0'进行状态转移
        n = self.base[p]  # 查询base
        if p == self.check[p] and n < 0:  # 状态转移成功且对应词语结尾
            index = -n - 1  # 取得字典序
            return self.value[index]
        return None


测试一下效果:

if __name__ == '__main__':
    dic = {'自然': 'nature', '自然人': 'human', '自然语言': 'language', '自语': 'talk  to oneself', '入门': 'introduction'}
    dat = DoubleArrayTrie(dic)
    #assert dat['自然'] == 'nature'
    #assert dat['自然语言'] == 'language'
    #assert dat['不存在'] is None
    #assert dat['自然\0在'] is None
    print(dat['自然'])
    print(dat['自然语言'])
    print(dat['不存在'])
    print(dat['自然\0在'])

20210125124936895.png


总结

多看,多思考,不懂的先保留,重在理解晗佬的思路,解决方案。

相关文章
|
存储 自然语言处理
自然语言处理hanlp------9基于双数组字典树的AC自动机
自然语言处理hanlp------9基于双数组字典树的AC自动机
自然语言处理hanlp------9基于双数组字典树的AC自动机
|
存储 自然语言处理 算法
自然语言处理hanlp------7-2双数组字典树(*初学者可选择性学习)
自然语言处理hanlp------7-2双数组字典树(*初学者可选择性学习)
自然语言处理hanlp------7-2双数组字典树(*初学者可选择性学习)
|
自然语言处理 算法 Java
自然语言处理hanlp------6-2字典树的实现
自然语言处理hanlp------6-2字典树的实现
自然语言处理hanlp------6-2字典树的实现
|
自然语言处理 算法 Java
自然语言处理hanlp------6-1字典树的实现
自然语言处理hanlp------6-1字典树的实现
自然语言处理hanlp------6-1字典树的实现
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
AI技术在自然语言处理中的应用与挑战
【10月更文挑战第3天】本文将探讨AI技术在自然语言处理(NLP)领域的应用及其面临的挑战。我们将分析NLP的基本原理,介绍AI技术如何推动NLP的发展,并讨论当前的挑战和未来的趋势。通过本文,读者将了解AI技术在NLP中的重要性,以及如何利用这些技术解决实际问题。
|
3月前
|
机器学习/深度学习 数据采集 自然语言处理
深度学习在自然语言处理中的应用与挑战
本文探讨了深度学习技术在自然语言处理(NLP)领域的应用,包括机器翻译、情感分析和文本生成等方面。同时,讨论了数据质量、模型复杂性和伦理问题等挑战,并提出了未来的研究方向和解决方案。通过综合分析,本文旨在为NLP领域的研究人员和从业者提供有价值的参考。
|
2月前
|
自然语言处理 算法 Python
自然语言处理(NLP)在文本分析中的应用:从「被动收集」到「主动分析」
【10月更文挑战第9天】自然语言处理(NLP)在文本分析中的应用:从「被动收集」到「主动分析」
50 4
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
探索AI在自然语言处理中的创新应用
【10月更文挑战第7天】本文将深入探讨人工智能在自然语言处理领域的最新进展,揭示AI技术如何改变我们与机器的互动方式,并展示通过实际代码示例实现的具体应用。
39 1
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
AI技术在自然语言处理中的应用
【9月更文挑战第17天】本文主要介绍了AI技术在自然语言处理(NLP)领域的应用,包括文本分类、情感分析、机器翻译和语音识别等方面。通过实例展示了AI技术如何帮助解决NLP中的挑战性问题,并讨论了未来发展趋势。
|
17天前
|
机器学习/深度学习 自然语言处理 监控
探索深度学习在自然语言处理中的应用与挑战
本文深入分析了深度学习技术在自然语言处理(NLP)领域的应用,并探讨了当前面临的主要挑战。通过案例研究,展示了如何利用神经网络模型解决文本分类、情感分析、机器翻译等任务。同时,文章也指出了数据稀疏性、模型泛化能力以及计算资源消耗等问题,并对未来的发展趋势进行了展望。