jiebaNET中文分词器

  最近我接手了一个有趣的需求,需要对用户评价进行分词,进行词频统计和情绪分析,并且根据词频权重制成词云图以供后台数据统计,于是我便引入了jieba分词器,但是我发现网上关于jiebaNET相关文档实在太少了,甚至连配置文件都很难搞清楚,所以我来大家介绍一下jiebaNET。

jiebaNET分词器介绍:

ieba.NET分词器是一款基于.NET平台的中文分词工具,它借鉴了jieba分词器的算法和思路,为.NET开发者提供了高效、准确的中文分词功能。jieba.NET分词器的主要功能和特点如下:

  1. 中文分词:jieba.NET分词器能够将中文文本按照词语进行切分,使得文本更易于被处理和分析。分词是中文文本处理的基础步骤,对于词频统计、文本分类、情感分析等任务具有重要意义。
  2. 多种分词模式:jieba.NET分词器支持多种分词模式,包括精确模式、全模式和搜索引擎模式。精确模式会将句子最精确地切分开,适合在文本分析时使用;全模式会将句子中所有成词的词语都扫描出来,速度非常快,但可能产生歧义;搜索引擎模式会在精确模式的基础上对长词再进行切分,提高召回率,适用于搜索引擎等场景。
  3. 自定义词典:jieba.NET分词器允许用户创建自定义词典,以确保特定词汇被正确切分。这对于处理特定行业或领域的文本非常有用,可以提高分词的准确性和效率。
  4. 高效快速:jieba.NET分词器采用了高效的分词算法和优化的数据结构,可以让分词速度非常快,能够满足大规模文本处理的需求。
  5. 接口友好:jieba.NET分词器提供了简洁易用的API接口,开发者可以方便地将其集成到自己的.NET项目中,进行中文文本处理和分析。

分词

字典文件存储在Resources中的dict.txt文件中,其中:

  • “一个系列”是词条,也就是一个词语或者短语,是词典中存储的实际内容。
  • “14”通常是这个词的词频,表示这个词在语料库中出现的次数或者重要程度。较高的词频意味着这个词在语料中较为常见。
  • “m”代表词性标注,用来描述这个词的语法角色或词汇类别。在中文词性标注体系中,“m”通常代表“数词”,用于表示数量或序数的词语,比如“一个”、“两个”、“第一次”等

使用方法:

jieba.NET程序集中与分词相关的主要是JiebaSegmenter.Cut函数和JiebaSegmenter. CutForSearch函数,这两个函数都以字符串作为分词输入,不像之前盘古分词支持流式输入。

 public IEnumerable<string> Cut(string text, bool cutAll = false, bool hmm = true)
public IEnumerable<string> CutForSearch(string text, bool hmm = true)

基于这两个函数,jieba.NET支持多种分词模式:全模式(把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义)、精确模式(试图将句子最精确地切开)、搜索引擎模式(在精确模式的基础上,对长词再次切分,提高召回率)。这三种方式的代码其实都比较简单,如下所示:

 string textstr = txtContent.Text;
 txtResult.Text= textstr;
 var segmenter = new JiebaSegmenter();
 if (RadioButtonListType.SelectedValue == "jz")
 {
     var segments = segmenter.Cut(textstr,cutAll:false,hmm:false);
     txtResult.Text = "【精准模式】:" + string.Join("/ ", segments);
     //他/ 来到/ 上海交通大学
 }
 else if (RadioButtonListType.SelectedValue == "jzhmm")
 {
     var segments = segmenter.Cut(textstr, cutAll: false, hmm: false);
     txtResult.Text = "【精准模式、新词识别】:" + string.Join("/ ", segments);
 }	//新词识别:"我/ 在/ 玩/ 某某/ 游戏/ 时/ 遇到/ 了/ 一个/ 名叫/ 小明/ 的/ 玩家/ 。"
//"某某"和"小明"可能是游戏中的特定角色或者玩家的ID,不在默认词典中。启用了新词识别功能后,结巴分词器可能会尝试将它们识别为新词,并进行分割
 else if (RadioButtonListType.SelectedValue == "cutAll")
 {
     var segments = segmenter.Cut(textstr, cutAll: true);
     txtResult.Text = "【全模式】:" + string.Join("/ ", segments);
     //【全模式】:他/ 来到/ 上海/ 上海交通大学/ 交通/ 大学

 }
 else if (RadioButtonListType.SelectedValue == "CutForSearch")
 {
     var segments = segmenter.CutForSearch(textstr,  true);
     txtResult.Text = "【搜索引擎模式】:" + string.Join("/ ", segments);
     //他/ 毕业/ 于/ 上海/ 交通/ 大学/ 上海交通大学/ 机电/ 系/ ,/ 后来/ 在/ 一机部/ 上海/ 电器/ 科学/ 研究/ 研究所/ 工作
 }

关键词提取

jieba.NET支持通过两种算法提取文本关键词:TF-IDF算法TextRank算法,关于这两种算法的介绍详见参考文献10-11,在jieba.NET中对应的类为TfidfExtractorTextRankExtractor,这两个分词都都支持调用ExtractTagsExtractTagsWithWeight函数,前者默认返回前20个关键词,后者还附带每个关键词的权重。

权重逆文档频率存储在Resources/idf.txt文件中:如下图所示:

代码如下:

  //不带权重
  txtResult.Text = String.Empty;
  using (TextReader tr = File.OpenText(txtPath.Text))
  {
      TfidfExtractor extractor = new TfidfExtractor();
      var keywords=extractor.ExtractTags(tr.ReadToEnd());
      txtResult.Text = string.Join("/ ", keywords);
  }
  
  //带权重
  txtResult.Text = String.Empty;
  using (TextReader tr = File.OpenText(txtPath.Text))
   {
       TfidfExtractor extractor = new TfidfExtractor();
       IEnumerable<WordWeightPair> results = extractor.ExtractTagsWithWeight(tr.ReadToEnd());
       foreach (WordWeightPair p in results)
       {
           txtResult.Text +=  p.Word + "," + p.Weight.ToString()+ "\r\n";
       }   
    }

TextRankExtractor类的示例代码及运行效果如下所示,对比可以看出这两种算法的返回结果还是存在差异:

  //不带权重
  txtResult.Text = String.Empty;
  using (TextReader tr = File.OpenText(txtPath.Text))
  {
      TextRankExtractorextractor = new TextRankExtractor();
      var keywords=extractor.ExtractTags(tr.ReadToEnd());
      txtResult.Text = string.Join("/ ", keywords);
  }
  
  //带权重
  txtResult.Text = String.Empty;
  using (TextReader tr = File.OpenText(txtPath.Text))
   {
       TextRankExtractorextractor = new TextRankExtractor();
       IEnumerable<WordWeightPair> results = extractor.ExtractTagsWithWeight(tr.ReadToEnd());
       foreach (WordWeightPair p in results)
       {
           txtResult.Text +=  p.Word + "," + p.Weight.ToString()+ "\r\n";
       }   
    }

并行分词

"并行分词" 意味着可以同时处理多个文本或文本集合的分词任务,以提高分词速度和效率。在处理大量文本数据时特别有用,可以利用多核处理器的并行能力,加速分词过程。

JiebaSegmenter类的CutInParallelCutForSearchInParallel函数支持并行分词

  1. CutInParallel: 这个函数用于普通的分词任务。它可以同时处理一个字符串集合单个字符串,并将其分词后返回结果。如果输入是单个字符串,Jieba.NET 会自动将其按行转换为字符串集合,然后并行进行分词处理。
  2. CutForSearchInParallel: 这个函数用于搜索引擎模式的分词任务。类似于 CutInParallel,它也支持并行处理,但会采用搜索引擎模式进行分词,以适应搜索引擎等应用场景的需求。

设置停用词

提取关键词时,部分词语可能不重要或者并非所需的词语,此时可以通过设置停用词,在提取关键词时过滤掉指定的停用词。jieba.NET的停用词词库放在Resources文件夹下的stopwords.txt,程序启动时会自动加载该文件。 以之前的测试文本为例,提取前20个关键词,将其中的“一声”、“一脉”两次设置停用词,即在stopwords.txt后追加这两词,再次运行程序提取关键词,可以看到这两个词已经消息

词性标注

jieba.NET中的PosSegmenter类支持在分词的同时,为每个词添加词性标注,词性标注的含义表如下所示:

  • segmenter.Tokenize(text) 返回的是一个 IEnumerable<WordToken>,其中每个 WordToken 对象包含了词语、词性以及词语在原始文本中的起始位置。

1.在Resource的char_state_tab.json文件下存储了针对Unicode字符到其可能的词性的映射关系

2.在pos_prob_emit.json文件下存储了不同“词性”在遇到特定汉字时可能出现的概率大小,内容如图所示:

(这个指南不是直接给概率值,而是给了“负对数似然度”,你可以把它想象成衡量“不寻常程度”的一个指标——数值越小,表示这种情况越常见、越合理。)比如"E-e"下面"\u5440"的值是-0.65302718677052,意思是当某个词性是"E-e"时,汉字“\u5440”出现的概率相对较大,因为这个数字相比其他很多值是比较接近0的,也就是比较“不罕见”。

3.pos_prob_start.json /prob_emit.json 文件是用于存储词性标注模型中不同词性状态的先验概率或转移概率的数据。在自然语言处理任务,尤其是词性标注(Part-of-Speech Tagging)中,这样的文件起着至关重要的作用。(百度解释,不是太明白)

这个文件中的内容是每个词性对应的状态转移概率,以及每个状态的概率。每个词性都有一个对应的标识,比如 "E-e"、"E-d"、"S-rg" 等,这些标识可能是分别表示着不同的词性。而每个标识后面的数值则表示了该词性转移到下一个词性的概率,或者是该词性在句子中出现的概率。

4.pos_prob_trans/prob_trans.json 记录了不同词性之间的转移概率。其中,每个词性(比如 "E-e")后面跟着一个对象,对象的键是可能的下一个词性,而对应的值则是从当前词性转移到下一个词性的概率。例如,对于词性 "E-e",它可以转移到的词性有 "S-nr"、"S-ng"、"B-rz"、"B-mq" 等等,对应着不同的转移概率。这些值是负对数形式,数值越小代表从当前词性转移到目标词性的概率越高。

获取分词词语的起始位置

jieba.NET中的JiebaSegmenter类的Tokenize函数除了返回分词词语之外,还会返回每个分词词语的起止位置。该函数支持默认模式搜索模式两种分词方式,根据官网说明及测试,默认模式类似于分词函数的精确模式分词,每个词语只会被分一次,而搜索模式类似于全模式及搜索引擎模式分词,把所有可能的分词形式都返回。代码使用如下所示

using JiebaNet.Segmenter;
using System;

class Program
{
    static void Main(string[] args)
    {
        var segmenter = new JiebaSegmenter();
        
        // 默认模式下的分词及位置信息
        var tokensDefaultMode = segmenter.Tokenize("我爱自然语言处理");
        foreach (var token in tokensDefaultMode)
        {
            Console.WriteLine($"Word: {token.Word}, Start Index: {token.StartIndex}, End Index: {token.EndIndex}");
        }
        
        // 搜索模式下的分词及位置信息
        var tokensSearchMode = segmenter.Tokenize("我爱自然语言处理", TokenizerMode.Search);
        foreach (var token in tokensSearchMode)
        {
            Console.WriteLine($"Word: {token.Word}, Start Index: {token.StartIndex}, End Index: {token.EndIndex}");
        }
    }
}

查找关键词

jieba.NET中的KeywordProcessor类预先指定的一组关键词,然后在指定的文本中查找存在哪些关键词,也即查找指定的关键词在文本中是否存在。

添加自定义词典

自定义词典,以便包含jeba词库里面没有的词,格式如下:

创新办 3 i

云计算 5

凱特琳 nz

载入词典

使用jieba,load_userdict(file_name)即可载入词典

动态调整词典

结巴分词器(Jieba)提供了 add_word(word, freq=None, tag=None)del_word(word) 这两个方法,允许在程序运行过程中动态修改词典,以满足特定的需求。

  • add_word(word, freq=None, tag=None): 这个方法用于向分词器的词典中添加新的词语。可以指定词语的频率(freq)和词性(tag),如果不指定频率和词性,则默认使用内部规则进行设置。这样一来,当分词器进行分词时,就可以识别和使用这些新增的词语了。
  • del_word(word): 这个方法用于从分词器的词典中删除指定的词语。这在某些情况下可能很有用,比如当某些词语被错误地添加到词典中,或者需要动态地调整词典以适应不同的场景。

词频统计

词频统计功能可以计算文本中每个词语出现的频率以及统计词语的数量,这对文本分析、关键词提取、文本摘要等任务都非常有用。

Jieba 中的 cut 函数用于对文本进行分词,而分词后的结果可以通过 Counter 类进行词频统计。Counter 类可以统计一个可迭代对象中各个元素出现的次数。

using JiebaNet.Segmenter;
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        // 创建 JiebaSegmenter 实例
        var segmenter = new JiebaSegmenter();

        // 文本
        string text = "我爱自然语言处理,自然语言处理也很有趣。";

        // 分词
        var segments = segmenter.Cut(text);

        // 统计词频
        var wordCounts = segments.GroupBy(x => x)
                                 .ToDictionary(g => g.Key, g => g.Count());

        // 输出词频统计结果
        foreach (var pair in wordCounts)
        {
            Console.WriteLine($"词语: {pair.Key},频率: {pair.Value}");
        }
    }
}

那么如何按照词频绘制词云图呢?我们下章就为大家讲解!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/629857.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2.1.2 C++程序设计——程序基本概念

文章目录 展示大纲1、程序基本概念2、基本数据类型3、程序基本语句4、基本运算5、数学库常用函数6、结构化程序设计展示大纲 1、程序基本概念

分享开放原子AtomGit开源协作平台评测报告

AtomGit平台的总体介绍 开放原子开源基金会是致力于推动全球开源事业发展的非营利机构&#xff0c;于 2020 年 6 月在北京成立&#xff0c;由阿里巴巴、百度、华为、浪潮、360、腾讯、招商银行等多家龙头科技企业联合发起。目前有三个主要机构设置&#xff0c;技术监督委员会&…

3-3 基于RYU的流量风暴事件原理与响应策略

在传统网络中&#xff0c;存在着一定的广播流量&#xff0c;占据了一部分的网络带宽。同时&#xff0c;在有环的拓扑中&#xff0c;如果不运行某些协议&#xff0c;广播数据还会引起网络风暴&#xff0c;使网络瘫痪。 如有以下的一个网络拓扑结构&#xff08;3_2_topoplus.py) …

武汉星起航:亚马逊构建综合性商业生态,卖家买家共享全球化红利

在当今全球化日益加速的时代&#xff0c;亚马逊不仅以其卓越的电商平台服务全球消费者&#xff0c;更通过一系列前沿服务打造了一个综合性的商业生态系统。在这个生态系统中&#xff0c;卖家能够轻松拓展全球业务&#xff0c;买家则享受到了前所未有的购物体验。亚马逊以其独特…

CCF-Csp算法能力认证, 202309-1坐标变换(其一)(C++)含解析

前言 推荐书目&#xff0c;在这里推荐那一本《算法笔记》&#xff08;胡明&#xff09;&#xff0c;需要PDF的话&#xff0c;链接如下 「链接&#xff1a;https://pan.xunlei.com/s/VNvz4BUFYqnx8kJ4BI4v1ywPA1?pwd6vdq# 提取码&#xff1a;6vdq”复制这段内容后打开手机迅雷…

js之选项卡制作实例

大家好&#xff0c;今天给大家书写选项卡实例&#xff0c;话不多说&#xff0c;直接上干货 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

Vue.js的发展史(一)

Vue.js的发展史&#xff08;一&#xff09; 什么是Vue? Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发…

electron进程间通信

Electron 应用程序的结构非常相似。 作为应用开发者&#xff0c;你将控制两种类型的进程&#xff1a;主进程 和 渲染器进程。 这类似于上文所述的 Chrome 的浏览器和渲染器进程。 主进程 每个 Electron 应用都有一个单一的主进程&#xff0c;作为应用程序的入口点。 主进程在 N…

(实测验证)【移远EC800M-CN 】GNSS功能打开和关闭关闭步骤验证

引言 本文章使用自研“超小体积TTL转4GGPS集成模块”进行实测验证&#xff1b; 一、打开GNSS功能 步骤一、通过 ATQGPSCFG 配置 GNSS 参数 &#xff08;1&#xff09;该命令用于查询和配置 GNSS 不同的设置&#xff0c;包括 NMEA 语句输出端口、NMEA 语句的输出类型等。 1.1…

栈和队列经典面试题详解

目录 题目一&#xff1a;20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 题目二&#xff1a;225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 题目三&#xff1a;232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 题目四&#xff1a;622. 设…

【董晓算法】动态规划之线性DP问题

前言&#xff1a; 本系列是看的B站董晓老师所讲的知识点做的笔记 董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com) 树塔-记忆化搜索 特点&#xff08;前提&#xff09;&#xff1a;从上向下的累加和是不能重复使用的&#xff0c;从下向上的累加和是可以重…

抖音电商发展受限,视频号反而成了短视频电商风口?这是为什么?

哈喽~我是电商月月 抖音小店发展的如火如荼间&#xff0c;视频号也正式推出了自己的电商平台 视频号小店的推出&#xff0c;引的众多商家讨论 很多人都觉得视频号的流量比不过抖音&#xff0c;玩互联网的人群【年轻群体】都集中在抖音上了&#xff0c;有抖音在&#xff0c;视…

动态规划算法:⼦序列问题(数组中不连续的⼀段)

例题一 解法&#xff08;动态规划&#xff09;&#xff1a; 算法思路&#xff1a; 1. 状态表⽰&#xff1a; 对于线性 dp &#xff0c;我们可以⽤「经验 题⽬要求」来定义状态表⽰&#xff1a; i. 以某个位置为结尾&#xff0c;巴拉巴拉&#xff1b; ii. 以某个位置…

【EasyX】快速入门——静态图形篇

1.基本说明 EasyX 是针对 C 的图形库&#xff0c;可以帮助 C/C 初学者快速上手图形和游戏编程。 比如&#xff0c;可以基于 EasyX 图形库很快的用几何图形画一个房子&#xff0c;或者一辆移动的小车&#xff0c;可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏&#xff0c;可以练…

类和对象的特性

1.检查错误。 代码&#xff1a; #include <iostream>using namespace std;class Time { private:/* data */ public:Time(/* args */);~Time();void set_time(void);void show_time(void);int hour;int minute;int sec; };Time::Time(/* args */) { }Time::~Time() { }T…

Java环境搭配(一)JDK下载以及介绍、path环境变量配置

目录 JDK Development Kit &#xff08;JDK&#xff09; 下载 JDK介绍 &#xff1a; JDK 包括以下主要组件 配置path环境变量 在cmd上打印Helloworld JDK Development Kit &#xff08;JDK&#xff09; 下载 下载官方地址 www.oracle.com 进入网址后&#xff1a; 点击产…

指针在函数的应用(C++)

一、传递地址 实参传递进函数体内后&#xff0c;生成的是实参的副本&#xff0c;在函数内改变副本的值并不影响实参。指针传递参数时&#xff0c;指针变量产生了副本&#xff0c;但副本与原变量指向的内存区域是同一个。改变指针副本指向的变量&#xff0c;就是改变原指针变量指…

快速查看字符对应的ASCII码

1、借助gdb查看 打印字符串用双引号括起来打印单个字符用单引号括起来x 表示十六机制d 表示十进制t 表示二进制 2、借助二进制查看软件 第一步&#xff1a;把要查看的字符保存到文本文件中第二步&#xff1a;借助二进制查看工具&#xff08;比如&#xff1a;Hex Editor Neo&am…

字节跳动在2024年春季火山引擎Force原动力大会上隆重推出了“豆包大模型”家族

此次大会以AI为主题&#xff0c;聚焦大模型的应用与发展&#xff0c;旨在引领AI技术的落地和推动各行各业的数字化转型。 字节跳动官网&#xff1a;https://www.bytedance.com/zh/ 豆包官网&#xff1a;https://www.doubao.com/chat/ 更多消息&#xff1a;https://heehel.co…

Redis实战—验证码登录注册

目录 基于Session Controller层 Service层 ServiceImpl层 ​编辑校验登录状态 ThreadLocal 登录拦截器 添加拦截器到Config Controller层实现 基于Redis ServiceImpl 新增刷新拦截器 添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMappi…