Python分词工具——pyhanlp
本文为本人学习pyhanlp的笔记,大多知识点来源于GitHubhttps://github.com/hankcs/HanLP/blob/master/README.md,文中的demo代码来源于该GitHub主
what's the pyhanlp
pyhanlp是HanLP的Python接口,支持自动下载与升级HanLP,兼容py2、py3。
安装
pip install pyhanlp
安装时可能遇到的问题:
- 报错:error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual
解决方法:手动下载,下载链接:https://pan.baidu.com/s/1WaBxFghTll6Zofz1DGOZBg
- 报错:jpype._jvmfinder.JVMNotFoundException: No JVM shared library file (jvm.dll) found. Try setting up the JAVA_HOME environment variable properly.
解决方法:HanLP主项目采用Java开发,所以需要Java运行环境,请安装JDK。需要保证JDK位数、操作系统位数和Python位数一致。pyhanlp在64位系统上通过了所有测试;在32位系统上可以运行但不做保证。
配置
默认在首次调用pyhanlp时自动下载jar包和数据包,并自动完成配置。
如果网速慢或者其他问题导致配置失败,需要自行下载data文件,然后放入pyhanlp文件的static目录中。下载地址:http://nlp.hankcs.com/download.php?file=data
如果还是失败,请参考https://github.com/hankcs/pyhanlp/wiki/手动配置
一、标准中文分词
使用命令hanlp segment进入交互分词模式,输入一个句子并回车,HanLP会输出分词结果:
$ hanlp segment 商品和服务 商品/n 和/cc 服务/vn 当下雨天地面积水分外严重 当/p 下雨天/n 地面/n 积水/n 分外/d 严重/a 龚学平等领导说,邓颖超生前杜绝超生 龚学平/nr 等/udeng 领导/n 说/v ,/w 邓颖超/nr 生前/t 杜绝/v 超生/vi
还可以重定向输入输出到文件等:
$ hanlp segment <<< '欢迎新老师生前来就餐' 欢迎/v 新/a 老/a 师生/n 前来/vi 就餐/vi
在Python中的实现
from pyhanlp import * print(HanLP.segment('你好,欢迎在Python中调用HanLP的API')) # [你好/vl, ,/w, 欢迎/v, 在/p, Python/nx, 中/f, 调用/v, HanLP/nx, 的/ude1, API/nx] ################### for term in HanLP.segment('下雨天地面积水'): print('{}\t{}'.format(term.word, term.nature)) # 获取单词与词性 ''' 下雨天 n 地面 n 积水 n ''' ################### testCases = [ "商品和服务", "结婚的和尚未结婚的确实在干扰分词啊", "买水果然后来世博园最后去世博会", "中国的首都是北京", "欢迎新老师生前来就餐", "工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作", "随着页游兴起到现在的页游繁盛,依赖于存档进行逻辑判断的设计减少了,但这块也不能完全忽略掉。"] for sentence in testCases: print(HanLP.segment(sentence)) ''' [商品/n, 和/cc, 服务/vn] [结婚/vi, 的/ude1, 和/cc, 尚未/d, 结婚/vi, 的/ude1, 确实/ad, 在/p, 干扰/vn, 分词/n, 啊/y] [买/v, 水果/n, 然后/c, 来/vf, 世博园/n, 最后/f, 去/vf, 世博会/n] [中国/ns, 的/ude1, 首都/n, 是/vshi, 北京/ns] [欢迎/v, 新/a, 老/a, 师生/n, 前来/vi, 就餐/vi] [工信处/n, 女干事/n, 每月/t, 经过/p, 下属/v, 科室/n, 都/d, 要/v, 亲口/d, 交代/v, 24/m, 口/n, 交换机/n, 等/udeng, 技术性/n, 器件/n, 的/ude1, 安装/v, 工作/vn] [随着/p, 页游/nz, 兴起/v, 到/v, 现在/t, 的/ude1, 页游/nz, 繁盛/a, ,/w, 依赖于/v, 存档/vi, 进行/vn, 逻辑/n, 判断/v, 的/ude1, 设计/vn, 减少/v, 了/ule, ,/w, 但/c, 这/rzv, 块/q, 也/d, 不能/v, 完全/ad, 忽略/v, 掉/v, 。/w] '''
说明
- HanLP中有一系列“开箱即用”的静态分词器,以Tokenizer结尾,在接下来的例子中会继续介绍。
- HanLP.segment其实是对StandardTokenizer.segmen的包装。
- 分词结果包含词性,每个词性的意思请查阅《HanLP词性标注集》。
算法详解
二、关键词提取、自动摘要
# 关键词提取 document = "水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露," \ "根据刚刚完成了水资源管理制度的考核,有部分省接近了红线的指标," \ "有部分省超过红线的指标。对一些超过红线的地方,陈明忠表示,对一些取用水项目进行区域的限批," \ "严格地进行水资源论证和取水许可的批准。" print(HanLP.extractKeyword(document, 2)) # [水资源, 陈明忠] # 自动摘要 print(HanLP.extractSummary(document, 3)) # [严格地进行水资源论证和取水许可的批准, 水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露, 有部分省超过红线的指标]
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_keyword(content): """ 关键词提取 [程序员, 程序, 分为, 人员, 软件] """ TextRankKeyword = JClass("com.hankcs.hanlp.summary.TextRankKeyword") keyword_list = HanLP.extractKeyword(content, 5) print(keyword_list) if __name__ == "__main__": content = ( "程序员(英文Programmer)是从事程序开发、维护的专业人员。" "一般将程序员分为程序设计人员和程序编码人员," "但两者的界限并不非常清楚,特别是在中国。" "软件从业人员分为初级程序员、高级程序员、系统" "分析员和项目经理四大类。") demo_keyword(content)
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_summary(document): """自动摘要 [严格地进行水资源论证和取水许可的批准, 水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露, 有部分省超过红线的指标] """ TextRankSentence = JClass("com.hankcs.hanlp.summary.TextRankSentence") sentence_list = HanLP.extractSummary(document, 3) print(sentence_list) if __name__ == "__main__": document = '''水利部水资源司司长陈明忠9月29日在国务院新闻办举行的新闻发布会上透露, 根据刚刚完成了水资源管理制度的考核,有部分省接近了红线的指标, 有部分省超过红线的指标。对一些超过红线的地方,陈明忠表示,对一些取用水项目进行区域的限批, 严格地进行水资源论证和取水许可的批准。 ''' demo_summary(document)
三、短语提取
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_phrase_extractor(text): """ 短语提取 [算法工程师, 算法处理, 一维信息, 算法研究, 信号处理] """ phrase_list = HanLP.extractPhrase(text, 5) print(phrase_list) if __name__ == "__main__": text = ''' 算法工程师 算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。 如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、 空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。算法工程师就是利用算法处理事物的人。 1职位简介 算法工程师是一个非常高端的职位; 专业要求:计算机、电子、通信、数学等相关专业; 学历要求:本科及其以上的学历,大多数是硕士学历及其以上; 语言要求:英语要求是熟练,基本上能阅读国外专业书刊; 必须掌握计算机相关知识,熟练使用仿真工具MATLAB等,必须会一门编程语言。 2研究方向 视频算法工程师、图像处理算法工程师、音频算法工程师 通信基带算法工程师 3目前国内外状况 目前国内从事算法研究的工程师不少,但是高级算法工程师却很少,是一个非常紧缺的专业工程师。 算法工程师根据研究领域来分主要有音频/视频算法处理、图像技术方面的二维信息算法处理和通信物理层、 雷达信号处理、生物医学信号处理等领域的一维信息算法处理。 在计算机音视频和图形图像技术等二维信息算法处理方面目前比较先进的视频处理算法:机器视觉成为此类算法研究的核心; 另外还有2D转3D算法(2D-to-3D conversion),去隔行算法(de-interlacing),运动估计运动补偿算法 (Motion estimation/Motion Compensation),去噪算法(Noise Reduction),缩放算法(scaling), 锐化处理算法(Sharpness),超分辨率算法(Super Resolution) 手势识别(gesture recognition) 人脸识别(face recognition)。 在通信物理层等一维信息领域目前常用的算法:无线领域的RRM、RTT,传送领域的调制解调、信道均衡、信号检测、网络优化、信号分解等。 另外数据挖掘、互联网搜索算法也成为当今的热门方向。 算法工程师逐渐往人工智能方向发展。 ''' demo_phrase_extractor(text)
四、拼音转换
说明
- HanLP不仅支持基础的汉字转拼音,还支持声母、韵母、音调、音标和输入法首字母首声母功能。
- HanLP能够识别多音字,也能给繁体中文注拼音。
- 最重要的是,HanLP采用的模式匹配升级到AhoCorasickDoubleArrayTrie,性能大幅提升,能够提供毫秒级的响应速度!
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_pinyin(): """ 汉字转拼音 原文, 重载不是重任! 拼音(数字音调), [chong2, zai3, bu2, shi4, zhong4, ren4, none5] 拼音(符号音调), chóng, zǎi, bú, shì, zhòng, rèn, none, 拼音(无音调), chong, zai, bu, shi, zhong, ren, none, 声调, 2, 3, 2, 4, 4, 4, 5, 声母, ch, z, b, sh, zh, r, none, 韵母, ong, ai, u, i, ong, en, none, 输入法头, ch, z, b, sh, zh, r, none, jie zhi none none none none nian none jie zhi 2 0 1 2 nian , """ Pinyin = JClass("com.hankcs.hanlp.dictionary.py.Pinyin") text = "重载不是重任!" pinyin_list = HanLP.convertToPinyinList(text) print("原文,", end=" ") print(text) print("拼音(数字音调),", end=" ") print(pinyin_list) print("拼音(符号音调),", end=" ") for pinyin in pinyin_list: print("%s," % pinyin.getPinyinWithToneMark(), end=" ") print("\n拼音(无音调),", end=" ") for pinyin in pinyin_list: print("%s," % pinyin.getPinyinWithoutTone(), end=" ") print("\n声调,", end=" ") for pinyin in pinyin_list: print("%s," % pinyin.getTone(), end=" ") print("\n声母,", end=" ") for pinyin in pinyin_list: print("%s," % pinyin.getShengmu(), end=" ") print("\n韵母,", end=" ") for pinyin in pinyin_list: print("%s," % pinyin.getYunmu(), end=" ") print("\n输入法头,", end=" ") for pinyin in pinyin_list: print("%s," % pinyin.getHead(), end=" ") print() # 拼音转换可选保留无拼音的原字符 print(HanLP.convertToPinyinString("截至2012年,", " ", True)) print(HanLP.convertToPinyinString("截至2012年,", " ", False)) if __name__ == "__main__": demo_pinyin()
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_pinyin_to_chinese(): """ HanLP中的数据结构和接口是灵活的,组合这些接口,可以自己创造新功能 [renmenrenweiyalujiangbujian/null, lvse/[滤色, 绿色]] """ AhoCorasickDoubleArrayTrie = JClass( "com.hankcs.hanlp.collection.AhoCorasick.AhoCorasickDoubleArrayTrie") StringDictionary = JClass( "com.hankcs.hanlp.corpus.dictionary.StringDictionary") CommonAhoCorasickDoubleArrayTrieSegment = JClass( "com.hankcs.hanlp.seg.Other.CommonAhoCorasickDoubleArrayTrieSegment") CommonAhoCorasickSegmentUtil = JClass( "com.hankcs.hanlp.seg.Other.CommonAhoCorasickSegmentUtil") Config = JClass("com.hankcs.hanlp.HanLP$Config") TreeMap = JClass("java.util.TreeMap") TreeSet = JClass("java.util.TreeSet") dictionary = StringDictionary() dictionary.load(Config.PinyinDictionaryPath) entry = {} m_map = TreeMap() for entry in dictionary.entrySet(): pinyins = entry.getValue().replace("[\\d,]", "") words = m_map.get(pinyins) if words is None: words = TreeSet() m_map.put(pinyins, words) words.add(entry.getKey()) words = TreeSet() words.add("绿色") words.add("滤色") m_map.put("lvse", words) segment = CommonAhoCorasickDoubleArrayTrieSegment(m_map) print(segment.segment("renmenrenweiyalujiangbujianlvse")) if __name__ == "__main__": demo_pinyin_to_chinese()
五、简繁转换
说明
- HanLP能够识别简繁分歧词,比如打印机=印表機。许多简繁转换工具不能区分“以后”“皇后”中的两个“后”字,HanLP可以。
- 支持香港繁体和台湾繁体
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_traditional_chinese2simplified_chinese(): """ 将简繁转换做到极致 「以後等你當上皇后,就能買草莓慶祝了」。發現一根白頭髮 凭借笔记本电脑写程序HanLP hankcs在臺灣寫程式碼 hankcs在台湾写代码 hankcs在香港寫代碼 hankcs在香港写代码 hankcs在臺灣寫程式碼 hankcs在香港寫代碼 hankcs在臺灣寫程式碼 hankcs在台灣寫代碼 hankcs在臺灣寫代碼 hankcs在臺灣寫代碼 """ print(HanLP.convertToTraditionalChinese("“以后等你当上皇后,就能买草莓庆祝了”。发现一根白头发")) print(HanLP.convertToSimplifiedChinese("憑藉筆記簿型電腦寫程式HanLP")) # 简体转台湾繁体 print(HanLP.s2tw("hankcs在台湾写代码")) # 台湾繁体转简体 print(HanLP.tw2s("hankcs在臺灣寫程式碼")) # 简体转香港繁体 print(HanLP.s2hk("hankcs在香港写代码")) # 香港繁体转简体 print(HanLP.hk2s("hankcs在香港寫代碼")) # 香港繁体转台湾繁体 print(HanLP.hk2tw("hankcs在臺灣寫代碼")) # 台湾繁体转香港繁体 print(HanLP.tw2hk("hankcs在香港寫程式碼")) # 香港/台湾繁体和HanLP标准繁体的互转 print(HanLP.t2tw("hankcs在臺灣寫代碼")) print(HanLP.t2hk("hankcs在臺灣寫代碼")) print(HanLP.tw2t("hankcs在臺灣寫程式碼")) print(HanLP.hk2t("hankcs在台灣寫代碼")) if __name__ == "__main__": demo_traditional_chinese2simplified_chinese()
六、文本推荐(类似搜索引擎功能)
说明
- 在搜索引擎的输入框中,用户输入一个词,搜索引擎会联想出最合适的搜索词,HanLP实现了类似的功能。
- 支持语义、字符、拼音等形式的搜索推荐
- 可以动态调节每种识别器的权重
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_suggester(): """ 文本推荐(句子级别,从一系列句子中挑出与输入句子最相似的那一个) [威廉王子发表演说 呼吁保护野生动物, 英报告说空气污染带来“公共健康危机”] [英报告说空气污染带来“公共健康危机”] [《时代》年度人物最终入围名单出炉 普京马云入选] [魅惑天后许佳慧不爱“预谋” 独唱《许某某》] """ Suggester = JClass("com.hankcs.hanlp.suggest.Suggester") suggester = Suggester() title_array = [ "威廉王子发表演说 呼吁保护野生动物", "魅惑天后许佳慧不爱“预谋” 独唱《许某某》", "《时代》年度人物最终入围名单出炉 普京马云入选", "“黑格比”横扫菲:菲吸取“海燕”经验及早疏散", "日本保密法将正式生效 日媒指其损害国民知情权", "英报告说空气污染带来“公共健康危机”" ] for title in title_array: suggester.addSentence(title) print(suggester.suggest("陈述", 2)) # 语义 print(suggester.suggest("危机公关", 1)) # 字符 print(suggester.suggest("mayun", 1)) # 拼音 print(suggester.suggest("徐家汇", 1)) # 拼音 if __name__ == "__main__": demo_suggester()
七、语义距离
说明
- 可以得到给出的词汇之间语义的相似度
- word2vec文档
- 《word2vec原理推导与代码分析》
# -*- coding:utf-8 -*- from pyhanlp import * def demo_word_distance(): """ 语义距离 词A 词B 语义距离 语义相似度 <BLANKLINE> 香蕉 香蕉 0 1.0000000000 香蕉 苹果 19980 0.9999997311 香蕉 白菜 2628369 0.9999646244 香蕉 水果 32967 0.9999995563 香蕉 蔬菜 2630367 0.9999645975 香蕉 自行车 1854515628 0.9750398066 香蕉 公交车 1854535619 0.9750395376 香蕉 飞机 1857307833 0.9750022259 香蕉 买 39729797433 0.4652709248 香蕉 卖 39729897333 0.4652695802 香蕉 购入 39729797433 0.4652709248 香蕉 新年 4981789224 0.9329493801 香蕉 春节 4981789224 0.9329493801 香蕉 丢失 46784535633 0.3703201856 香蕉 补办 39205230527 0.4723311464 香蕉 办理 39205222533 0.4723312540 香蕉 送给 40831595534 0.4504416652 香蕉 寻找 41124601233 0.4464980592 香蕉 孩子 6734891367 0.9093541255 香蕉 教室 1548030420 0.9791648353 香蕉 教师 7516908567 0.8988288432 香蕉 会计 7547972472 0.8984107496 苹果 香蕉 19980 0.9999997311 苹果 苹果 0 1.0000000000 苹果 白菜 2608389 0.9999648933 苹果 水果 12987 0.9999998252 苹果 蔬菜 2610387 0.9999648664 苹果 自行车 1854535608 0.9750395377 苹果 公交车 1854555599 0.9750392686 苹果 飞机 1857327813 0.9750019570 苹果 买 39729817413 0.4652706559 苹果 卖 39729917313 0.4652693113 苹果 购入 39729817413 0.4652706559 苹果 新年 4981809204 0.9329491112 苹果 春节 4981809204 0.9329491112 苹果 丢失 46784555613 0.3703199167 苹果 补办 39205250507 0.4723308775 苹果 办理 39205242513 0.4723309851 苹果 送给 40831615514 0.4504413963 苹果 寻找 41124621213 0.4464977903 苹果 孩子 6734871387 0.9093543944 苹果 教室 1548050400 0.9791645663 苹果 教师 7516888587 0.8988291121 苹果 会计 7547952492 0.8984110185 白菜 香蕉 2628369 0.9999646244 白菜 苹果 2608389 0.9999648933 白菜 白菜 0 1.0000000000 白菜 水果 2595402 0.9999650681 白菜 蔬菜 1998 0.9999999731 白菜 自行车 1857143997 0.9750044310 白菜 公交车 1857163988 0.9750041620 白菜 飞机 1859936202 0.9749668503 白菜 买 39732425802 0.4652355492 白菜 卖 39732525702 0.4652342046 白菜 购入 39732425802 0.4652355492 白菜 新年 4984417593 0.9329140045 白菜 春节 4984417593 0.9329140045 白菜 丢失 46787164002 0.3702848100 白菜 补办 39207858896 0.4722957708 白菜 办理 39207850902 0.4722958784 白菜 送给 40834223903 0.4504062896 白菜 寻找 41127229602 0.4464626836 白菜 孩子 6732262998 0.9093895011 白菜 教室 1550658789 0.9791294597 白菜 教师 7514280198 0.8988642188 白菜 会计 7545344103 0.8984461252 水果 香蕉 32967 0.9999995563 水果 苹果 12987 0.9999998252 水果 白菜 2595402 0.9999650681 水果 水果 0 1.0000000000 水果 蔬菜 2597400 0.9999650412 水果 自行车 1854548595 0.9750393629 水果 公交车 1854568586 0.9750390939 水果 飞机 1857340800 0.9750017822 水果 买 39729830400 0.4652704811 水果 卖 39729930300 0.4652691365 水果 购入 39729830400 0.4652704811 水果 新年 4981822191 0.9329489364 水果 春节 4981822191 0.9329489364 水果 丢失 46784568600 0.3703197419 水果 补办 39205263494 0.4723307027 水果 办理 39205255500 0.4723308103 水果 送给 40831628501 0.4504412215 水果 寻找 41124634200 0.4464976155 水果 孩子 6734858400 0.9093545692 水果 教室 1548063387 0.9791643915 水果 教师 7516875600 0.8988292869 水果 会计 7547939505 0.8984111933 蔬菜 香蕉 2630367 0.9999645975 蔬菜 苹果 2610387 0.9999648664 蔬菜 白菜 1998 0.9999999731 蔬菜 水果 2597400 0.9999650412 蔬菜 蔬菜 0 1.0000000000 蔬菜 自行车 1857145995 0.9750044041 蔬菜 公交车 1857165986 0.9750041351 蔬菜 飞机 1859938200 0.9749668234 蔬菜 买 39732427800 0.4652355223 蔬菜 卖 39732527700 0.4652341777 蔬菜 购入 39732427800 0.4652355223 蔬菜 新年 4984419591 0.9329139777 蔬菜 春节 4984419591 0.9329139777 蔬菜 丢失 46787166000 0.3702847831 蔬菜 补办 39207860894 0.4722957440 蔬菜 办理 39207852900 0.4722958515 蔬菜 送给 40834225901 0.4504062627 蔬菜 寻找 41127231600 0.4464626567 蔬菜 孩子 6732261000 0.9093895280 蔬菜 教室 1550660787 0.9791294328 蔬菜 教师 7514278200 0.8988642457 蔬菜 会计 7545342105 0.8984461521 自行车 香蕉 1854515628 0.9750398066 自行车 苹果 1854535608 0.9750395377 自行车 白菜 1857143997 0.9750044310 自行车 水果 1854548595 0.9750393629 自行车 蔬菜 1857145995 0.9750044041 自行车 自行车 0 1.0000000000 自行车 公交车 19991 0.9999997309 自行车 飞机 2792205 0.9999624193 自行车 买 37875281805 0.4902311182 自行车 卖 37875381705 0.4902297736 自行车 购入 37875281805 0.4902311182 自行车 新年 3127273596 0.9579095735 自行车 春节 3127273596 0.9579095735 自行车 丢失 44930020005 0.3952803790 自行车 补办 37350714899 0.4972913398 自行车 办理 37350706905 0.4972914474 自行车 送给 38977079906 0.4754018586 自行车 寻找 39270085605 0.4714582526 自行车 孩子 8589406995 0.8843939321 自行车 教室 306485208 0.9958749714 自行车 教师 9371424195 0.8738686498 自行车 会计 9402488100 0.8734505562 公交车 香蕉 1854535619 0.9750395376 公交车 苹果 1854555599 0.9750392686 公交车 白菜 1857163988 0.9750041620 公交车 水果 1854568586 0.9750390939 公交车 蔬菜 1857165986 0.9750041351 公交车 自行车 19991 0.9999997309 公交车 公交车 0 1.0000000000 公交车 飞机 2772214 0.9999626884 公交车 买 37875261814 0.4902313872 公交车 卖 37875361714 0.4902300427 公交车 购入 37875261814 0.4902313872 公交车 新年 3127253605 0.9579098426 公交车 春节 3127253605 0.9579098426 公交车 丢失 44930000014 0.3952806480 公交车 补办 37350694908 0.4972916089 公交车 办理 37350686914 0.4972917165 公交车 送给 38977059915 0.4754021276 公交车 寻找 39270065614 0.4714585217 公交车 孩子 8589426986 0.8843936631 公交车 教室 306505199 0.9958747023 公交车 教师 9371444186 0.8738683807 公交车 会计 9402508091 0.8734502872 飞机 香蕉 1857307833 0.9750022259 飞机 苹果 1857327813 0.9750019570 飞机 白菜 1859936202 0.9749668503 飞机 水果 1857340800 0.9750017822 飞机 蔬菜 1859938200 0.9749668234 飞机 自行车 2792205 0.9999624193 飞机 公交车 2772214 0.9999626884 飞机 飞机 0 1.0000000000 飞机 买 37872489600 0.4902686988 飞机 卖 37872589500 0.4902673543 飞机 购入 37872489600 0.4902686988 飞机 新年 3124481391 0.9579471542 飞机 春节 3124481391 0.9579471542 飞机 丢失 44927227800 0.3953179597 飞机 补办 37347922694 0.4973289205 飞机 办理 37347914700 0.4973290281 飞机 送给 38974287701 0.4754394393 飞机 寻找 39267293400 0.4714958333 飞机 孩子 8592199200 0.8843563514 飞机 教室 309277413 0.9958373907 飞机 教师 9374216400 0.8738310691 飞机 会计 9405280305 0.8734129755 买 香蕉 39729797433 0.4652709248 买 苹果 39729817413 0.4652706559 买 白菜 39732425802 0.4652355492 买 水果 39729830400 0.4652704811 买 蔬菜 39732427800 0.4652355223 买 自行车 37875281805 0.4902311182 买 公交车 37875261814 0.4902313872 买 飞机 37872489600 0.4902686988 买 买 0 1.0000000000 买 卖 99900 0.9999986554 买 购入 0 1.0000000000 买 新年 34748008209 0.5323215446 买 春节 34748008209 0.5323215446 买 丢失 7054738200 0.9050492608 买 补办 524566906 0.9929397783 买 办理 524574900 0.9929396707 买 送给 1101798101 0.9851707404 买 寻找 1394803800 0.9812271344 买 孩子 46464688800 0.3746250503 买 教室 38181767013 0.4861060895 买 教师 47246706000 0.3640997680 买 会计 47277769905 0.3636816744 卖 香蕉 39729897333 0.4652695802 卖 苹果 39729917313 0.4652693113 卖 白菜 39732525702 0.4652342046 卖 水果 39729930300 0.4652691365 卖 蔬菜 39732527700 0.4652341777 卖 自行车 37875381705 0.4902297736 卖 公交车 37875361714 0.4902300427 卖 飞机 37872589500 0.4902673543 卖 买 99900 0.9999986554 卖 卖 0 1.0000000000 卖 购入 99900 0.9999986554 卖 新年 34748108109 0.5323202001 卖 春节 34748108109 0.5323202001 卖 丢失 7054638300 0.9050506054 卖 补办 524666806 0.9929384338 卖 办理 524674800 0.9929383262 卖 送给 1101698201 0.9851720850 卖 寻找 1394703900 0.9812284790 卖 孩子 46464788700 0.3746237057 卖 教室 38181866913 0.4861047450 卖 教师 47246805900 0.3640984234 卖 会计 47277869805 0.3636803298 购入 香蕉 39729797433 0.4652709248 购入 苹果 39729817413 0.4652706559 购入 白菜 39732425802 0.4652355492 购入 水果 39729830400 0.4652704811 购入 蔬菜 39732427800 0.4652355223 购入 自行车 37875281805 0.4902311182 购入 公交车 37875261814 0.4902313872 购入 飞机 37872489600 0.4902686988 购入 买 0 1.0000000000 购入 卖 99900 0.9999986554 购入 购入 0 1.0000000000 购入 新年 34748008209 0.5323215446 购入 春节 34748008209 0.5323215446 购入 丢失 7054738200 0.9050492608 购入 补办 524566906 0.9929397783 购入 办理 524574900 0.9929396707 购入 送给 1101798101 0.9851707404 购入 寻找 1394803800 0.9812271344 购入 孩子 46464688800 0.3746250503 购入 教室 38181767013 0.4861060895 购入 教师 47246706000 0.3640997680 购入 会计 47277769905 0.3636816744 新年 香蕉 4981789224 0.9329493801 新年 苹果 4981809204 0.9329491112 新年 白菜 4984417593 0.9329140045 新年 水果 4981822191 0.9329489364 新年 蔬菜 4984419591 0.9329139777 新年 自行车 3127273596 0.9579095735 新年 公交车 3127253605 0.9579098426 新年 飞机 3124481391 0.9579471542 新年 买 34748008209 0.5323215446 新年 卖 34748108109 0.5323202001 新年 购入 34748008209 0.5323215446 新年 新年 0 1.0000000000 新年 春节 0 1.0000000000 新年 丢失 41802746409 0.4373708055 新年 补办 34223441303 0.5393817663 新年 办理 34223433309 0.5393818739 新年 送给 35849806310 0.5174922850 新年 寻找 36142812009 0.5135486791 新年 孩子 11716680591 0.8423035056 新年 教室 3433758804 0.9537845449 新年 教师 12498697791 0.8317782233 新年 会计 12529761696 0.8313601297 春节 香蕉 4981789224 0.9329493801 春节 苹果 4981809204 0.9329491112 春节 白菜 4984417593 0.9329140045 春节 水果 4981822191 0.9329489364 春节 蔬菜 4984419591 0.9329139777 春节 自行车 3127273596 0.9579095735 春节 公交车 3127253605 0.9579098426 春节 飞机 3124481391 0.9579471542 春节 买 34748008209 0.5323215446 春节 卖 34748108109 0.5323202001 春节 购入 34748008209 0.5323215446 春节 新年 0 1.0000000000 春节 春节 0 1.0000000000 春节 丢失 41802746409 0.4373708055 春节 补办 34223441303 0.5393817663 春节 办理 34223433309 0.5393818739 春节 送给 35849806310 0.5174922850 春节 寻找 36142812009 0.5135486791 春节 孩子 11716680591 0.8423035056 春节 教室 3433758804 0.9537845449 春节 教师 12498697791 0.8317782233 春节 会计 12529761696 0.8313601297 丢失 香蕉 46784535633 0.3703201856 丢失 苹果 46784555613 0.3703199167 丢失 白菜 46787164002 0.3702848100 丢失 水果 46784568600 0.3703197419 丢失 蔬菜 46787166000 0.3702847831 丢失 自行车 44930020005 0.3952803790 丢失 公交车 44930000014 0.3952806480 丢失 飞机 44927227800 0.3953179597 丢失 买 7054738200 0.9050492608 丢失 卖 7054638300 0.9050506054 丢失 购入 7054738200 0.9050492608 丢失 新年 41802746409 0.4373708055 丢失 春节 41802746409 0.4373708055 丢失 丢失 0 1.0000000000 丢失 补办 7579305106 0.8979890392 丢失 办理 7579313100 0.8979889316 丢失 送给 5952940099 0.9198785204 丢失 寻找 5659934400 0.9238221264 丢失 孩子 53519427000 0.2796743111 丢失 教室 45236505213 0.3911553504 丢失 教师 54301444200 0.2691490288 丢失 会计 54332508105 0.2687309352 补办 香蕉 39205230527 0.4723311464 补办 苹果 39205250507 0.4723308775 补办 白菜 39207858896 0.4722957708 补办 水果 39205263494 0.4723307027 补办 蔬菜 39207860894 0.4722957440 补办 自行车 37350714899 0.4972913398 补办 公交车 37350694908 0.4972916089 补办 飞机 37347922694 0.4973289205 补办 买 524566906 0.9929397783 补办 卖 524666806 0.9929384338 补办 购入 524566906 0.9929397783 补办 新年 34223441303 0.5393817663 补办 春节 34223441303 0.5393817663 补办 丢失 7579305106 0.8979890392 补办 补办 0 1.0000000000 补办 办理 7994 0.9999998924 补办 送给 1626365007 0.9781105187 补办 寻找 1919370706 0.9741669128 补办 孩子 45940121894 0.3816852719 补办 教室 37657200107 0.4931663112 补办 教师 46722139094 0.3711599896 补办 会计 46753202999 0.3707418960 办理 香蕉 39205222533 0.4723312540 办理 苹果 39205242513 0.4723309851 办理 白菜 39207850902 0.4722958784 办理 水果 39205255500 0.4723308103 办理 蔬菜 39207852900 0.4722958515 办理 自行车 37350706905 0.4972914474 办理 公交车 37350686914 0.4972917165 办理 飞机 37347914700 0.4973290281 办理 买 524574900 0.9929396707 办理 卖 524674800 0.9929383262 办理 购入 524574900 0.9929396707 办理 新年 34223433309 0.5393818739 办理 春节 34223433309 0.5393818739 办理 丢失 7579313100 0.8979889316 办理 补办 7994 0.9999998924 办理 办理 0 1.0000000000 办理 送给 1626373001 0.9781104112 办理 寻找 1919378700 0.9741668052 办理 孩子 45940113900 0.3816853795 办理 教室 37657192113 0.4931664188 办理 教师 46722131100 0.3711600972 办理 会计 46753195005 0.3707420036 送给 香蕉 40831595534 0.4504416652 送给 苹果 40831615514 0.4504413963 送给 白菜 40834223903 0.4504062896 送给 水果 40831628501 0.4504412215 送给 蔬菜 40834225901 0.4504062627 送给 自行车 38977079906 0.4754018586 送给 公交车 38977059915 0.4754021276 送给 飞机 38974287701 0.4754394393 送给 买 1101798101 0.9851707404 送给 卖 1101698201 0.9851720850 送给 购入 1101798101 0.9851707404 送给 新年 35849806310 0.5174922850 送给 春节 35849806310 0.5174922850 送给 丢失 5952940099 0.9198785204 送给 补办 1626365007 0.9781105187 送给 办理 1626373001 0.9781104112 送给 送给 0 1.0000000000 送给 寻找 293005699 0.9960563940 送给 孩子 47566486901 0.3597957907 送给 教室 39283565114 0.4712768299 送给 教师 48348504101 0.3492705084 送给 会计 48379568006 0.3488524148 寻找 香蕉 41124601233 0.4464980592 寻找 苹果 41124621213 0.4464977903 寻找 白菜 41127229602 0.4464626836 寻找 水果 41124634200 0.4464976155 寻找 蔬菜 41127231600 0.4464626567 寻找 自行车 39270085605 0.4714582526 寻找 公交车 39270065614 0.4714585217 寻找 飞机 39267293400 0.4714958333 寻找 买 1394803800 0.9812271344 寻找 卖 1394703900 0.9812284790 寻找 购入 1394803800 0.9812271344 寻找 新年 36142812009 0.5135486791 寻找 春节 36142812009 0.5135486791 寻找 丢失 5659934400 0.9238221264 寻找 补办 1919370706 0.9741669128 寻找 办理 1919378700 0.9741668052 寻找 送给 293005699 0.9960563940 寻找 寻找 0 1.0000000000 寻找 孩子 47859492600 0.3558521847 寻找 教室 39576570813 0.4673332240 寻找 教师 48641509800 0.3453269024 寻找 会计 48672573705 0.3449088088 孩子 香蕉 6734891367 0.9093541255 孩子 苹果 6734871387 0.9093543944 孩子 白菜 6732262998 0.9093895011 孩子 水果 6734858400 0.9093545692 孩子 蔬菜 6732261000 0.9093895280 孩子 自行车 8589406995 0.8843939321 孩子 公交车 8589426986 0.8843936631 孩子 飞机 8592199200 0.8843563514 孩子 买 46464688800 0.3746250503 孩子 卖 46464788700 0.3746237057 孩子 购入 46464688800 0.3746250503 孩子 新年 11716680591 0.8423035056 孩子 春节 11716680591 0.8423035056 孩子 丢失 53519427000 0.2796743111 孩子 补办 45940121894 0.3816852719 孩子 办理 45940113900 0.3816853795 孩子 送给 47566486901 0.3597957907 孩子 寻找 47859492600 0.3558521847 孩子 孩子 0 1.0000000000 孩子 教室 8282921787 0.8885189607 孩子 教师 782017200 0.9894747177 孩子 会计 813081105 0.9890566241 教室 香蕉 1548030420 0.9791648353 教室 苹果 1548050400 0.9791645663 教室 白菜 1550658789 0.9791294597 教室 水果 1548063387 0.9791643915 教室 蔬菜 1550660787 0.9791294328 教室 自行车 306485208 0.9958749714 教室 公交车 306505199 0.9958747023 教室 飞机 309277413 0.9958373907 教室 买 38181767013 0.4861060895 教室 卖 38181866913 0.4861047450 教室 购入 38181767013 0.4861060895 教室 新年 3433758804 0.9537845449 教室 春节 3433758804 0.9537845449 教室 丢失 45236505213 0.3911553504 教室 补办 37657200107 0.4931663112 教室 办理 37657192113 0.4931664188 教室 送给 39283565114 0.4712768299 教室 寻找 39576570813 0.4673332240 教室 孩子 8282921787 0.8885189607 教室 教室 0 1.0000000000 教室 教师 9064938987 0.8779936784 教室 会计 9096002892 0.8775755849 教师 香蕉 7516908567 0.8988288432 教师 苹果 7516888587 0.8988291121 教师 白菜 7514280198 0.8988642188 教师 水果 7516875600 0.8988292869 教师 蔬菜 7514278200 0.8988642457 教师 自行车 9371424195 0.8738686498 教师 公交车 9371444186 0.8738683807 教师 飞机 9374216400 0.8738310691 教师 买 47246706000 0.3640997680 教师 卖 47246805900 0.3640984234 教师 购入 47246706000 0.3640997680 教师 新年 12498697791 0.8317782233 教师 春节 12498697791 0.8317782233 教师 丢失 54301444200 0.2691490288 教师 补办 46722139094 0.3711599896 教师 办理 46722131100 0.3711600972 教师 送给 48348504101 0.3492705084 教师 寻找 48641509800 0.3453269024 教师 孩子 782017200 0.9894747177 教师 教室 9064938987 0.8779936784 教师 教师 0 1.0000000000 教师 会计 31063905 0.9995819064 会计 香蕉 7547972472 0.8984107496 会计 苹果 7547952492 0.8984110185 会计 白菜 7545344103 0.8984461252 会计 水果 7547939505 0.8984111933 会计 蔬菜 7545342105 0.8984461521 会计 自行车 9402488100 0.8734505562 会计 公交车 9402508091 0.8734502872 会计 飞机 9405280305 0.8734129755 会计 买 47277769905 0.3636816744 会计 卖 47277869805 0.3636803298 会计 购入 47277769905 0.3636816744 会计 新年 12529761696 0.8313601297 会计 春节 12529761696 0.8313601297 会计 丢失 54332508105 0.2687309352 会计 补办 46753202999 0.3707418960 会计 办理 46753195005 0.3707420036 会计 送给 48379568006 0.3488524148 会计 寻找 48672573705 0.3449088088 会计 孩子 813081105 0.9890566241 会计 教室 9096002892 0.8775755849 会计 教师 31063905 0.9995819064 会计 会计 0 1.0000000000 """ CoreSynonymDictionary = JClass("com.hankcs.hanlp.dictionary.CoreSynonymDictionary") word_array = [ "香蕉", "苹果", "白菜", "水果", "蔬菜", "自行车", "公交车", "飞机", "买", "卖", "购入", "新年", "春节", "丢失", "补办", "办理", "送给", "寻找", "孩子", "教室", "教师", "会计", ] print("%-5s\t%-5s\t%-10s\t%-5s\n" % ("词A", "词B", "语义距离", "语义相似度")) for a in word_array: for b in word_array: print("%-5s\t%-5s\t%-15d\t%-5.10f" % (a, b, CoreSynonymDictionary.distance(a, b), CoreSynonymDictionary.similarity(a, b))) if __name__ == "__main__": demo_word_distance()
八、依存句法分析
命令为hanlp parse,同样支持交互模式和重定向:命令为hanlp parse,同样支持交互模式和重定向:
说明
- 内部采用NeuralNetworkDependencyParser实现,用户可以直接调用NeuralNetworkDependencyParser.compute(sentence)
- 也可以调用基于ArcEager转移系统的柱搜索依存句法分析器KBeamArcEagerDependencyParser
算法详解
$ hanlp parse <<< '徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。' 1 徐先生 徐先生 nh nr _ 4 主谓关系 _ _ 2 还 还 d d _ 4 状中结构 _ _ 3 具体 具体 a a _ 4 状中结构 _ _ 4 帮助 帮助 v v _ 0 核心关系 _ _ 5 他 他 r rr _ 4 兼语 _ _ 6 确定 确定 v v _ 4 动宾关系 _ _ 7 了 了 u ule _ 6 右附加关系 _ _ 8 把 把 p pba _ 15 状中结构 _ _ 9 画 画 v v _ 8 介宾关系 _ _ 10 雄鹰 雄鹰 n n _ 9 动宾关系 _ _ 11 、 、 wp w _ 12 标点符号 _ _ 12 松鼠 松鼠 n n _ 10 并列关系 _ _ 13 和 和 c cc _ 14 左附加关系 _ _ 14 麻雀 麻雀 n n _ 10 并列关系 _ _ 15 作为 作为 p p _ 6 动宾关系 _ _ 16 主攻 主攻 v vn _ 17 定中关系 _ _ 17 目标 目标 n n _ 15 动宾关系 _ _ 18 。 。 wp w _ 4 标点符号 _ _
Python中实现
# 依存句法分析 print(HanLP.parseDependency("徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。")) ''' 1 徐先生 徐先生 nh nr _ 4 主谓关系 _ _ 2 还 还 d d _ 4 状中结构 _ _ 3 具体 具体 a ad _ 4 状中结构 _ _ 4 帮助 帮助 v v _ 0 核心关系 _ _ 5 他 他 r r _ 4 兼语 _ _ 6 确定 确定 v v _ 4 动宾关系 _ _ 7 了 了 u u _ 6 右附加关系 _ _ 8 把 把 p p _ 15 状中结构 _ _ 9 画 画 v v _ 8 介宾关系 _ _ 10 雄鹰 雄鹰 n n _ 9 动宾关系 _ _ 11 、 、 wp w _ 12 标点符号 _ _ 12 松鼠 松鼠 n n _ 10 并列关系 _ _ 13 和 和 c c _ 14 左附加关系 _ _ 14 麻雀 麻雀 n n _ 10 并列关系 _ _ 15 作为 作为 v v _ 6 动宾关系 _ _ 16 主攻 主攻 v vn _ 17 定中关系 _ _ 17 目标 目标 n n _ 15 动宾关系 _ _ 18 。 。 wp w _ 4 标点符号 _ _ '''
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_dependency_parser(): """ 依存句法分析(CRF句法模型需要-Xms512m -Xmx512m -Xmn256m, MaxEnt和神经网络句法模型需要-Xms1g -Xmx1g -Xmn512m) 徐先生 --(主谓关系)--> 帮助 还 --(状中结构)--> 帮助 具体 --(状中结构)--> 帮助 帮助 --(核心关系)--> ##核心## 他 --(兼语)--> 帮助 确定 --(动宾关系)--> 帮助 了 --(右附加关系)--> 确定 把 --(状中结构)--> 作为 画 --(介宾关系)--> 把 雄鹰 --(动宾关系)--> 画 、 --(标点符号)--> 松鼠 松鼠 --(并列关系)--> 雄鹰 和 --(左附加关系)--> 麻雀 麻雀 --(并列关系)--> 雄鹰 作为 --(动宾关系)--> 确定 主攻 --(定中关系)--> 目标 目标 --(动宾关系)--> 作为 。 --(标点符号)--> 帮助 <BLANKLINE> 徐先生 --(主谓关系)--> 帮助 还 --(状中结构)--> 帮助 具体 --(状中结构)--> 帮助 帮助 --(核心关系)--> ##核心## 他 --(兼语)--> 帮助 确定 --(动宾关系)--> 帮助 了 --(右附加关系)--> 确定 把 --(状中结构)--> 作为 画 --(介宾关系)--> 把 雄鹰 --(动宾关系)--> 画 、 --(标点符号)--> 松鼠 松鼠 --(并列关系)--> 雄鹰 和 --(左附加关系)--> 麻雀 麻雀 --(并列关系)--> 雄鹰 作为 --(动宾关系)--> 确定 主攻 --(定中关系)--> 目标 目标 --(动宾关系)--> 作为 。 --(标点符号)--> 帮助 <BLANKLINE> 麻雀 --(并列关系)--> 雄鹰 --(动宾关系)--> 画 --(介宾关系)--> 把 --(状中结构)--> 作为 --(动宾关系)--> 确定 --(动宾关系)--> 帮助 --(核心关系)--> ##核心## """ sentence = HanLP.parseDependency("徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。") for word in sentence.iterator(): # 通过dir()可以查看sentence的方法 print("%s --(%s)--> %s" % (word.LEMMA, word.DEPREL, word.HEAD.LEMMA)) print() # 也可以直接拿到数组,任意顺序或逆序遍历 word_array = sentence.getWordArray() for word in word_array: print("%s --(%s)--> %s" % (word.LEMMA, word.DEPREL, word.HEAD.LEMMA)) print() # 还可以直接遍历子树,从某棵子树的某个节点一路遍历到虚根 CoNLLWord = JClass("com.hankcs.hanlp.corpus.dependency.CoNll.CoNLLWord") head = word_array[12] while head.HEAD: head = head.HEAD if (head == CoNLLWord.ROOT): print(head.LEMMA) else: print("%s --(%s)--> " % (head.LEMMA, head.DEPREL)) if __name__ == "__main__": demo_dependency_parser()
九、NLP分词
调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,这个类位于包名com.hankcs.hanlp.model.perceptron.PerceptronLexicalAnalyzer下,所以先用JClass得到类,然后就可以调用了:
PerceptronLexicalAnalyzer = JClass('com.hankcs.hanlp.model.perceptron.PerceptronLexicalAnalyzer') analyzer = PerceptronLexicalAnalyzer() print(analyzer.analyze("上海华安工业(集团)公司董事长谭旭光和秘书胡花蕊来到美国纽约现代艺术博物馆参观")) # [上海/ns 华安/nz 工业/n (/w 集团/n )/w 公司/n]/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国纽约/ns 现代/ntc 艺术/n 博物馆/n]/ns 参观/v print(analyzer.analyze("我的希望是希望张晚霞的背影被晚霞映红").translateLabels()) # 我/代词 的/助词 希望/名动词 是/动词 希望/动词 张晚霞/人名 的/助词 背影/名词 被/介词 晚霞/名词 映红/动词 print(analyzer.analyze("支援臺灣正體香港繁體:微软公司於1975年由比爾·蓋茲和保羅·艾倫創立。")) # 支援/v 臺灣/ns 正體/n 香港/ns 繁體/n :/w 微软公司/ntc 於/p 1975年/t 由/p 比爾·蓋茲/nr 和/c 保羅·艾倫/nr 創立/v 。/w
说明
- NLP分词NLPTokenizer会执行词性标注和命名实体识别,由结构化感知机序列标注框架支撑。
- 默认模型训练自9970万字的大型综合语料库,是已知范围内全世界最大的中文分词语料库。语料库规模决定实际效果,面向生产环境的语料库应当在千万字量级。用户可以在自己的语料上训练新模型以适应新领域、识别新的命名实体。
十、索引分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,索引分词的类位于包名com.hankcs.hanlp.tokenizer.IndexTokenizer下,先用JClass得到类,然后就可以调用了:
- 索引分词IndexTokenizer是面向搜索引擎的分词器,能够对长词全切分,另外通过term.offset可以获取单词在文本中的偏移量。
- 任何分词器都可以通过基类Segment的enableIndexMode方法激活索引模式。
# # -*- coding:utf-8 -*- from pyhanlp import * from jpype import * def demo_index_segment(): """ 索引分词 主副食品/n [0:4] 主副食/j [0:3] 副食品/n [1:4] 副食/n [1:3] 食品/n [2:4] 最细颗粒度切分: 主副食品/n [0:4] 主副食/j [0:3] 主/ag [0:1] 副食品/n [1:4] 副食/n [1:3] 副/b [1:2] 食品/n [2:4] 食/v [2:3] 品/ng [3:4] """ Term =JClass("com.hankcs.hanlp.seg.common.Term") IndexTokenizer = JClass("com.hankcs.hanlp.tokenizer.IndexTokenizer") term_list = IndexTokenizer.segment("主副食品") for term in term_list.iterator(): print("{} [{}:{}]".format(term, term.offset, term.offset + len(term.word))) print("最细颗粒度切分:") IndexTokenizer.SEGMENT.enableIndexMode(JInt(1)) # JInt用于区分重载 term_list = IndexTokenizer.segment("主副食品") for term in term_list.iterator(): print("{} [{}:{}]".format(term, term.offset, term.offset + len(term.word))) if __name__ == "__main__": demo_index_segment()
十一、N-最短路径分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,N最短路径的类位于包名com.hankcs.hanlp.seg.NShort.NShortSegment下,最短路径的类位于包名com.hankcs.hanlp.seg.Viterbi.ViterbiSegment下,先用JClass得到类,然后就可以调用了
- N最短路分词器NShortSegment比最短路分词器慢,但是效果稍微好一些,对命名实体识别能力更强。
- 一般场景下最短路分词的精度已经足够,而且速度比N最短路分词器快几倍,请酌情选择。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_NShort_segment(sentences): """ N最短路径分词,该分词器比最短路分词器慢,但是效果稍微好一些,对命名实体识别能力更强 N-最短分词:[今天/t, ,/w, 刘志军/nr, 案/ng, 的/ude1, 关键/n, 人物/n, ,/w, 山西/ns, 女/b, 商人/nnt, 丁书苗/nr, 在/p, 市/n, 二/m, 中/f, 院/n, 出庭/vi, 受审/vi, 。/w] 最短路分词:[今天/t, ,/w, 刘志军/nr, 案/ng, 的/ude1, 关键/n, 人物/n, ,/w, 山西/ns, 女/b, 商人/nnt, 丁书苗/nr, 在/p, 市/n, 二/m, 中/f, 院/n, 出庭/vi, 受审/vi, 。/w] N-最短分词:[江西省监狱管理局/nt, 与/cc, 中国/ns, 太平洋/ns, 财产/n, 保险/n, 股份/n, 有限公司/nis, 南昌/ns, 中心支公司/nt, 保险/n, 合同/n, 纠纷案/nz] 最短路分词:[江西省监狱管理局/nt, 与/cc, 中国/ns, 太平洋/ns, 财产/n, 保险/n, 股份/n, 有限公司/nis, 南昌/ns, 中心支公司/nt, 保险/n, 合同/n, 纠纷案/nz] N-最短分词:[新北商贸有限公司/nt] 最短路分词:[新北商贸有限公司/nt] """ NShortSegment = JClass("com.hankcs.hanlp.seg.NShort.NShortSegment") Segment = JClass("com.hankcs.hanlp.seg.Segment") ViterbiSegment = JClass("com.hankcs.hanlp.seg.Viterbi.ViterbiSegment") nshort_segment = NShortSegment().enableCustomDictionary(False).enablePlaceRecognize( True).enableOrganizationRecognize(True) shortest_segment = ViterbiSegment().enableCustomDictionary( False).enablePlaceRecognize(True).enableOrganizationRecognize(True) for sentence in sentences: print("N-最短分词:{} \n最短路分词:{}".format( nshort_segment.seg(sentence), shortest_segment.seg(sentence))) if __name__ == "__main__": sentences = [ "今天,刘志军案的关键人物,山西女商人丁书苗在市二中院出庭受审。", "江西省监狱管理局与中国太平洋财产保险股份有限公司南昌中心支公司保险合同纠纷案", "新北商贸有限公司", ] demo_NShort_segment(sentences)
十二、CRF分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,CRF分词的类位于包名com.hankcs.hanlp.model.crf.CRFLexicalAnalyzer下,先用JClass得到类,然后就可以调用了
- CRF对新词有很好的识别能力,但是开销较大。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_CRF_lexical_analyzer(tests): """ CRF词法分析器 商品/n 和/c 服务/vn [上海/ns 华安/nz 工业/n (/n 集团/n )/v 公司/n]/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国/ns 纽约/ns 现代/t 艺术/n 博物馆/n]/ns 参观/v [微软/nt 公司/n]/nt 於/p 1975年/t 由/p 比爾·蓋茲/n 和/c 保羅·艾倫/v 創立/v ,/v 18年/n 啟動/v 以/p 智慧/n 雲端/n 、/v 前端/n 為/v 導向/n 的/u 大/a 改組/vn 。/w """ CRFLexicalAnalyzer = JClass("com.hankcs.hanlp.model.crf.CRFLexicalAnalyzer") analyzer = CRFLexicalAnalyzer() for sentence in tests: print(analyzer.analyze(sentence)) if __name__ == "__main__": sentences = ["商品和服务", "上海华安工业(集团)公司董事长谭旭光和秘书胡花蕊来到美国纽约现代艺术博物馆参观", "微软公司於1975年由比爾·蓋茲和保羅·艾倫創立,18年啟動以智慧雲端、前端為導向的大改組。" ] demo_CRF_lexical_analyzer(sentences)
十三、极速词典分词
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,极速字典分词的类位于包名com.hankcs.hanlp.tokenizer.SpeedTokenizer下,先用JClass得到类,然后就可以调用了
- 极速分词是词典最长分词,速度极其快,精度一般。
- 在i7-6700K上跑出了4500万字每秒的速度。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * import time def demo_high_speed_segment(): """ 演示极速分词,基于DoubleArrayTrie实现的词典正向最长分词,适用于“高吞吐量”“精度一般”的场合 [江西, 鄱阳湖, 干枯, ,, 中国, 最大, 淡水湖, 变成, 大草原] SpeedTokenizer分词速度:1253607.32字每秒 """ SpeedTokenizer = JClass("com.hankcs.hanlp.tokenizer.SpeedTokenizer") text = "江西鄱阳湖干枯,中国最大淡水湖变成大草原" JClass("com.hankcs.hanlp.HanLP$Config").ShowTermNature = False print(SpeedTokenizer.segment(text)) start = time.time() pressure = 1000000 for i in range(pressure): SpeedTokenizer.segment(text) cost_time = time.time() - start print("SpeedTokenizer分词速度:%.2f字每秒" % (len(text) * pressure / cost_time)) if __name__ == "__main__": demo_high_speed_segment()
十四、用户自定义词典
说明
- 调用更底层的API需要参考Java语法用JClass引入更深的类路径。以感知机词法分析器为例,用户自定义词典的类位于包名com.hankcs.hanlp.dictionary.CustomDictionary下,先用JClass得到类,然后就可以调用了
- CustomDictionary是一份全局的用户自定义词典,可以随时增删,影响全部分词器。另外可以在任何分词器中关闭它。通过代码动态增删不会保存到词典文件。
- 中文分词≠词典,词典无法解决中文分词,Segment提供高低优先级应对不同场景,请参考FAQ。
追加词典
- CustomDictionary主词典文本路径是data/dictionary/custom/CustomDictionary.txt,用户可以在此增加自己的词语(不推荐);也可以单独新建一个文本文件,通过配置文件CustomDictionaryPath=data/dictionary/custom/CustomDictionary.txt; 我的词典.txt;来追加词典(推荐)。
- 始终建议将相同词性的词语放到同一个词典文件里,便于维护和分享。
词典格式
- 每一行代表一个单词,格式遵从[单词] [词性A] [A的频次] [词性B] [B的频次] ... 如果不填词性则表示采用词典的默认词性。
- 词典的默认词性默认是名词n,可以通过配置文件修改:全国地名大全.txt ns;如果词典路径后面空格紧接着词性,则该词典默认是该词性。
- 在统计分词中,并不保证自定义词典中的词一定被切分出来。用户可在理解后果的情况下通过强制生效。
- 关于用户词典的更多信息请参考词典说明一章。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_custom_dictionary(text): """ 演示用户词典的动态增删 TO-DO: DoubleArrayTrie分词 首字哈希之后二分的trie树分词 [攻城/vi, 狮/ng, 逆袭/nz, 单身/n, 狗/n, ,/w, 迎娶/v, 白富美/nr, ,/w, 走上/v, 人生/n, 巅峰/n] [攻城狮/nz, 逆袭/nz, 单身狗/nz, ,/w, 迎娶/v, 白富美/nz, ,/w, 走上/v, 人生/n, 巅峰/n] """ print(HanLP.segment(text)) CustomDictionary = JClass("com.hankcs.hanlp.dictionary.CustomDictionary") CustomDictionary.add("攻城狮") # 动态增加 CustomDictionary.insert("白富美", "nz 1024") # 强行插入 #CustomDictionary.remove("攻城狮"); # 删除词语(注释掉试试) CustomDictionary.add("单身狗", "nz 1024 n 1") #print(CustomDictionary.get("单身狗")) print(HanLP.segment(text)) if __name__ == "__main__": text = "攻城狮逆袭单身狗,迎娶白富美,走上人生巅峰" demo_custom_dictionary(text)
十五、中国人名识别
说明
- 目前分词器基本上都默认开启了中国人名识别,比如HanLP.segment()接口中使用的分词器等等,用户不必手动开启;上面的代码只是为了强调。
- 有一定的误命中率,比如误命中关键年,则可以通过在data/dictionary/person/nr.txt加入一条关键年 A 1来排除关键年作为人名的可能性,也可以将关键年作为新词登记到自定义词典中。
- 建议NLP用户使用感知机或CRF词法分析器,精度更高。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_chinese_name_recognition(sentences): """ 中国人名识别 [签约/vi, 仪式/n, 前/f, ,/w, 秦光荣/nr, 、/w, 李纪恒/nr, 、/w, 仇和/nr, 等/udeng, 一同/d, 会见/v, 了/ule, 参加/v, 签约/vi, 的/ude1, 企业家/nnt, 。/w] [武大靖/nr, 创/v, 世界纪录/nz, 夺冠/vi, ,/w, 中国代表团/nt, 平昌/ns, 首金/n] [区长/nnt, 庄木弟/nr, 新年/t, 致辞/vi] [朱立伦/nr, :/w, 两岸/n, 都/d, 希望/v, 共创/v, 双赢/n, /w, 习/v, 朱/ag, 历史/n, 会晤/vn, 在即/vi] [陕西/ns, 首富/n, 吴一坚/nr, 被/pbei, 带走/v, /w, 与/cc, 令计划/nr, 妻子/n, 有/vyou, 交集/v] [据/p, 美国之音/n, 电台/nis, 网站/n, 4/m, 月/n, 28/m, 日/b, 报道/v, ,/w, 8/m, 岁/qt, 的/ude1, 凯瑟琳·克罗尔/nrf, (/w, 凤甫娟/nr, )/w, 和/cc, 很多/m, 华裔/n, 美国/nsf, 小朋友/n, 一样/uyy, ,/w, 小小年纪/n, 就/d, 开始/v, 学/v, 小提琴/n, 了/ule, 。/w, 她/rr, 的/ude1, 妈妈/n, 是/vshi, 位/q, 虎妈/nz, 么/y, ?/w] [凯瑟琳/nrf, 和/cc, 露西/nrf, (/w, 庐瑞媛/nr, )/w, ,/w, 跟/p, 她们/rr, 的/ude1, 哥哥/n, 们/k, 有/vyou, 一些/m, 不同/a, 。/w] [王国强/nr, 、/w, 高峰/n, 、/w, 汪洋/n, 、/w, 张朝阳/nr, 光着头/l, 、/w, 韩寒/nr, 、/w, 小/a, 四/m] [张浩/nr, 和/cc, 胡健康/nr, 复员/v, 回家/vi, 了/ule] [王总/nr, 和/cc, 小丽/nr, 结婚/vi, 了/ule] [编剧/nnt, 邵钧林/nr, 和/cc, 稽道青/nr, 说/v] [这里/rzs, 有/vyou, 关天培/nr, 的/ude1, 有关/vn, 事迹/n] [龚学平/nr, 等/udeng, 领导/n, 说/v, ,/w, 邓颖超/nr, 生前/t, 杜绝/v, 超生/vi] """ segment = HanLP.newSegment().enableNameRecognize(True); for sentence in sentences: term_list = segment.seg(sentence) print(term_list) if __name__ == "__main__": sentences = [ "签约仪式前,秦光荣、李纪恒、仇和等一同会见了参加签约的企业家。", "武大靖创世界纪录夺冠,中国代表团平昌首金", "区长庄木弟新年致辞", "朱立伦:两岸都希望共创双赢 习朱历史会晤在即", "陕西首富吴一坚被带走 与令计划妻子有交集", "据美国之音电台网站4月28日报道,8岁的凯瑟琳·克罗尔(凤甫娟)和很多华裔美国小朋友一样,小小年纪就开始学小提琴了。她的妈妈是位虎妈么?", "凯瑟琳和露西(庐瑞媛),跟她们的哥哥们有一些不同。", "王国强、高峰、汪洋、张朝阳光着头、韩寒、小四", "张浩和胡健康复员回家了", "王总和小丽结婚了", "编剧邵钧林和稽道青说", "这里有关天培的有关事迹", "龚学平等领导说,邓颖超生前杜绝超生",] demo_chinese_name_recognition(sentences)
十六、音译人名识别
说明
- 目前分词器基本上都默认开启了音译人名识别,用户不必手动开启
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_translated_name_recognition(sentences): """ 音译人名识别 [一桶/nz, 冰水/n, 当头/vi, 倒下/v, ,/w, 微软/ntc, 的/ude1, 比尔盖茨/nrf, 、/w, Facebook/nx, 的/ude1, 扎克伯格/nrf, 跟/p, 桑德博格/nrf, 、/w, 亚马逊/nrf, 的/ude1, 贝索斯/nrf, 、/w, 苹果/nf, 的/ude1, 库克/nrf, 全都/d, 不惜/v, 湿身/nz, 入镜/nz, ,/w, 这些/rz, 硅谷/ns, 的/ude1, 科技/n, 人/n, ,/w, 飞蛾扑火/nz, 似地/d, 牺牲/v, 演出/vn, ,/w, 其实/d, 全/a, 为了/p, 慈善/a, 。/w] [世界/n, 上/f, 最长/d, 的/ude1, 姓名/n, 是/vshi, 简森·乔伊·亚历山大·比基·卡利斯勒·达夫·埃利奥特·福克斯·伊维鲁莫·马尔尼·梅尔斯·帕特森·汤普森·华莱士·普雷斯顿/nrf, 。/w] """ segment = HanLP.newSegment().enableTranslatedNameRecognize(True) for sentence in sentences: term_list = segment.seg(sentence) print(term_list) if __name__ == "__main__": sentences = [ "一桶冰水当头倒下,微软的比尔盖茨、Facebook的扎克伯格跟桑德博格、亚马逊的贝索斯、苹果的库克全都不惜湿身入镜,这些硅谷的科技人,飞蛾扑火似地牺牲演出,其实全为了慈善。", "世界上最长的姓名是简森·乔伊·亚历山大·比基·卡利斯勒·达夫·埃利奥特·福克斯·伊维鲁莫·马尔尼·梅尔斯·帕特森·汤普森·华莱士·普雷斯顿。", ] demo_translated_name_recognition(sentences)
十七、日本人名识别
说明
- 目前标准分词器默认关闭了日本人名识别,用户需要手动开启;这是因为日本人名的出现频率较低,但是又消耗性能。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_japanese_name_recognition(sentences): """ 日本人名识别 [北川景子/nrj, 参演/v, 了/ule, 林诣彬/nr, 导演/nnt, 的/ude1, 《/w, 速度/n, 与/cc, 激情/n, 3/m, 》/w] [林志玲/nr, 亮相/vi, 网友/n, :/w, 确定/v, 不是/c, 波多野结衣/nrj, ?/w] [龟山千广/nrj, 和/cc, 近藤公园/nrj, 在/p, 龟山/nz, 公园/n, 里/f, 喝酒/vi, 赏花/nz] """ Segment = JClass("com.hankcs.hanlp.seg.Segment") Term = JClass("com.hankcs.hanlp.seg.common.Term") segment = HanLP.newSegment().enableJapaneseNameRecognize(True) for sentence in sentences: term_list = segment.seg(sentence) print(term_list) if __name__ == "__main__": sentences =[ "北川景子参演了林诣彬导演的《速度与激情3》", "林志玲亮相网友:确定不是波多野结衣?", "龟山千广和近藤公园在龟山公园里喝酒赏花", ] demo_japanese_name_recognition(sentences)
十八、地名识别
说明
- 目前标准分词器都默认关闭了地名识别,用户需要手动开启;这是因为消耗性能,其实多数地名都收录在核心词典和用户自定义词典中。
- 在生产环境中,能靠词典解决的问题就靠词典解决,这是最高效稳定的方法。
- 建议对命名实体识别要求较高的用户使用感知机词法分析器。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_place_recognition(sentences): """ 地名识别 [蓝翔/nt, 给/p, 宁夏/ns, 固原市/ns, 彭阳县/ns, 红河镇/ns, 黑牛沟村/ns, 捐赠/v, 了/ule, 挖掘机/n] """ Segment = JClass("com.hankcs.hanlp.seg.Segment") Term = JClass("com.hankcs.hanlp.seg.common.Term") segment = HanLP.newSegment().enablePlaceRecognize(True) for sentence in sentences: term_list = segment.seg(sentence) print(term_list) if __name__ == "__main__": sentences = ["蓝翔给宁夏固原市彭阳县红河镇黑牛沟村捐赠了挖掘机"] demo_place_recognition(sentences)
十九、机构名识别
说明
- 目前分词器默认关闭了机构名识别,用户需要手动开启;这是因为消耗性能,其实常用机构名都收录在核心词典和用户自定义词典中。
- HanLP的目的不是演示动态识别,在生产环境中,能靠词典解决的问题就靠词典解决,这是最高效稳定的方法。
- 建议对命名实体识别要求较高的用户使用感知机词法分析器。
算法详解
# # -*- coding:utf-8 -*- from pyhanlp import * def demo_organization_recognition(sentences): """ 机构名识别 [我/rr, 在/p, 上海/ns, 林原科技有限公司/nt, 兼职/vn, 工作/vn, ,/w] [我/rr, 经常/d, 在/p, 台川喜宴餐厅/nt, 吃饭/vi, ,/w] [偶尔/d, 去/vf, 开元地中海影城/nt, 看/v, 电影/n, 。/w] """ Segment = JClass("com.hankcs.hanlp.seg.Segment") Term = JClass("com.hankcs.hanlp.seg.common.Term") segment = HanLP.newSegment().enableOrganizationRecognize(True) for sentence in sentences: term_list = segment.seg(sentence) print(term_list) if __name__ == "__main__": sentences = [ "我在上海林原科技有限公司兼职工作,", "我经常在台川喜宴餐厅吃饭,", "偶尔去开元地中海影城看电影。", ] demo_organization_recognition(sentences)
服务器
通过hanlp serve来启动内置的http服务器,默认本地访问地址为:http://localhost:8765 ;也可以访问官网演示页面:http://hanlp.hankcs.com/ 。
与其他项目共享data
HanLP具备高度可自定义的特点,所有模型和词典都可以自由替换。如果你希望与别的项目共享同一套data,只需将该项目的配置文件hanlp.properties拷贝到pyhanlp的安装目录下即可。本机安装目录可以通过hanlp --version获取。
同时,还可以通过--config临时加载另一个配置文件:
hanlp segment --config path/to/another/hanlp.properties
参考:https://github.com/hankcs/pyhanlp
参考:https://github.com/hankcs/HanLP/blob/master/README.md