当无数个自己离去,我便日益坦然
—— 25.2.9
一、jieba分词器
Jieba 是一款优秀的 Python 中文分词库,它支持多种分词模式,其中全切分方式会将句子中所有可能的词语都扫描出来。
1.原理
全切分方式会找出句子中所有可能的词语组合。对于一个输入的句子,它会尝试将句子按照不同的方式进行切分,只要在词典中存在对应的词语,就会将其作为一个分词结果输出。这种方式会输出所有可能的分词组合,因此可能会产生较多的分词结果。
2.使用方法
在 Jieba 中,导入jieba分词库,使用 jieba.cut
函数并将 cut_all
参数设置为 True
即可实现全切分。
jieba.cut():是 Python 中文分词库 jieba 的核心函数,用于将中文文本切分成独立的词语。
参数名 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
sentence | str | 无 | 是 | 需要分词的中文字符串。 |
cut_all | bool | False | 否 | 控制分词模式: - False :精确模式(默认),返回最合理的分词结果。- True :全模式,输出所有可能的词语组合。 |
HMM | bool | True | 否 | 是否使用隐马尔可夫模型(HMM)识别未登录词(新词)。 - True :启用新词发现(推荐)。- False :关闭新词发现。 |
use_paddle | bool | False | 否 | 是否使用 PaddlePaddle 深度学习框架加速分词。 - 需先安装 PaddlePaddle 库( pip install paddlepaddle )。 |
join():join()
是 Python 字符串的内置方法,用于将一个可迭代对象(如列表、元组、生成器等)中的元素用指定的字符串连接成一个新字符串。在处理中文分词结果时,常用它来将分词后的词语列表转换为特定格式的字符串(例如用斜杠分隔)。
-
参数:
-
可迭代对象
: 包含多个元素(必须为字符串类型)的列表、元组、生成器等。 -
分隔符
: 用于连接元素的字符串(可以是空字符串""
)。
-
-
返回值: 返回一个由分隔符连接元素后的新字符串。
与其他方法的对比
方法 | 特点 | 示例 |
---|---|---|
str.join() | 高效连接字符串,支持任意可迭代对象。 | "/".join(["A", "B", "C"]) |
+ 运算符拼接 | 每次拼接生成新字符串,效率低(不推荐循环中使用)。 | "A" + "/" + "B" + "/" + "C" |
f-string 格式化 | 适合少量固定元素的拼接,可读性强但灵活性差。 | f"{a}/{b}/{c}" |
import jieba
# 待分词的句子
sentence = "我爱自然语言处理"
# 使用全切分方式进行分词
words = jieba.cut(sentence, cut_all=True)
# 输出分词结果
print("全切分结果:", "/ ".join(words))
3.Jieba内部分词实现细节
len():返回对象的长度或元素个数,适用于字符串、列表、元组、字典、集合等可迭代对象。
range():生成一个不可变的整数序列,常用于循环遍历。
append():向列表末尾添加一个元素(直接修改原列表)。
def calc_dag(sentence):
DAG = {} #DAG空字典,用来存储DAG有向无环图
N = len(sentence)
for k in range(N):
tmplist = []
i = k
frag = sentence[k]
while i < N:
if frag in Dict:
tmplist.append(i)
i += 1
frag = sentence[k:i + 1]
if not tmplist:
tmplist.append(k)
DAG[k] = tmplist
return DAG
4.对Jieba分词结果序列进行解码
pop():移除列表中指定位置的元素并返回该元素的值。若不指定位置,默认移除并返回列表的最后一个元素。
参数名 | 类型 | 默认值 | 是否必填 | 说明 |
---|---|---|---|---|
index | int | -1 | 否 | 要移除元素的索引(支持负数索引)。 |
pop()
和 append()
可共同实现**栈(LIFO)**结构
#将DAG中的信息解码(还原)出来,用文本展示出所有切分方式
class DAGDecode:
#通过两个队列来实现
def __init__(self, sentence):
self.sentence = sentence
self.DAG = calc_dag(sentence) #使用了上方的函数
self.length = len(sentence)
self.unfinish_path = [[]] #保存待解码序列的队列
self.finish_path = [] #保存解码完成的序列的队列
#对于每一个序列,检查是否需要继续解码
#不需要继续解码的,放入解码完成队列
#需要继续解码的,将生成的新队列,放入待解码队列
#path形如:["经常", "有", "意见"]
def decode_next(self, path):
path_length = len("".join(path))
if path_length == self.length: #已完成解码
self.finish_path.append(path)
return
candidates = self.DAG[path_length]
new_paths = []
for candidate in candidates:
new_paths.append(path + [self.sentence[path_length:candidate+1]])
self.unfinish_path += new_paths #放入待解码对列
return
#递归调用序列解码过程
def decode(self):
while self.unfinish_path != []:
path = self.unfinish_path.pop() #从待解码队列中取出一个序列
self.decode_next(path) #使用该序列进行解码
二、模仿jieba分词器对输入的句子进行全切分
递归迭代进行分词
def segmentation(sentence, word_dict):
result = []
if sentence == "":
return [[]]
for end in range(1, len(sentence) + 1):
word = sentence[:end]
if word in word_dict:
# 递归获取剩余字符串的切分结果
sub_results = segmentation(sentence[end:], word_dict)
for sub_result in sub_results:
result.append([word] + sub_result)
return result