Python-基于词典-中文分词算法

article/2025/9/22 23:00:39

文章目录

  • 三种分词算法比较
  • 逆向最大匹配
    • 从后往前扫描
    • 词典匹配
  • 概率分词
    • 原理
      • DAG
      • 计算大概率路径
    • 封装
  • 图论知识补充
    • 图的表示方法
    • 概率图模型
    • 贝叶斯网络

三种分词算法比较

dt = {'空调': 1, '调和': 1, '和风': 1, '风扇': 1,'空': 1, '调': 1, '和': 2, '风': 1, '扇': 1}  # 词典
max_len = max(len(w) for w in dt)  # 词最大长度,默认等于词典最长词
total = sum(dt.values())  # 总频数
sentence = '空调和风扇'
length = len(sentence)def maximum_matching(sentence):"""正向最大匹配"""head = 0while head < length:tail = min(head + max_len, length)for middle in range(tail, head + 1, -1):word = sentence[head: middle]if word in dt:head = middlebreakelse:word = sentence[head]head += 1yield worddef reverse_maximum_matching(sentence):"""逆向最大匹配"""words = []tail = lengthwhile tail > 0:head = min(tail - max_len, 0)for middle in range(head, tail - 1):word = sentence[middle: tail]if word in dt:tail = middlebreakelse:tail -= 1word = sentence[tail]words.append(word)  # 比words.insert(0, word)快6%return words[::-1]def probability(sentence):"""贝叶斯网络"""# get DAGDAG = dict()for head in range(length):DAG.update({head: [head]})tail = min(head + max_len, length)for middle in range(head + 2, tail + 1):word = sentence[head: middle]if word in dt:DAG[head].append(middle - 1)# calculate routeroute = {}route[length] = (1, 1)for idx in range(length - 1, -1, -1):route[idx] = max((dt.get(sentence[idx:x + 1], 0) / total * route[x + 1][0], x)for x in DAG[idx])# yieldx = 0while x < length:y = route[x][1] + 1l_word = sentence[x:y]yield l_wordx = yprint(list(maximum_matching(sentence)))
print(reverse_maximum_matching(sentence))
print(list(probability(sentence)))
空调和风扇分词结果
[‘空调’, ‘和风’, ‘扇’]
[‘空’, ‘调和’, ‘风扇’]
[‘空调’, ‘和’, ‘风扇’]

逆向最大匹配

从后往前扫描

sentence = '西樵山'
# 初始化扫描位置,从句尾开始
tail = len(sentence)
# 词最大长度
max_len = 3
# 逆向扫描
while tail > 0:head = tail - max_lenif head < 0:head = 0for middle in range(head, tail):word = sentence[middle: tail]print(head, middle, tail, word)tail -= 1

0 0 3 西樵山
0 1 3 樵山
0 2 3 山
0 0 2 西樵
0 1 2 樵
0 0 1 西

词典匹配

dt = {'桂江二中', '毕业', '二中'}  # 词典
sentence = '桂江二中毕业'tail = len(sentence)
max_len = 4
words = []
while tail > 0:head = max(tail - max_len, 0)for middle in range(head, tail - 1):  # 忽略长度为1的词word = sentence[middle: tail]if word in dt:print(middle, tail - 1, word)words.append(word)tail = middlebreakelse:tail -= 1print(tail, tail, sentence[tail])words.append(sentence[tail])
print(words[::-1])

4 5 毕业
0 3 桂江二中
[‘桂江二中’, ‘毕业’]

概率分词

原理

  1. 基于词典,对句子进行词图扫描,生成所有成词情况所构成的有向无环图Directed Acyclic Graph
  2. 根据DAG,反向计算最大概率路径(使用动态规划算法)
  3. 根据路径获取最大概率的分词序列
dt = {'空调': 1, '调和': 1, '和风': 1, '风扇': 1,'空': 1, '调': 1, '和': 2, '风': 1, '扇': 1}  # 词典
max_len = max(len(w) for w in dt)  # 词最大长度,默认等于词典最长词
total = sum(dt.values())  # 总频数
sentence = '空调和风扇'
length = len(sentence)

t o t a l = 1 + 1 + 1 + 1 + 1 + 1 + 2 + 1 + 1 = 10 total=1+1+1+1+1+1+2+1+1=10 total=1+1+1+1+1+1+2+1+1=10
P ( 空 调 , 和 风 , 扇 ) = 1 10 ∗ 1 10 ∗ 1 10 = 1 1000 P(空调,和风,扇)=\frac {1} {10} * \frac {1} {10} * \frac {1} {10} = \frac {1} {1000} P()=101101101=10001
P ( 空 , 调 和 , 风 扇 ) = 1 10 ∗ 1 10 ∗ 1 10 = 1 1000 P(空,调和,风扇)=\frac {1} {10} * \frac {1} {10} * \frac {1} {10} = \frac {1} {1000} P()=101101101=10001
P ( 空 调 , 和 , 风 扇 ) = 1 10 ∗ 2 10 ∗ 1 10 = 2 1000 P(空调,和,风扇)=\frac {1} {10} * \frac {2} {10} * \frac {1} {10} = \frac {2} {1000} P()=101102101=10002
P ( 空 调 , 和 , 风 扇 ) 最 大 P(空调,和,风扇)最大 P()

DAG

DAG = dict()
for head in range(length):DAG.update({head: [head]})tail = min(head + max_len, length)for middle in range(head + 2, tail + 1):word = sentence[head: middle]if word in dt:DAG[head].append(middle - 1)
print(DAG)

{0: [0, 1], 1: [1, 2], 2: [2, 3], 3: [3, 4], 4: [4]}

计算大概率路径

route = {}
route[length] = (1, 1)
for idx in range(length - 1, -1, -1):route[idx] = max((dt.get(sentence[idx:x + 1], 0) / total * route[x + 1][0], x)for x in DAG[idx])
print(route)

{5: (1, 1), 4: (0.1, 4), 3: (0.1, 4), 2: (0.02, 2), 1: (0.01, 2), 0: (0.002, 1)}

封装

from os import path
import re
import jieba
from math import log
fname = path.join(path.dirname(jieba.__file__), 'dict.txt')
NA = 'NA'class Tokenizer:re_eng = re.compile('[a-zA-Z]+')re_m = re.compile('[0-9]+')  # jieba数词标注为mdef __init__(self, word2freq, total, word2flag, max_len):self.word2freq = word2freqself.total = totalself.word2flag = word2flagself.max_len = max_len@classmethoddef initialization(cls):word2freq, total, word2flag = dict(), 0, dict()with open(fname, encoding='utf-8') as f:for line in f.read().strip().split('\n'):word, freq, flag = line.split()freq = int(freq)word2freq[word] = freqtotal += freqword2flag[word] = flag# 词最大长度,默认等于词典最长词(超长英文符会识别不出来)max_len = max(len(i) for i in word2freq.keys())return cls(word2freq, total, word2flag, max_len)def _get_DAG(self, sentence):length = len(sentence)DAG = dict()for head in range(length):DAG.update({head: [head]})tail = min(head + self.max_len, length)for middle in range(head + 2, tail + 1):word = sentence[head: middle]# ------------- 词典 + 正则 ------------- #if word in self.word2freq:DAG[head].append(middle - 1)elif self.re_eng.fullmatch(word):DAG[head].append(middle - 1)elif self.re_m.fullmatch(word):DAG[head].append(middle - 1)return DAGdef _calculate(self, sentence):DAG = self._get_DAG(sentence)length = len(sentence)route = dict()route[length] = (0, 0)logtotal = log(self.total)for idx in range(length - 1, -1, -1):route[idx] = max((log(self.word2freq.get(sentence[idx:x + 1], 1)) - logtotal + route[x + 1][0], x)for x in DAG[idx])return routedef cut(self, sentence):route = self._calculate(sentence)length = len(sentence)x = 0while x < length:y = route[x][1] + 1l_word = sentence[x:y]yield l_wordx = ydef lcut(self, sentence):return list(self.cut(sentence))def add_word(self, word, freq=-1, flag=NA):if freq >= 0:self.del_word(word)else:freq = 1original_freq = self.word2freq.get(word, 0)self.word2freq[word] = original_freq + freqself.total = self.total - original_freq + self.word2freq[word]self.word2flag[word] = flagdef del_word(self, word):original_freq = self.word2freq.get(word)if original_freq is not None:del self.word2freq[word]self.total -= original_freqdel self.word2flag[word]def cut2position(self, sentence):route = self._calculate(sentence)x = 0length = len(sentence)while x < length:y = route[x][1] + 1l_word = sentence[x:y]yield l_word, x, yx = ydef get_flag(self, word):return self.word2flag.get(word, NA)def get_flags(self, words):if isinstance(words, str):words = self.cut(words)return [self.get_flag(word) for word in words]# 实例化
tokenizer = Tokenizer.initialization()
cut = tokenizer.cut
lcut = tokenizer.lcut
add_word = tokenizer.add_word
del_word = tokenizer.del_word
cut2position = tokenizer.cut2position
get_flag = tokenizer.get_flag
get_flags = tokenizer.get_flagsif __name__ == '__main__':text = '幻刺斩杀大法师'print(lcut(text))add_word('幻刺', 2, 'N')print(list(cut2position(text)))del_word('大法师')print(lcut(text))print(get_flags(text))

图论知识补充

图的表示方法

  • networkx
%matplotlib inline
import networkx as nx
# 创建图
G = nx.DiGraph()
# 添加边
G.add_edges_from([(0, 1), (0, 2), (1, 2), (2, 3)])
# 绘图
nx.draw(G, with_labels=True, font_size=36, node_size=1500, width=4, node_color='lightgreen')
  • 矩阵
class G:def __init__(self, nodes):self.matrix = [[0] * nodes for _ in range(nodes)]def add_edge(self, start, end, value=1):self.matrix[start][end] = valueg = G(4)
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 3)
print(g.matrix)
  • 字典
class G:def __init__(self):self.dt = dict()def add_edge(self, start, end, value=1):self.dt[start] = self.dt.get(start, dict())self.dt[start][end] = valueg = G()
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 3)
print(g.dt)

概率图模型

  • 概率图模型:利用图来表示与模型有关的变量的联合概率分布
  • 贝叶斯网络模型:由有向无环图和条件概率表(Conditional Probability Table,CPT)组成

贝叶斯网络


http://chatgpt.dhexx.cn/article/kCDi7xn8.shtml

相关文章

分词算法介绍

如有需要可以转载&#xff0c;但转载请注明出处&#xff0c;并保留这一块信息&#xff0c;谢谢合作&#xff01; 部分内容参考互联网,如有异议,请跟我联系! 作者:刀剑笑(Blog:http://blog.csdn.net/jyz3051) Email:jyz3051 at yahoo dot com dot cn(at请替换成&#xff…

为什么中文分词比英文分词更难?有哪些常用算法?(附代码)

导读&#xff1a;人类文明的重要标志之一是语言文字的诞生。数千年来&#xff0c;几乎人类所有知识的传播都是以语言和文字作为媒介。 自然语言处理是使用计算机科学与人工智能技术分析和理解人类语言的一门学科。在人工智能的诸多范畴中&#xff0c;自然语言的理解以其复杂性、…

中文分词工具讨论

中文分词工具讨论 1 中文分词原理介绍 1.1 中文分词概述 中文分词(Chinese Word Segmentation) 指的是将一个汉字序列切分成一个一个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。 1.2 中文分词方法介绍 现有的分词方法可分为三大类&#xff1…

几种中文分词工具

word分词 word分词是一个Java实现的分布式的中文分词组件&#xff0c;提供了多种基于词典的分词算法&#xff0c;并利用ngram模型来消除歧义。能准确识别英文、数字&#xff0c;以及日期、时间等数量词&#xff0c;能识别人名、地名、组织机构名等未登录词。能通过自定义配置文…

NLP词法分析(一):中文分词技术

文分词介绍 中文分词相较于英文分词要难许多&#xff0c;因为英文本身就是由单词与空格组成的&#xff0c;而中文则是由独立的字组成的&#xff0c;但同时语义却是有词来表达的。因此对于中文的分析与研究&#xff0c;首先应寻找合适的方法进行分词。现有的中文分词技术主要分…

双向最大匹配算法——基于词典规则的中文分词(Java实现)

目录 前言 一、中文分词理论描述 二、算法描述 1、正向最大匹配算法 2、反向最大匹配算法 3、双剑合璧 三、案例描述 四、JAVA实现完整代码 五、组装UI 六、总结 前言 中文分词所需要的词典放在公众号&#xff0c;关注文章末尾的公众号&#xff0c;回复“字典”获取…

中文分词技术及应用

中文分词技术及应用中文分词算法有5大类&#xff1a; 1、 基于词典的方法 2、基于统计的方法 3、基于规则的方法 4、基于字标注的方法 5、基于人工智能的技术&#xff08;基于理解&#xff09;的方法 中文分词目前有4个瓶颈&#xff1a; 1、分词歧义 2、未登陆词识别 3、分词粒…

【NLP】为什么中文分词比英文分词更难?有哪些常用算法?(附代码)

导读&#xff1a;人类文明的重要标志之一是语言文字的诞生。数千年来&#xff0c;几乎人类所有知识的传播都是以语言和文字作为媒介。 自然语言处理是使用计算机科学与人工智能技术分析和理解人类语言的一门学科。在人工智能的诸多范畴中&#xff0c;自然语言的理解以其复杂性、…

正向最大匹配中文分词算法

中文分词一直都是中文自然语言处理领域的基础研究。目前&#xff0c;网络上流行的很多中文分词软件都可以在付出较少的代价的同时&#xff0c;具备较高的正确率。而且不少中文分词软件支持Lucene扩展。但不管实现如何&#xff0c;目前而言的分词系统绝大多数都是基于中文词典的…

NLP|中文分词技术及应用

摘要:中文分词是中文信息处理的重要基础,本文详细阐述了目前主要的几种中文分词算法的技术原理 、中文分词目前的瓶颈和评价准则,以及中文分词的具体应用。 中文分词指将一个汉字序列切分成一个个单独的词。现有的中文分词算法有五大类:基于词典的方法,基于统计的方法,基…

入门科普:一文看懂NLP和中文分词算法(附代码举例)

导读&#xff1a;在人类社会中&#xff0c;语言扮演着重要的角色&#xff0c;语言是人类区别于其他动物的根本标志&#xff0c;没有语言&#xff0c;人类的思维无从谈起&#xff0c;沟通交流更是无源之水。 所谓“自然”乃是寓意自然进化形成&#xff0c;是为了区分一些人造语言…

中文分词算法—— 基于词典的方法

1、基于词典的方法&#xff08;字符串匹配&#xff0c;机械分词方法&#xff09; 定义:按照一定策略将待分析的汉字串与一个“大机器词典”中的词条进行匹配&#xff0c;若在词典中找到某个字符串&#xff0c;则匹配成功。 按照扫描方向的不同&#xff1a;正向匹配和逆向匹配…

【NLP】中文分词:原理及分词算法

一、中文分词 词是最小的能够独立活动的有意义的语言成分&#xff0c;英文单词之间是以空格作为自然分界符的&#xff0c;而汉语是以字为基本的书写单位&#xff0c;词语之间没有明显的区分标记&#xff0c;因此&#xff0c;中文词语分析是中文信息处理的基础与关键。 Lucene中…

常见分词算法综述

常见分词算法综述 文章目录 常见分词算法综述一、基于词典的分词1. 最大匹配分词算法2. 最短路径分词算法&#xff1a;2.1基于dijkstra算法求最短路径&#xff1a;2.2N-dijkstra算法求最短路径&#xff1a;2.3. 基于n-gram model的分词算法&#xff1a; 二、基于字的分词算法生…

中文分词原理及分词工具介绍

转自&#xff1a;https://blog.csdn.net/flysky1991/article/details/73948971 本文首先介绍下中文分词的基本原理&#xff0c;然后介绍下国内比较流行的中文分词工具&#xff0c;如jieba、SnowNLP、THULAC、NLPIR&#xff0c;上述分词工具都已经在github上开源&#xff0c;后…

中文分词常见方法

中文分词是中文文本处理的一个基础步骤&#xff0c;也是中文人机自然语言交互的基础模块。不同于英文的是&#xff0c;中文句子中没有词的界限&#xff0c;因此在进行中文自然语言处理时&#xff0c;通常需要先进行分词&#xff0c;分词效果将直接影响词性、句法树等模块的效果…

自然语言处理之中文分词技术与算法

1 正向最大匹配法 1.1 正向最大匹配&#xff08;Maximum Match Method, MM法&#xff09;的基本思想&#xff1a; 假定分词词典中的最长词有i个汉字字符&#xff0c;则用被处理文档的当前字串中的前i个字作为匹配字段&#xff0c;查找字典。若字典中存在这样的一个i字词&#…

列举:中文分词算法你知道几种?

列举&#xff1a;中文分词算法你知道几种&#xff1f; 摘要&#xff1a;看似普通的一句话&#xff0c;甚至几个词&#xff0c;在机器眼里都要经过好几道“程序”。这个过程主要靠中文分词算法&#xff0c;这个算法分为三大类&#xff1a;机械分词算法、基于n元语法的分词算法、…

(转)Linux下管道的原理

7.1.1 Linux管道的实现机制 在Linux中&#xff0c;管道是一种使用非常频繁的通信机制。从本质上说&#xff0c;管道也是一种文件&#xff0c;但它又和一般的文件有所不同&#xff0c;管道可以克服使用文件进行通信的两个问题&#xff0c;具体表现为&#xff1a; 限制管…

Linux之进程间通信——管道

文章目录 前言一、进程间通信1.概念2.目的3.进程间通信分类 二、管道1.管道介绍2.管道分类1.匿名管道pipi创建管道文件&#xff0c;打开读写端fork子进程关闭父进程的写入端&#xff0c;关闭子进程的读取端读写特征管道特征 2.命名管道mkfifo创建管道文件删除管道文件通信 三、…