/// <summary> /// 依存句法分析(神经网络句法模型需要-Xms1g -Xmx1g -Xmn512m) /// 内部采用NeuralNetworkDependencyParser实现,用户可以直接调用NeuralNetworkDependencyParser.compute(sentence) /// 也可以调用基于MaxEnt的依存句法分析器MaxEntDependencyParser.compute(sentence) /// 《基于神经网络的高性能依存句法分析器》 ///https://www.hankcs.com/nlp/parsing/neural-network-based-dependency-parser.html ///《最大熵依存句法分析器的实现》 ///https://www.hankcs.com/nlp/parsing/to-achieve-the-maximum-entropy-of-the-dependency-parser.html ///《基于CRF序列标注的中文依存句法分析器的Java实现》 ///https://www.hankcs.com/nlp/parsing/crf-sequence-annotation-chinese-dependency-parser-implementation-based-on-java.html /// </summary> public void DependencyParser() { CoNLLSentence sentence = HanLP.parseDependency("徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。"); Console.WriteLine(sentence); // 可以方便地遍历它 foreach (CoNLLWord word in sentence) { Console.WriteLine($"{word.LEMMA} --({word.DEPREL})--> {word.HEAD.LEMMA}\n"); } // 也可以直接拿到数组,任意顺序或逆序遍历 CoNLLWord[] wordArray = sentence.getWordArray(); for (int i = wordArray.Length - 1; i >= 0; i--) { CoNLLWord word = wordArray[i]; Console.WriteLine($"{word.LEMMA} --({word.DEPREL})-->{word.HEAD.LEMMA}\n"); } // 还可以直接遍历子树,从某棵子树的某个节点一路遍历到虚根 CoNLLWord head = wordArray[12]; while ((head = head.HEAD) != null) { if (head == CoNLLWord.ROOT) { Console.WriteLine(head.LEMMA); } else { Console.WriteLine($"{head.LEMMA} --({head.DEPREL})--> "); } } }
/// <summary> /// 短语识别 /// 内部采用MutualInformationEntropyPhraseExtractor实现,用户可以直接调用MutualInformationEntropyPhraseExtractor..extractPhrase(text, size)。 /// 《基于互信息和左右信息熵的短语提取识别》 /// https://www.hankcs.com/nlp/extraction-and-identification-of-mutual-information-about-the-phrase-based-on-information-entropy.html /// </summary> /// <param name="content"></param> public void extractPhrase(string content) { content = "算法工程师\n" + "算法(Algorithm)是一系列解决问题的清晰指令,也就是说,能够对一定规范的输入,在有限时间内获得所要求的输出。" + "如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、" + "空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。算法工程师就是利用算法处理事物的人。\n" + "\n" + "1职位简介\n" + "算法工程师是一个非常高端的职位;\n" + "专业要求:计算机、电子、通信、数学等相关专业;\n" + "学历要求:本科及其以上的学历,大多数是硕士学历及其以上;\n" + "语言要求:英语要求是熟练,基本上能阅读国外专业书刊;\n" + "必须掌握计算机相关知识,熟练使用仿真工具MATLAB等,必须会一门编程语言。\n" + "\n" + "2研究方向\n" + "视频算法工程师、图像处理算法工程师、音频算法工程师 通信基带算法工程师\n" + "\n" + "3目前国内外状况\n" + "目前国内从事算法研究的工程师不少,但是高级算法工程师却很少,是一个非常紧缺的专业工程师。" + "算法工程师根据研究领域来分主要有音频/视频算法处理、图像技术方面的二维信息算法处理和通信物理层、" + "雷达信号处理、生物医学信号处理等领域的一维信息算法处理。\n" + "在计算机音视频和图形图像技术等二维信息算法处理方面目前比较先进的视频处理算法:机器视觉成为此类算法研究的核心;" + "另外还有2D转3D算法(2D-to-3D conversion),去隔行算法(de-interlacing),运动估计运动补偿算法" + "(Motion estimation/Motion Compensation),去噪算法(Noise Reduction),缩放算法(scaling)," + "锐化处理算法(Sharpness),超分辨率算法(Super Resolution),手势识别(gesture recognition),人脸识别(face recognition)。\n" + "在通信物理层等一维信息领域目前常用的算法:无线领域的RRM、RTT,传送领域的调制解调、信道均衡、信号检测、网络优化、信号分解等。\n" + "另外数据挖掘、互联网搜索算法也成为当今的热门方向。\n" + "算法工程师逐渐往人工智能方向发展。"; var phraseList = HanLP.extractPhrase(content, 5).ToList(); Console.WriteLine(phraseList); }
/// <summary> /// 内部采用TextRankKeyword实现,用户可以直接调用TextRankKeyword.getKeywordList(document, size) /// 《TextRank算法提取关键词的Java实现》 /// https://www.hankcs.com/nlp/textrank-algorithm-to-extract-the-keywords-java-implementation.html /// </summary> /// <param name="content"></param> public void ExtractKeyword(string content) { content = "程序员(英文Programmer)是从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统分析员和项目经理四大类。"; var keywordList = HanLP.extractKeyword(content, 5); Console.WriteLine(keywordList); }
/// <summary> /// CustomDictionary是一份全局的用户自定义词典,可以随时增删,影响全部分词器。 /// CustomDictionary主词典文本路径是data/dictionary/custom/CustomDictionary.txt, /// 用户可以在此增加自己的词语(不推荐); /// 也可以单独新建一个文本文件, /// 通过配置文件CustomDictionaryPath=data/dictionary/custom/CustomDictionary.txt; /// 我的词典.txt;来追加词典(推荐)。 /// 始终建议将相同词性的词语放到同一个词典文件里,便于维护和分享。 /// 词典格式 ///每一行代表一个单词,格式遵从[单词][词性A][A的频次][词性B][B的频次] ... 如果不填词性则表示采用词典的默认词性。 ///词典的默认词性默认是名词n,可以通过配置文件修改:全国地名大全.txt ns; 如果词典路径后面空格紧接着词性,则该词典默认是该词性。 ///关于用户词典的更多信息请参考词典说明一章。 ///《Trie树分词》https://www.hankcs.com/program/java/tire-tree-participle.html ///《Aho Corasick自动机结合DoubleArrayTrie极速多模式匹配》 ///https://www.hankcs.com/program/algorithm/aho-corasick-double-array-trie.html /// </summary> /// <param name="str"></param> public void Segement_CustomerDic(string str) { // 动态增加 CustomDictionary.add("攻城狮"); // 强行插入 CustomDictionary.insert("白富美", "nz 1024"); // 删除词语(注释掉试试) // CustomDictionary.remove("攻城狮"); Console.WriteLine(CustomDictionary.add("单身狗", "nz 1024 n 1")); Console.WriteLine(CustomDictionary.get("单身狗")); string text = "攻城狮逆袭单身狗,迎娶白富美,走上人生巅峰"; // 怎么可能噗哈哈! // DoubleArrayTrie分词 var arrayTrieHit = new AhoCorasickDoubleArrayTrieHitEx(text); CustomDictionary.parseText(text, arrayTrieHit); // 首字哈希之后二分的trie树分词 BaseSearcher searcher = CustomDictionary.getSearcher(text); var entry = searcher.next(); while (entry != null) { Console.WriteLine(entry); entry = searcher.next(); } // 标准分词 Console.WriteLine(HanLP.segment(text)); // Note:动态增删不会影响词典文件 // 目前CustomDictionary使用DAT储存词典文件中的词语,用BinTrie储存动态加入的词语,前者性能高,后者性能低 // 之所以保留动态增删功能,一方面是历史遗留特性,另一方面是调试用;未来可能会去掉动态增删特性。 }
/// <summary> /// 词性标注 /// </summary> public void demo_pos_tagging() { //未标注: [教授/nnt, 正在/d, 教授/nnt, 自然语言处理/nz, 课程/n] // 标注后: [教授/nnt, 正在/d, 教授/v, 自然语言处理/nz, 课程/n] var text = "教授正在教授自然语言处理课程"; var segment = HanLP.newSegment(); print("未标注:", segment.seg(text)); segment.enablePartOfSpeechTagging(true); print("标注后:", segment.seg(text)); }
/// <summary> /// 拼音转换 /// anLP不仅支持基础的汉字转拼音,还支持声母、韵母、音调、音标和输入法首字母首声母功能。 ///HanLP能够识别多音字,也能给繁体中文注拼音。 ///最重要的是,HanLP采用的模式匹配升级到AhoCorasickDoubleArrayTrie,性能大幅提升,能够提供毫秒级的响应速度! ///《汉字转拼音与简繁转换的Java实现》 ///https://www.hankcs.com/nlp/java-chinese-characters-to-pinyin-and-simplified-conversion-realization.html#h2-17 /// </summary> public void PinYinCollection() { String text = "重载不是重任"; List <Pinyin> pinyinList = HanLP.convertToPinyinList(text).ToList <Pinyin>(); Console.WriteLine($"原文,{text}"); Console.WriteLine("拼音(数字音调),"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin},"); } Console.WriteLine("拼音(符号音调),"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin.getPinyinWithToneMark()},"); } Console.WriteLine("拼音(无音调),"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin.getPinyinWithoutTone()},"); } Console.WriteLine("声调,"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin.getTone()},"); } Console.WriteLine("声母,"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin.getShengmu()},"); } Console.WriteLine("韵母,"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin.getYunmu()},"); } Console.WriteLine("输入法头,"); foreach (Pinyin pinyin in pinyinList) { Console.WriteLine($"{pinyin.getHead()},"); } }
/// <summary> /// 日本人名识别 /// 目前标准分词器默认关闭了日本人名识别,用户需要手动开启;这是因为日本人名的出现频率较低,但是又消耗性能。 /// 《层叠隐马模型下的音译人名和日本人名识别》 /// https://www.hankcs.com/nlp/name-transliteration-cascaded-hidden-markov-model-and-japanese-personal-names-recognition.html /// </summary> /// <param name="str"></param> public void JapaneseNameRecognize(string str) { string[] testCase = new string[] { "一桶冰水当头倒下,微软的比尔盖茨、Facebook的扎克伯格跟桑德博格、亚马逊的贝索斯、苹果的库克全都不惜湿身入镜,这些硅谷的科技人,飞蛾扑火似地牺牲演出,其实全为了慈善。", "世界上最长的姓名是简森·乔伊·亚历山大·比基·卡利斯勒·达夫·埃利奥特·福克斯·伊维鲁莫·马尔尼·梅尔斯·帕特森·汤普森·华莱士·普雷斯顿。", }; Segment segment = HanLP.newSegment().enableJapaneseNameRecognize(true); foreach (var sentence in testCase) { var termList = segment.seg(sentence); Console.WriteLine(termList); } }
/// <summary> /// 目前分词器默认关闭了机构名识别,用户需要手动开启;这是因为消耗性能,其实常用机构名都收录在核心词典和用户自定义词典中。 /// HanLP的目的不是演示动态识别,在生产环境中,能靠词典解决的问题就靠词典解决,这是最高效稳定的方法。 /// https://www.hankcs.com/nlp/name-transliteration-cascaded-hidden-markov-model-and-japanese-personal-names-recognition.html /// </summary> /// <param name="str"></param> public void OrganizationRecognize(string str) { string[] testCase = new string[] { "我在上海林原科技有限公司兼职工作,", "我经常在台川喜宴餐厅吃饭,", "偶尔去地中海影城看电影。", }; Segment segment = HanLP.newSegment().enableOrganizationRecognize(true); foreach (var sentence in testCase) { var termList = segment.seg(sentence); Console.WriteLine(termList); } }
/// <summary> /// 提取关键字与寨蒿 /// </summary> public void ExtractSummary() { var content = "商品和服务,"; content += "结婚的和尚未结婚的确实在干扰分词啊,"; content += "买水果然后来世博园最后去世博会,"; content += "中国的首都是北京,"; content += "欢迎新老师生前来就餐,"; content += "工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作,"; content += "随着页游兴起到现在的页游繁盛,依赖于存档进行逻辑判断的设计减少了,但这块也不能完全忽略掉。"; //提取关键字 Console.WriteLine(HanLP.extractKeyword(content, 2)); // 自动摘要 Console.WriteLine(HanLP.extractSummary(content, 2)); Console.WriteLine(HanLP.parseDependency("徐先生还具体帮助他确定了把画雄鹰、松鼠和麻雀作为主攻目标。")); }
/// <summary> /// 中国人名识别 /// 目前分词器基本上都默认开启了中国人名识别,比如HanLP.segment()接口中使用的分词器等等,用户不必手动开启; /// 代码只是为了强调。 ///有一定的误命中率,比如误命中关键年,则可以通过在data/dictionary/person/nr.txt加入一条关键 ///年 A 1来排除关键年作为人名的可能性,也可以将关键年作为新词登记到自定义词典中。 ///《实战HMM-Viterbi角色标注中国人名识别》 ///https://www.hankcs.com/nlp/chinese-name-recognition-in-actual-hmm-viterbi-role-labeling.html /// </summary> /// <param name="str"></param> public void NameRecognize(string str) { string[] testCase = new string[] { "签约仪式前,秦光荣、李纪恒、仇和等一同会见了参加签约的企业家。", "王国强、高峰、汪洋、张朝阳光着头、韩寒、小四", "张浩和胡健康复员回家了", "王总和小丽结婚了", "编剧邵钧林和稽道青说", "这里有关天培的有关事迹", "龚学平等领导,邓颖超生前", }; Segment segment = HanLP.newSegment().enableNameRecognize(true); foreach (string sentence in testCase) { var termList = segment.seg(sentence); Console.WriteLine(termList); } }
/// <summary> /// 第一个demo /// </summary> /// <param name="str"></param> public void Segement(string str) { var docList = HanLP.segment(str).ToList(); Console.WriteLine(docList); }
/// <summary> /// 简繁转换 /// HanLP能够识别简繁分歧词,比如打印机=印表機。许多简繁转换工具不能区分“以后”“皇后”中的两个“后”字,HanLP可以。 /// 《汉字转拼音与简繁转换的Java实现》https://www.hankcs.com/nlp/java-chinese-characters-to-pinyin-and-simplified-conversion-realization.html#h2-17 /// </summary> public void TraditionalChineseCollection() { Console.WriteLine(HanLP.convertToTraditionalChinese("用笔记本电脑写程序")); Console.WriteLine(HanLP.convertToSimplifiedChinese("「以後等妳當上皇后,就能買士多啤梨慶祝了」")); }