news 2026/6/30 1:17:49

LLM系列:4.transformer算法:3.Jieba

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LLM系列:4.transformer算法:3.Jieba

Jieba

一.认识Jieba

Jieba 是目前表现较为不错的、立志于做最好的 Python 中文分词组件。它不仅支持多种分词模式,还支持自定义词典和繁体分词,且采用 MIT 授权协议。

安装与导入 Jieba:可以直接通过 pip 进行安装,支持 Python 2/3。

# 安装pip3 install jieba# 导入importjieba

二.Jieba的分词原理与步骤

jieba分词综合了基于字符串匹配的算法和基于统计的算法。其主要底层算法及分词步骤如下:

  • 初始化与加载:加载词典文件,获取每个词语和它出现的词数。
  • 切分短语:利用正则,将文本切分为一个个语句,之后对语句进行分词。
  • 构建DAG (有向无环图):基于前缀词典实现高效的词图扫描,通过字符串匹配,构建所有可能的分词情况的有向无环图 (DAG)。
  • 计算最大概率路径:采用了动态规划查找最大概率路径,找出基于词频的最大切分组合;同时计算每个汉字节点到语句结尾的所有路径中的最大概率,并记下对应位置。
  • 构建切分组合:根据节点路径,得到最终的词语切分结果。
  • HMM新词处理:对于未登录词 (dict.txt中没有的词语),采用基于汉字成词能力的 HMM (隐马尔科夫) 模型来处理,并使用了 Viterbi 算法。
  • 返回结果:通过yield将切分好的词语逐个返回,相较于直接返回list,这可以节约存储空间。

三.Jieba 的核心类与属性

jieba的底层设计中,大多数直接调用的模块级方法(如jieba.cut)实际上是代理给了默认实例化的核心类。

1. 核心类 (Classes)
  • jieba.Tokenizer: 这是jieba的核心分词器类。每次import jieba时,模块会自动创建一个默认的Tokenizer实例(即jieba.dt)。如果你在多线程环境或需要隔离的词典环境,可以自行实例化这个类(例如my_tokenizer = jieba.Tokenizer(dictionary="..."))。
  • jieba.posseg.POSTokenizer: 专门用于词性标注的分词器类,继承/组合了基础的分词能力并集成了词性标注模型。
  • jieba.analyse.TFIDF/jieba.analyse.TextRank: 用于关键词提取的评估类。
2. 核心属性 (Attributes)

通常不建议直接操作底层属性,但了解它们有助于理解原理:

  • jieba.dt: 默认的Tokenizer实例,所有全局方法(jieba.cut等)都在操作这个实例。
  • jieba.dt.FREQ: 一个 Python 字典,存储了加载的词库中所有词语及其对应的词频(包括前缀词)。
  • jieba.dt.total: 统计出的所有词汇的总词频(用于计算概率分布)。
  • jieba.dt.initialized: 布尔值,标识词典是否已经被加载和初始化。

四.Jieba 的分词模式

Jieba 库支持以下四种主要的分词模式:

分词模式描述与特点
精确模式试图将文本精确地切分成若干个中文单词,最精确地还原为之前的文本。适合文本分析,其中不存在冗余单词。
全模式将一段文本中所有可能的、可以成词的词语都扫描出来。速度非常快,但不能解决歧义,分词后的信息组合起来会有冗余。
搜索引擎模式在精确模式的基础上,对发现的长词再次进行切分,从而提高召回率。适合用于搜索引擎分词和索引,同样会存在冗余。
paddle模式通过延迟加载方式,在安装paddlepaddle-tiny后提供的模式。

1. 精确模式 (Precise Mode)

这是 Jieba 的默认模式,也是日常开发中最常用的模式。

  • 核心机制:它会结合基于词典的 DAG(有向无环图)最大概率路径算法,以及基于 HMM(隐马尔可夫模型)的 Viterbi 算法来处理未登录词。系统会力求根据上下文找到一条唯一且最合理的切分路径。
  • 特点:毫无冗余,句子中的每个字只会属于一个词,最终组合起来能完美还原原文。
  • 适用场景:绝大多数常规的自然语言处理(NLP)任务,如文本特征提取、情感分析、文本分类、词云生成等,因为它能最大程度保留句子的正常语义。
  • 调用方式
jieba.cut(text,cut_all=False)# 默认就是 False

2. 全模式 (Full Mode)

顾名思义,这是一种“地毯式搜索”的暴力模式。

  • 核心机制:主要依赖纯词典匹配,把句子中从每一个位置开始,只要能和词典匹配上的词全部扫描出来。它不考虑上下文语境,也不会开启 HMM 模型去猜测新词。
  • 特点:切分速度极快(因为跳过了复杂的概率计算),但分词结果会有大量的重叠和冗余,完全不具备解决词义歧义的能力。
  • 适用场景:对处理速度要求极高,且需要极高“召回率”(宁可错杀一千,不可放过一个)的粗粒度文本扫描任务。通常不适合直接用于语义分析。
  • 调用方式
jieba.cut(text,cut_all=True)

3. 搜索引擎模式 (Search Engine Mode)

这是在“精确模式”基础上做加法的一种模式,专门为了解决搜索场景痛点而生。

  • 核心机制:属于“二次加工”。它首先在底层执行一次精确模式,然后对精确切分出来的长词(通常指长度大于 2 的词)进行再次拆解,提取出其中包含的更短的词汇。
  • 特点:在保留基础语义环境的同时,增加了细粒度词汇的输出。
  • 适用场景:专门用于构建搜索引擎的倒排索引(如配合 Elasticsearch 等使用)。在搜索场景下,用户经常只输入长词的一部分(比如原文是“计算机科学”,用户可能只搜“计算”),这种模式能确保长短词汇都能被索引到,显著提升搜索命中率。
  • 调用方式
jieba.cut_for_search(text)

4. Paddle模式 (Paddle Mode)

引入了深度学习框架,是 Jieba 拥抱神经网络架构的一种扩展模式。

  • 核心机制:脱离了传统的词典统计与概率推算,底层直接调用了百度飞桨(PaddlePaddle)预训练的深度学习序列标注模型(通常基于 BiGRU+CRF 架构)。
  • 特点:在处理长难句、解决复杂语境歧义、以及发现未登录词(新词、专有名词、网络梗)方面表现远超基础模式,且可以同时输出高精度的词性标注。但缺点是依赖较重,初次启动和运行速度比传统词典法慢,资源消耗更大。
  • 适用场景:对分词准确率要求极高、语料库包含大量非常规或新生词汇、且硬件资源允许的深度 AI 分析场景。
  • 调用方式
# 必须先安装 paddlepaddle-tinyjieba.enable_paddle()# 开启并加载模型jieba.cut(text,use_paddle=True)

五.基础分词方法

1. cut & lcut - 精确与全模式分词

作用:对目标文本进行精确模式或全模式的切分。cut返回一个可迭代的生成器,能够在处理长文本时节约内存;而lcut则直接将全部分词结果转化为列表返回。

jieba.cut(sentence,cut_all=False,HMM=True)jieba.lcut(sentence,cut_all=False,HMM=True)

参数:

  • 文本 (sentence): 需要分词的目标中文字符串(str)。
  • 全模式 (cut_all): 控制分词模式。设为False为精确模式(默认),设为True则为全模式(bool)。
  • 隐马尔可夫模型 (HMM): 是否开启HMM模型来识别未登录词(新词)。默认为True(bool)。
    • 关闭HMM(HMM=False),Jieba 遇到不认识的词时,就会极其生硬地把它们全部切碎成单独的汉字。
    • 开启HMM(HMM=True)后,即便词典里完全没有这个词,算法也能利用统计学规律和上下文的概率,“猜”出它可能是一个完整的词,并将其作为一个整体切分出来。

返回值:

  • 成功:cut返回生成器(generator);lcut返回由词汇字符串组成的列表(list[str])。

示例:

importjieba text="清华大学的计算机科学与技术专业"# 1.精确模式 (返回生成器,转化为list以便查看)seg_gen=jieba.cut(text,cut_all=False)print(list(seg_gen))# ['清华大学', '的', '计算机科学', '与', '技术', '专业']# 2.全模式 (直接返回列表)seg_list=jieba.lcut(text,cut_all=True)print(seg_list)# ['清华', '清华大学', '华大', '大学', '的', '计算', '计算机', '计算机科学', '算机', '科学', '与', '技术', '专业']

2. cut_for_search & lcut_for_search - 搜索引擎模式分词

作用:在精确模式的基础上,对发现的长词再次进行切分,提取出更细粒度的词汇,通常用于构建搜索引擎的倒排索引。cut_for_search返回一个可迭代的生成器;lcut_for_search则直接将全部分词结果转化为列表返回。

jieba.cut_for_search(sentence,HMM=True)jieba.lcut_for_search(sentence,HMM=True)

参数:

  • 文本 (sentence): 需要分词的目标字符串(str)。
  • 隐马尔可夫模型 (HMM): 是否开启 HMM 模型。默认为True(bool)。

返回值:

  • 成功:cut_for_search返回生成器(generator);lcut_for_search返回列表(list[str])。

示例:

importjieba text="清华大学的计算机科学与技术专业"seg_search_gen=jieba.cut_for_search(text)print("搜索引擎模式 (generator):",list(seg_search_gen))# ['清华', '华大', '大学', '清华大学', '的', '计算', '算机', '科学', '计算机', '计算机科学', '与', '技术', '专业']search_list=jieba.lcut_for_search(text)print("搜索引擎模式 (list):",search_list)# ['清华', '华大', '大学', '清华大学', '的', '计算', '算机', '科学', '计算机', '计算机科学', '与', '技术', '专业']

六.自定义词典与词频干预方法

在垂直领域(如医疗、法律、特定小说)中,系统自带的词典往往无法正确识别专业名词。此时需要介入干预 Jieba 的词库。

1. load_userdict - 加载外部自定义词典

作用:批量加载本地的自定义 TXT 词典文件,提升特定领域词汇的分词准确率。

jieba.load_userdict(file_name)

参数:

  • 文件路径 (file_name): 包含自定义词汇的文本文件路径(str 或 pathlib.Path)。

词典文件格式要求:一词占一行;每一行分为三部分:词语、词频(可省略)、词性(可省略),各部分之间用空格隔开。
示例:创新工场 3 n

返回值:

  • 无返回值,直接修改全局jieba.dt的内部状态。

2. add_word & del_word - 动态增删词汇

作用:在程序运行过程中,通过代码动态地向内存中的词典添加或移除特定词汇,而无需修改本地文件。

jieba.add_word(word,freq=None,tag=None)jieba.del_word(word)

参数:

  • 词汇 (word): 需要添加或删除的目标词语(str)。
  • 词频 (freq): 可选,指定该词的词频(int)。
  • 词性 (tag): 可选,指定该词的词性(str)。

示例:

text="我来到了庆国京都"print(jieba.lcut(text))# 可能被切成 ['我', '来到', '了', '庆国', '京都']jieba.add_word("庆国京都")print(jieba.lcut(text))# 变为 ['我', '来到', '了', '庆国京都']

3. suggest_freq - 调节单个词语词频

作用:自动计算并调节单个词语的词频,强制让系统能够(或不能)将某几个字作为一个词分出来。这是解决“误拆分”或“误合并”的最直接方法。

jieba.suggest_freq(segment,tune=True)

参数:

  • 词段 (segment): 需要干预的词汇。(str 或 tuple)。
    • 传入元组代表促使拆分,传入元组 (A, B) = “把 A 和 B 拆开,别连在一起!”
    • 传入单个字符串代表促使合并,传入字符串 “AB” = “把 A 和 B 锁死,这就是一个词!”
  • 调节启用 (tune): 是否立刻在内部词典中生效此词频调节。默认为True(bool)。
    • tune=True:既计算,又执行(修改内存)。
    • tune=False:只计算,不执行(只看结果)。

返回值:

  • 成功: 返回调节后的该词语(或字组)的新词频(int)。

示例:

importjieba# 一.拆分场景:强制将一个词拆开 (tuple)text="如果放到post中将出错"# --- 情况 A: tune=True (默认) ---# 强制拆分,并立即在分词器中生效jieba.suggest_freq(('中','将'),tune=True)print("tune=True 拆分结果:",jieba.lcut(text))# 结果: ['如果', '放到', 'post', '中', '将', '出错']# --- 情况 B: tune=False ---# 此时调用 suggest_freq 仅仅是计算了词频,但没有强制覆盖内存中的模型,# 因此分词效果可能不会发生改变,或者需要依赖后续更新jieba.suggest_freq(('中','将'),tune=False)print("tune=False 拆分结果:",jieba.lcut(text))# 结果: ['如果', '放到', 'post', '中将', '出错'] (效果未生效)# 二.合并场景:强制将两个字锁死为一个词 (str)text="我爱北京天安门"# 原始分词:系统可能会把 "天安门" 识别出来,但如果系统很笨,可能切成 ["天安", "门"]print("原始分词:",jieba.lcut(text))# --- 情况 A: tune=True ---# 强制把 "天安门" 作为一个整体jieba.suggest_freq("天安门",tune=True)print("tune=True 合并结果:",jieba.lcut(text))# 结果: ['我', '爱', '北京', '天安门']# --- 情况 B: tune=False ---# 调用了计算,但未应用到当前分词器的动态词典中jieba.suggest_freq("天安门",tune=False)print("tune=False 合并结果:",jieba.lcut(text))# 结果: ['我', '爱', '北京', '天安', '门'] (可能保持原样,取决于模型初始状态)

七.关键词提取 -jieba.analyse子模块

需要额外import jieba.analyse

1. extract_tags - 基于 TF-IDF 提取关键词

作用:基于统计学中的 TF-IDF 算法,从一段长文本中抽取出最具代表性的核心关键词。

jieba.analyse.extract_tags(sentence,topK=20,withWeight=False,allowPOS=())

参数:

  • 文本 (sentence): 待提取关键词的长文本字符串(str)。
  • 数量 (topK): 提取权重排名前 K 个的关键词。默认为 20(int)。
  • 权重返回 (withWeight): 是否一并返回每个关键词对应的 TF-IDF 权重值。默认为False(bool)。
  • 词性过滤 (allowPOS): 仅包含指定词性的词(如仅提取名词和人名('n', 'nr'))。默认为空元组,即不筛选(tuple)。

返回值:

  • 成功: 默认返回关键词列表(list[str]);如果withWeight=True,则返回包含(关键词, 权重)的元组列表(list[tuple])。

示例:

importjieba.analyse text="人工智能与深度学习在自然语言处理领域取得了巨大的突破"tags=jieba.analyse.extract_tags(text,topK=3,withWeight=True)print(tags)# [('自然语言处理', 1.12...), ('深度学习', 0.89...), ('人工智能', 0.75...)]

八.词性标注 -jieba.posseg子模块

1. posseg.lcut - 词性标注

作用:在对文本进行分词的同时,标注出每一个词语的词性(如n名词、v动词、a形容词等)。

需要额外import jieba.posseg as pseg

pseg.cut(sentence)pseg.lcut(sentence)

参数:

  • 文本 (sentence): 需要标注词性的目标字符串(str)。

返回值:

  • 成功: 返回包含pair(word, flag)对象的生成器或列表。可以通过.word.flag提取。

示例:

importjieba.possegaspseg words=pseg.lcut("我爱北京天安门")forwinwords:print(f"{w.word}:{w.flag}")# 我: r (代词)# 爱: v (动词)# 北京: ns (地名)# 天安门: ns (地名)

九.位置获取方法

1. tokenize - 获取词语位置索引

作用:进行切分,并同时返回词语在原文中的起止位置(索引)。

jieba.tokenize(unicode_sentence,mode="default")

参数:

  • 文本 (unicode_sentence): 需要处理的文本字符串。
  • 模式 (mode): 默认为'default'(精确模式),可设为'search'(搜索引擎模式)(str)。

返回值:

  • 成功: 返回一个生成器,每个元素是一个元组(词语, 起始索引, 结束索引)(Generator)。

示例:

result=jieba.tokenize("自然语言处理")fortkinresult:print(f"词汇:{tk[0]}, 起始:{tk[1]}, 结束:{tk[2]}")# 词汇: 自然语言, 起始: 0, 结束: 4# 词汇: 处理, 起始: 4, 结束: 6

十.结合Jieba的PyTorch Embedding示例重构

使用您提供的《庆余年》文本作为语料库,通过jieba构建真实的词汇表,并利用这些真实数据来演示nn.Embedding的查表过程。

importtorchimporttorch.nnasnnimportjieba# 1.准备原始文本text1="""朝堂是谁的朝堂,天下又是谁的天下——庆帝的文武百官绝不敢轻易忤逆或直谏,\ 夹缝里喘息,贪污,结党,企图吞噬一点点这肮脏血腥的权力,却落得个死无葬身之地,\ 他想起赖明成,陈萍萍,那些一个个被处以极刑的大臣,他与承乾自孩提时代就见识过权力只是一把刀子,\ 一场流血,一个个微不足道的死亡,于是他们恐惧又愤恨,他们开始认为阴谋诡计是一种力量,\ 非要一刀见血,才是一次胜利,嬴的人才配活着,与野兽何异?他们在跟谁争,\ 只有庆帝一个人把握着权柄,把它高高挂起,高于良知,高于品德,高于世间万物,\ 他们竟然在争抢这样一个丑陋又卑鄙,散发着腐烂恶臭的东西。"""text2="""人心?那我亏大了,自抬身价罢了。你觉得他们会感激我,那都是一时的,\ 他们求的是自己想要的东西,我满足了一时片刻,他们就想要有别的东西了,\ 这点儿不长久的人心算什么人心。你看那些古来文人大家,那庄墨韩,人人追捧,\ 高高在上,不容亵渎,一字换一城也毫不夸张,是笔墨纸张值钱,还是他们的名气?\ 就像是最近给你送礼攀关系那些人一样的,他们为的不是一时的东西,我也不能做那一\ 时的玩意儿。”李承泽收回目光,转过身来,他握紧了自己的一双手,直视着谢必安冰冷\ 宛如冬夜般的眼睛,“必安,你得明白,东宫太子有父母,有名头,有朝臣,陛下,\ 拥有这个天下的人和财权,我只有我自己,但是我要让你知道的是,这些他们有的,\ 不见得一直有,我依然有我自己。"""# 2.使用 jieba 构建全局词汇表 (Vocabulary)# 2.1对所有文本进行分词,获取所有的 tokenall_words=jieba.lcut(text1+" "+text2)# 2.2去重并排序(排序非必须,只是为了结果稳定)unique_words=sorted(list(set([wforwinall_wordsifw.strip()])))# 2.3构建 word -> index 的映射字典word2idx={"<PAD>":0}# 郑重声明 0 号索引是 PADfori,wordinenumerate(unique_words):word2idx[word]=i+1vocab_size=len(word2idx)d_model=16# 为了方便展示,我们将向量维度设为16pad_index=0print(f"总词汇量 (Vocab Size):{vocab_size}")# 总词汇量(Vocab Size): 204# 3. 实例化 Embedding 层embed_layer=nn.Embedding(num_embeddings=vocab_size,embedding_dim=d_model,padding_idx=pad_index)# 观察底层核心矩阵 weightprint(embed_layer.weight.shape)# torch.Size([204, 16])(行数对应词汇表大小)# 验证padding_idx:第0行被强行锁定为全0print(embed_layer.weight[0])# tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], grad_fn=<SelectBackward0>)# 4. 构造数据并映射为ID序列(支持动态Batch Size)raw_texts=[text1,text2]# 将待处理文本放入列表中encoded_texts=[]# 映射后ID序列列表max_len=0# 最大句子长度,确定时间步长度用# 4.1将文本分词、映射为ID序列,并动态记录最大长度fortextinraw_texts:# 转换为ID序列(过滤掉不在词典中的词,增加鲁棒性)encoded_sequence=[word2idx[word]forwordinjieba.lcut(text)ifwordinword2idx]encoded_texts.append(encoded_sequence)# 确认并更新 max_leniflen(encoded_sequence)>max_len:max_len=len(encoded_sequence)# 4.2依据max_len对所有序列进行Padding填充padded_sequences=[]forseqinencoded_texts:# 用PAD(0)补齐至最大长度padded_seq=seq+[pad_index]*(max_len-len(seq))padded_sequences.append(padded_seq)# 4.3 组装成Batch输入张量(必须是torch.long类型)input_indices=torch.tensor(padded_sequences,dtype=torch.long)# 输入张量(Batch, Seq_Len)映射关系print(input_indices)# tensor([[119, 116, ...(省略中间) , 0, 0],[ 42, 203, ...(省略中间) , 156, 4]])print(input_indices.shape)# torch.Size([2, 202])# 5. 前向传播:执行查表操作embedded_features=embed_layer(input_indices)# Embedding处理后的输出print(embedded_features.shape)# torch.Size([2, 202, 16])

需要注意的是,在实际构建Encoder时,Embedding 层既可以写在 Encoder 的结构中,也可以单独写。如果将Embedding层写在Encoder结构中,代码会整洁,所有与模型相关的部分都在同一个类中,便于维护,但这个操作相当于将整个Transformer结构的输入数据由(batch_size, seq_len, input_dimensions)结构修改为了(batch_size, seq_len)结构、从而会影响掩码的结构、影响掩码函数、这个Embedding层无法与Decoder或其他算法共用、甚至可能导致你的Encoder结构无法用于时间序列任务;如果我们将Embedding层写在Encoder结构之外,灵活性更高,可以在多个模型中共享同一个 Embedding 层,也可以对Embedding后的结果进行更加顺畅的独立处理,但缺点是就需要额外的代码来管理Embedding层的初始化和传递。在实际进行编程时,Embedding结构究竟写在Encoder内还是外,与你的数据和实现的架构有很大的关系,你需要根据具体情况进行具体的分析。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/30 1:17:15

四级备考资料书|四级考试备考资料|四级英语备考资料

四级备考资料书|四级考试备考资料|四级英语备考资料资料全科都有四级英语备考资料 PDFhttps://tool.nineya.com/s/1jpf2t49o 【英语真题】1. "Reference" most probably means&#xff08; &#xff09; A. 参考&#xff0c;参考书 B. 考试 C. 练习 D. 答案 答案&…

作者头像 李华
网站建设 2026/6/30 1:16:57

自动定期备份服务器数据

项目要求&#xff1a;1、每天00点整在Web服务器上按日期打包备份系统配置文件、网站程序目录及访问日志文件2、通过rsync命令推送到备份服务器上保存3、备份服务器定时清除旧记录4、搭建邮件告警平台备份要求&#xff1a;1、所有服务器的备份目录必须都为/backup。2、要备份的系…

作者头像 李华
网站建设 2026/6/30 1:16:27

半导体测试设备 + 探针卡|纯技术管理线完整晋升阶梯(全程带团队,不走纯专家通道,直达 CTO)

赛道范围&#xff1a;ATE 测试整机、探针台、MEMS / 垂直 / 射频探针卡、先进封装 HBM/Chiplet 测试耗材、探针微加工、测试软硬件一体化研发&#xff1b;纯技术管理线核心特征&#xff1a;每一级都带固定团队、管人、管项目预算、对产品量产交付负责&#xff0c;不靠个人单项技…

作者头像 李华
网站建设 2026/6/30 1:15:07

TSB42xx芯片解析:IEEE 1394总线与DTCP内容保护的硬件实现

1. 项目概述&#xff1a;当高速总线遇上内容保护在二十年前&#xff0c;如果你是一名负责设计高端数字录像机&#xff08;DVR&#xff09;、数字机顶盒或专业视频编辑设备的硬件工程师&#xff0c;那么“IEEE 1394”这个名词对你来说&#xff0c;绝对是绕不开的核心技术。它不仅…

作者头像 李华
网站建设 2026/6/30 1:12:54

3分钟快速上手:让你的网易云音乐变得更强大

3分钟快速上手&#xff1a;让你的网易云音乐变得更强大 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer BetterNCM Installer II 是一款专门为网易云音乐PC客户端设计的插件管理器&…

作者头像 李华