Python教学专栏: 系统学习Python编程及HanLP词典相关内容
有关更多内容,请单击查看Python实际战斗|高级中国分割HANLP字典分割(顶部)

Python教学专栏旨在为初学者提供系统,全面的Python编程学习经验。通过逐渐解释Python的基本语言和编程逻辑并与实际情况相结合,Xiaobai可以轻松理解Python!
本文目录
1。简介
2。加载HANLP词典
第三,切割划分规则
第四,实施HANLP词典
5。最终语言
本文中有9,395个单词。阅读大约需要24分钟。欢迎纠正它!
部分简介
自然语言处理任务的水平可以分为短语分析,语法分析和语义分析。同时,这也是一个从易于到困难的渐进过程。对于中国人,系统分析(中国细分,单词 - 本质标签和命名实体识别)是以下任务的基础,中文单词是最基本的任务。目前,基于字典规则和机器学习,中国细分算法可以大致分为两个主要派系。无论哪种派系算法,总是有自己的优势和缺点。我们应该选择最合适的算法来进行当前的工作和学习任务。
此问题将向您介绍如何基于HANLP执行字典单词。字典分割是基于字典的分割方法。它的原则是匹配要用字典中的单词来处理的文本。剪下。此外,为什么我们首先介绍HANLP词典?除了相对容易的理解外,引入这种方法的原因有两个:
HANLP支持自定义字典(还支持默认字典单词)。用户可以自定义其各自字段内容的字典,以提高细分的准确性。
HANLP开发人员Hancks使用双阵列字典树结构来存储字典。它具有较小的空间复杂性和较高的匹配效率。在确保准确性的同时,它提高了单词拆分的效率。
根据字典单词的定义,使用字典来分割单词实际上只需要一部字典和搜索字典的一组规则,因此让我们首先介绍如何在hanlp中加载字典,然后介绍三个常用的段段规则,然后它们介绍它们。 HANLP的效果最终实现。
该文本基于HANLP 1.8.4。
本文中的所有Python代码均写在综合开发环境Visual Studio Code(VSCODE)中的交互式开发环境中。
Part2负载HANLP词典
实施字典单词的第一步是准备字典。互联网上已经有许多开放的中国钻石,例如Thuocl(Tsinghua University的中国连衣裙),中国维基百科和He Yu发布的1000万级巨型中国钻石。下载用于个人研究和使用。
在上一篇文章中,我们介绍了安装HANLP的方法。如果未安装的读者,请参考。当我们第一次运行时,数据包和词典带有HANLP会自动下载到Pyhanlp的系统路径。作者的词典路径如下:
C:\ users \ Qiyan_user \ miniconda3 \ lib \ site-packages \ pyhanlp \ static \ static \ data \ dictionaryary
这是HANLP(CountatureDictionary.txt)的核心字典的一个示例。这是由“ UTF-8”编码的纯文本文件。
可以看出,HANLP字典是空间中单独形式的形式。这三列是单词,单词和相应的单词(语料库中的统计结果),例如“叙事”。第二个是名词的形式18次。
现在,让我们看看如何在Hanlp中加载该字典。代码如下:
应该注意的是,为了促进显示,本文将将代码存储在.IPYNB文件中。如果读者将来需要调用该功能,建议将代码存放在脚本文件(也称为“模块”)中。功能。
from pyhanlp import *
# 参数 path:需要加载的词典路径
def load_dictionary(path):
IOUtil = JClass('com.hankcs.hanlp.corpus.io.IOUtil') # 1
dic = IOUtil.loadDictionary([path]) # 2
return set(dic.keySet()) # 返回 set 形式的词典
my_dict = load_dictionary(HanLP.Config.CoreDictionaryPath) # 传入核心词典路径
print(len(my_dict)) # 词典的词条数
# 运行结果
'''
153091
'''
在上面的代码中,代码1行中的JCLASS函数用于根据Java路径名获取Python -Class桥。 ,例如读取和编写文件等);注释2的代码行是调用ioutil方法加载。此方法支持将多个文件读取到同一字典中,因此需要将其传递到列表中。返回值DIC是一个时间表。它的关键是单词本身,值是包含单词和频繁单词的结构(无论治理如何)。用汉语单词,我们更关心单词本身,因此该函数只需要返回tarmap键(通过dic.keyset())。
然后,我们将HANLP配置项中的字典路径传输为参数,获得了字典my_dic,并输出字典的条目数。在这一点上,我们已经成功加载了HANLP的核心字典,并且可以根据Python代码使用字典。
如果您现在需要使用HANLP的核心迷你词典怎么办?只需将呼叫函数的代码更改为:
my_dict = load_dictionary(HanLP.Config.CoreDictionaryPath.replace('.txt', '.mini.txt'))
第3部分切割规则
准备词典后,下一步是确定搜索字典的规则。三个常用的规则是最长的匹配,最长的匹配和最长的匹配和最长的匹配和最长的匹配。在对这三种类型的划分规则的具体理解之前,首先是规则的基础。
完全分开的点是在文本段落中找到所有单词。请注意,这不是标准意义上的单词。完全切割的是遍历文本中的连续序列,并检查序列是否在字典中。根据这个想法,现在我们将“完整的划分过程是削减规则的基础”中的一句话。代码如下:
def full_seg(text, dic):
seg_list = []
for i in range(len(text)): # i 从 0 遍历至 text 最后一个字的下标
for j in range(i+1, len(text)+1): # j 从 i 的后一个位置开始遍历
word = text[i:j] # 取出区间 [i, j) 对应的字符串
if word in dic: # 如果该字符串在词典中,则认为是一个词语
seg_list.append(word)
return seg_list
# 此处使用的词典,为上一步加载的 HanLP 核心词典
full_seg('完全切分过程是切分规则的基础', my_dict)
结果如下:
可以看出,所有可能的单词都是按遍历的顺序完全输出的,包括一些单词和单词。这不是我们想要的结果。考虑到单词表达式的含义越长,单词表达式的含义越丰富,因此定义单词越长,优先级越高,优先级就越高。目前,出现了三种类型的分割规则。在在特定终点中增加单词 - 检查单词的过程中,优先级输出是最长的匹配算法。最长的比赛。
1。积极匹配
顾名思义,正义的匹配算法是投标的扫描顺序。简而言之,它将扫描从左到右分开的单词文本。每次尝试尽可能匹配单词。如果您找到匹配的单词,请将其切成单词,然后从下一个字符开始。继续匹配。看看效果。现在,我们分为“这项研究在中国人民大学进行”一词。代码如下:
def fore_seg(text, dic):
seg_list = []
i = 0
while i < len(text):
longest_word = text[i] # 当前扫描位置对应的字符
for j in range(i+1, len(text)+1): # j 为结束为止,从 i 的下一位开始,遍历得到所有可能的词 [i,j)
word = text[i:j] # 得到区间 [i,j) 对应的字符串
if word in dic:
if len(word) > len(longest_word): # 该词在词典中 & 比longest_word更长,优先输出
longest_word = word
seg_list.append(longest_word) # 输出每一个起始位置 i 匹配的最长词
i += len(longest_word) # 从下一个字符开始匹配
return seg_list
fore_seg('这项研究在中国人民大学进行', my_dict)
# 输出结果
'''
['这项', '研究', '在', '中国人', '民', '大学', '进行']
'''
可以看出,将“中国人”一词的结果分为一个单词。实际上,对于这句话,我们理想的分数结果是“中国”和“人”有两个词。这是因为最长的匹配是“中国”的优先级高于“中国”。因此,如果以最长的匹配规则剪切该句子,它将得到什么结果?
2。最长的匹配
最长的匹配和最长匹配之间的区别在于,它开始扫描单词的文字要从右至左分开。目前,只需对代码进行相应的更改,如下所示:
def back_seg(text, dic):
seg_list = []
j = len(text) - 1
while j >= 0: # 逆向扫描, 当前扫描位置为终点
longest_word = text[j] # 当前扫描位置对应的字符
for i in range(0, j): # i 为起始位置,从 0 开始遍历至 j 的前一个位置
word = text[i: j+1] # 得到区间 [i, j] 对应的字符串
if word in dic:
if len(word) > len(longest_word): # 该词在词典中 & 比longest_word更长,优先级更高
longest_word = word
seg_list.insert(0, longest_word) # 由于逆向扫描,查出的单词位置靠后
j -= len(longest_word)
return seg_list
back_seg('这项研究在中国人民大学进行', my_dict)
# 输出结果
'''
['这项', '研究', '在', '中国', '人民', '大学', '进行']
'''
可以看出,这句话的结果是我们想要的,这表明最长的匹配效果比最长的匹配效果更好?然后查看另一句话的单词的单词,代码如下:
print(fore_seg('项目的研究目的值得人们的关注', my_dict))
print(back_seg('项目的研究目的值得人们的关注', my_dict))
# 输出结果
'''
['项目', '的', '研究', '目的', '值得', '人们', '的', '关注']
['项', '目的', '研究', '目的', '值得', '人们', '的', '关注']
'''
为了响应上面示例中的句子,最长的匹配结果比最长的匹配匹配要好。可以看出,这两个细分规则具有自己的优势。
3。两者之间最长的匹配
因此,有些人提出了这两个规则的综合分区规则 - 两条路之间最长的匹配,其规则更为复杂:
同时,匹配最长的匹配和反向。如果两个次数的数量有所不同,则单词数量较少的结果返回
如果两个次数的数量相同,则返回两个单词较少单词的结果将被返回。
如果单词数相同,则优先级匹配的向后匹配的结果优先
根据SunM.S的研究和Benjamin KT(1995),中文中约有90.0%的句子完全重叠,最大匹配是完整而正确的。不同的,但其中一个必须是正确的(成功检测),不到句子的1.0%,这是最大的匹配,反向和最大匹配的不法行为。最大匹配方法是不同的,但两者不正确(歧义测试失败)。
结合两条两条路的最长匹配规则,获取以下代码:
def bidir_seg(text, dic):
fore = fore_seg(text, dic)
back = back_seg(text, dic)
bidir = fore if len(fore) < len(back) else back # 1.选择词数更少的结果
count_fore = len([word for word in fore if len(word) == 1]) # 正向匹配结果中单字的数量
count_back = len([word for word in back if len(word) == 1]) # 逆向匹配结果中单字的数量
bidir = fore if count_fore < count_back else back # 2.3.选择单字更少的结果,如果相等,优先逆向匹配
return bidir
print(bidir_seg('这项研究在中国人民大学进行', my_dict))
print(bidir_seg('项目的研究目的值得人们的关注', my_dict))
# 输出结果
'''
['这项', '研究', '在', '中国', '人民', '大学', '进行']
['项', '目的', '研究', '目的', '值得', '人们', '的', '关注']
'''
在两个最长匹配的最长匹配规则下,这两个句子的结果实际上是通过最长的匹配获得的。第一个句子分割的结果是正确的,第二句的结果不理想。
并不难看到字典分割的三个分割规则没有完美的效果。消除效果的效果不足以确保规则在特定上下文中正确理解每个单词的特定含义。准确性。当然,Hanlp的作者还指出,字典单词分割的核心价值不是精度或速度。
Part4实现HANLP词典
匹配算法的瓶颈之一是如何判断字典中的字符串。中文中有7,000多个常用单词,超过56,000个常用单词。将这些数据加载到内存很容易,但是执行高的并发操作更加困难。目前,您需要设计巧妙的数据结构和存储方法。在基于Java的高性能分段中,作者使用双阵列来完成字典树(Trie Tree)和自动机器的存储,从而实现了更快的匹配速度。本文更多地关注实际战斗。如果读者对特定算法原则非常感兴趣,他们可以在“获得自然语言的开始”一书中学习。
在正常情况下,当我们的容忍文本包含一个短模式字符串(不长或单词)时,对双阵列字典树(DAT)的数据结构得到了优先级,否则,首选使用double--基于ACDAT的数据结构的数组字典。让我们看一下如何调用HANLP字典单词分段。
HANLP中的字典基础段类包含DoubleRarrayTriesegment和acdat单词(Ahocorasickdoublearraytriesegment)。将单词分离器作为示例引入。
DAT分割是DAT的最长匹配的软件包。默认情况下,单词分离器是我们上面介绍的HANLP的核心词典。代码如下:
# 关闭词性标注(上期文章已介绍)
HanLP.Config.ShowTermNature = False
# 实例化
segment = DoubleArrayTrieSegment()
print(segment.seg("语料库规模决定实际效果,面向生产环境的语料库应当在千万字量级。"))
# 输出结果
'''
[语料库, 规模, 决定, 实际, 效果, ,, 面向, 生产, 环境, 的, 语料库, 应当, 在, 千, 万, 字, 量级, 。]
'''
第二行代码是创建DoubleArrayTriesegment类的实例。这是因为DoublearrayTriesegment是Hanlp的一类。为了使用类中定义的属性和方法,您需要创建一个实例(如果您对类和实例不了解,读者可以参考文章)。
我们还可以将自己的词典途径介绍给“ discor”一词。例如,我们被评为美国的位置名称的名称。代码如下:
# 需要传入的词典路径
dict1 = HANLP_DATA_PATH + "/dictionary/custom/全国地名大全.txt ns"
dict2 = HANLP_DATA_PATH + "/dictionary/CoreNatureDictionary.mini.txt"
# 以 list 的形式,将多个词典传入
segment = DoubleArrayTrieSegment([dict1, dict2])
print(segment.seg('中国北京市海淀区中关村大街59号'))
# 输出结果
'''
[中国, 北京市, 海淀区, 中关村, 大街, 5, 9, 号]
'''
在上面的代码中,HANLP_DATA_PATH指向Pyhanlp的数据包路径,因此您只需要在背面添加字典路径即可。同时,单词拆分设备支持多个词典(以列表的形式)。此外,您可能会注意到dict1字典被称为国家位置名称.txt ns。这里的ns指字典词典中的单词为ns(位置名称)。 “通过这种方式,无需指定字典中每个条目的单词,您还可以在字典中设置字段的单词性质。
如果仔细观察,您会发现应该连接59号房屋,而不是拆卸。这是因为在基于字典的段中,合并数字,英语和单词标记是一个总体函数。启用此功能的代码如下:
# 开启合并与词性标注功能
segment.enablePartOfSpeechTagging(True)
print(segment.seg('中国北京市海淀区中关村大街59号'))
# 输出结果
'''
[中国/ns, 北京市/ns, 海淀区/ns, 中关村/ns, 大街/n, 59/m, 号/q]
'''
应当指出的是,默认颗粒并不表示所有单词都在一个句子中指定,这显然是错误的。 HANLP的聚合物将考虑上下文和其他因素。例如,这句话中的“街”一词更适合名词,而不是一个名称。从上面的单词和单词标记结果可以看出,此功能更灵活。
第5部分结束
单词是中文自然语言处理的基础。没有中文的话,我们很难量化语言。基于字典的分割算法是一种常见的中文单词分割方法。本文重点介绍了三种类型的切割规则,以及在高性能单词分段HANP中实现字典分割。已经获得了划分一词的结果。如何计算单词的准确性?在下一篇文章中,我们将主要介绍中文单词领域中使用的准确性评估指标。下次见〜
此外,如果您还涉及文本分析的实践经验,请留下一条消息以与所使用的方法或工具进行通信,让我们一起探索更多的技术!
如果您想学习各种Python编程技术并增强个人竞争力,请加入我们的数据研讨会沟通小组(单击以阅读原始的Python Combat |高级中文细分HANLP词典(TOP),请与客户服务联系以获取进入客户服务小组),欢迎大家交流,探索,学习和共同取得进步!同时,您还可以通过数据研讨会和获得的结果分享所学的技能。
Part6推荐的Python教学Python真实数据可视化