中文分词算法-----1、介绍--机械分词--机械分词代码实现

1、中文分词算法介绍

        中文分词算法是指将一个汉字序列切分成一个一个单独的词,与英文以空格作为天然的分隔符不同,中文字符在语义识别时,需要把数个字符组合成词,才能表达出真正的含义。分词算法是文本挖掘的基础,通常应用于自然语言处理、搜索引擎、智能推荐等领域。

        分类:

  • 第一类是基于字符串匹配,即扫描字符串,如果发现字符串的子串和词典中的词相同,就算匹配,比如机械分词方法。这类分词通常会加入一些启发式规则,比如“正向/反向最大匹配”,“长词优先”等
  • 第二类是基于统计以及机器学习的分词方法,它们基于人工标注的词性和统计特征,对中文进行建模,即根据观测到的数据(标注好的语料)对模型参数进行训练,在分词阶段再通过模型计算各种分词出现的概率,将概率最大的分词结果作为最终结果。常见的序列标注模型有HMM和CRF。这类分词算法能很好处理歧义和未登录词问题,效果比前一类效果好,但是需要大量的人工标注数据,以及较慢的分词速度。
  • 第三类是通过让计算机模拟人对句子的理解,达到识别词的效果,由于汉语语义的复杂性,难以将各种语言信息组织成机器能够识别的形式,目前这种分词系统还处于试验阶段,这里不讲解和实现

2、机械分词

         机械分词又称基于字符串匹配的分词方法、按照一定的策略将待分析的字符串与一个“充分大的”机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。这是最简单的分词方法,但非常高效和常见。

        1、最大匹配方法----分为正向匹配和逆向匹配

        正向匹配算法:

                待分词文本: text = '计算机语言学课程有意思'

                词表: dict[]={"计算", "计算语言学", "课程", "有", "意思"} 

  •        从ste[0:***]开始,当扫描到ste[0:2]的时候,发现"计算"已经在词表dict[]中了。但还不能切分出来,因为我们不知道后面的词语能不能组成更长的词(最大匹配)。
  •     继续扫描ste[0:3],发现"计算语"并不是dict[]中的词。但是我们还不能确定是否前面找到的"计算语"已经是最大的词了。因为"计算语"是dict[2]的前缀。
  •     扫描ste[0:4],发现"计算语言"并不是dict[]中的词。但是是dict[2]的前缀。继续扫描:
  •     扫描ste[0:5],发现"计算语言学"是dict[]中的词。继续扫描下去:
  •     当扫描ste[0:6]的时候,发现"计算语言学课"并不是词表中的词,也不是词的前缀。则切分出"计算语言学"为最大词汇

# 文本
text = '我们的计算语言学课程有意思'
textlen = len([i for i in text])
print([i for i in text], '\n', len([i for i in text]), '\n'*2)
""" """
# sentence=["计", "算", "语", "言", "学", "课", "程", "有", "意", "思"]
# 词库
dict_1 = ["计算", "计算语言学", "课程", "有", "意思", "我们", "的", "我们的"]
len_dict = [len(i) for i in dict_1]
print(len_dict, '\n', max(len_dict), '\n'*2)

# 当前匹配起始位置 和 结束位置
start_loc = 0
end_loc = 0

# 匹配结果存储
word_split = []
i = 0
for _ in range(textlen):
	if i < textlen:
		# 每一次匹配结果存储
		word = []
		for j in range(max(len_dict)+1):
			word_try = text[i:(i+j)]
			print(text[i:(i+j)])
			if word_try in dict_1:
				word.append(word_try)

		# 取出最大匹配结果
		word_split.append(word[-1:])
		print(len(word))
		print(len(word[len(word)-1]), word, '\n')
		i = i + len(word[len(word)-1])
	else:
		break

print(word_split)

"""
[['我们的'], ['计算语言学'], ['课程'], ['有'], ['意思']]
"""

         负向匹配算法:

        首先我们定义一个最大分割长度5,从右往左开始分割:

  •   (1) 首先取出来的候选词W是 “课程有意思”。
  •   (2) 查词表,W不在词表中,将W最左边的第一个字去掉,得到W“程有意思”;
  •   (3) 查词表,W也不在词表中,将W最左边的第一个字去掉,得到W“有意思”;
  •   (4) 查词表,W也不在词表中,将W最左边的第一个字再去掉,得到W“意思”;
  •   (5) 查词表,W在词表中,就将W从整个句子中拆分出来,此时原句子为“计算语言学课程有”
  •   (6) 根据分割长度5,截取句子内容,得到候选句W是“言学课程有”;
  •   (7) 查词表,W不在词表中,将W最左边的第一个字去掉,得到W“学课程有”;
  •   (8) 查词表,W也不在词表中,将W最左边的第一个字去掉,得到W“课程有”;
  •   (9) 依次类推,直到W为“有”一个词的时候,这时候将W从整个句子中拆分出来,此时句子为“计算语言学课程”
  •   (10) 根据分割长度5,截取句子内容,得到候选句W是“算语言学课程”;
  •   (11) 查词表,W不在词表中,将W最左边的第一个字去掉,得到W“语言学课程”;
  •   (12) 依次类推,直到W为“课程”的时候,这时候将W从整个句子中拆分出来,此时句子为“计算语言学”
  •   (13) 根据分割长度5,截取句子内容,得到候选句W是“计算语言学”;
  •   (14)  查词表,W在词表,分割结束。

 

""" 2、负向匹配
# 文本
text = '我们的计算语言学课程有意思'
textlen = len([i for i in text])
print([i for i in text], '\n', len([i for i in text]), '\n'*2)

# sentence=["计", "算", "语", "言", "学", "课", "程", "有", "意", "思"]
# 词库
dict_1 = ["计算", "计算语言学", "课程", "有", "意思", "我们", "的", "我们的"]
len_dict = [len(i) for i in dict_1]
print(len_dict, '\n', max(len_dict), '\n'*2)

# 匹配结果存储
word_split = []

# 定义负向匹配最大长度,一般为词库中最大长度的词的长度
nega_len = max(len_dict)
i = 0

for _ in range(textlen):
	for j in range(nega_len):
		# print(text[(textlen-i-nega_len+j):(textlen-i)])
		if text[(textlen-i-nega_len+j):(textlen-i)] in dict_1:
			word_split.append(text[(textlen-i-nega_len+j):(textlen-i)])
			i = i + len([ia for ia in text[(textlen-i-nega_len+j):(textlen-i)] ])

print(word_split)
"""

"""
['我', '们', '的', '计', '算', '语', '言', '学', '课', '程', '有', '意', '思'] 
 13 


[2, 5, 2, 1, 2, 2, 1, 3] 
 5 


['意思', '有', '课程', '计算语言学', '我们的']

"""

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值