NLP之中文分词

中文分词主要分为规则分词、统计分词、混合分词

规则分词

主要是通过人工设立词库,按照一定方式进行匹配切分,其实现简单高效,但对新词很难进行处理

基于规则的分词是一种机械分词方法,主要是通过维护词典,在切分语句时,将语句的每个字符串与词表中的词进行逐一匹配,找到则切分,否则不予切分。按照匹配切分的方式,主要有正向最大匹配法、逆向最大匹配法以及双向最大匹配法三种方法。

正向最大匹配法

假定分词词典中的最长词有i个汉字字符,则用被处理文档的当前字串中的前i个字作为匹配字段,查找字典。若字典中存在这样的一个i字词,则匹配成功,匹配字段被作为一一个词切分出来。如果词典中找不到这样的一个i字词,则匹配失败,将匹配字段中的最后一个字去掉,对剩下的字串重新进行匹配处理。如此进行下去,直到匹配成功,即切分出一个词或剩余字串的长度为零为止。这样就完成了一轮匹配,然后取下一个i字字串进行匹配处理。直到文档被扫描完为止。

def getWordDic():
    """
    读取词典文件
    载入词典
    :return:
    """
    words_dic = []
    with open("dic.txt","r", encoding="utf8") as dic_input:
        for word in dic_input:
            words_dic.append(word.strip())
    return words_dic
#实现正向匹配算法中的切词方法
def cut_words(raw_sentence,words_dic):
    #统计词典中最长的词
    max_length = max(len(word) for word in words_dic)
    sentence = raw_sentence.strip()
    #统计序列长度
    words_length = len(sentence)
    #存储切分好的词语
    cut_word_list = []
    while words_length > 0:
        max_cut_length = min(max_length, words_length)
        subSentence = sentence[0 : max_cut_length]
        while max_cut_length > 0:
            if subSentence in words_dic:
                cut_word_list.append(subSentence)
                break
            elif max_cut_length == 1:
                cut_word_list.append(subSentence)
                break
            else:
                max_cut_length = max_cut_length -1
                subSentence = subSentence[0:max_cut_length]
        sentence = sentence[max_cut_length:]
        words_length = words_length - max_cut_length
    #words = "/".join(cut_word_list)
    return cut_word_list
cut_words('很高兴分享关于NLP的技术',getWordDic())
['很', '高兴', '分享', '关于', 'NLP', '的', '技术']
逆向最大匹配算法

逆向最大匹配法从被处理文档的末端开始匹配扫描,每次取最末端的i个字符(i为词典中最长词数)作为匹配字段,若匹配失败,则去掉匹配字段最前面的一个字,继续匹配。

def getWordDic():
    """
    读取词典文件
    载入词典
    :return:
    """
    words_dic = []
    with open("dic.txt","r", encoding="utf8") as dic_input:
        for word in dic_input:
            words_dic.append(word.strip())
    return words_dic
#实现逆向最大匹配算法中的切词方法
def cut_words(raw_sentence,words_dic):
    #统计词典中词的最长长度
    max_length = max(len(word) for word in words_dic)
    sentence = raw_sentence.strip()
    #统计序列长度
    words_length = len(sentence)
    #存储切分出来的词语
    cut_word_list = []
    #判断是否需要继续切词
    while words_length > 0:
        max_cut_length = min(max_length, words_length)
        subSentence = sentence[-max_cut_length:]
        while max_cut_length > 0:
            if subSentence in words_dic:
                cut_word_list.append(subSentence)
                break
            elif max_cut_length == 1:
                cut_word_list.append(subSentence)
                break
            else:
                max_cut_length = max_cut_length -1
                subSentence = subSentence[-max_cut_length:]
        sentence = sentence[0:-max_cut_length]
        words_length = words_length -max_cut_length
    cut_word_list.reverse()
    #words = "/".join(cut_word_list)
    return  cut_word_list
cut_words('很高兴分享关于NLP的技术',getWordDic())
['很', '高兴', '分享', '关于', 'NLP', '的', '技术']
双向最大匹配法

双向最大匹配法( Bi-directction Matching method)是将正向最大匹配法得到的分词结果和逆向最大匹配法得到的结果进行比较,然后按照最大匹配原则,选取词数切分最少的作为结果。这正是双向最大匹配法在实用中文信息处理系统中得以广泛使用的原因。

def getWordDic():
    """
    读取词典文件
    载入词典
    :return:
    """
    words_dic = []
    with open("dic.txt","r", encoding="utf8") as dic_input:
        for word in dic_input:
            words_dic.append(word.strip())
    return words_dic
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#Author bruce
import FMM
import BMM
#实现双向匹配算法中的切词方法
def cut_words(raw_sentence,words_dic):
    bmm_word_list = BMM.cut_words(raw_sentence,words_dic)
    fmm_word_list = FMM.cut_words(raw_sentence,words_dic)
    bmm_word_list_size = len(bmm_word_list)
    fmm_word_list_size = len(fmm_word_list)
    if bmm_word_list_size != fmm_word_list_size:
        if bmm_word_list_size < fmm_word_list_size:
            return bmm_word_list
        else:
            return fmm_word_list
    else:
        FSingle = 0
        BSingle = 0
        isSame = True
        for i in range(len(fmm_word_list)):
            if fmm_word_list[i] not in bmm_word_list:
                isSame = False
            if len(fmm_word_list[i])  == 1:
                FSingle = FSingle + 1
            if len(bmm_word_list[i]) == 1:
                BSingle = BSingle + 1
        if isSame:
            return fmm_word_list
        elif BSingle > FSingle:
            return fmm_word_list
        else:
            return bmm_word_list
cut_words('很高兴分享关于NLP的技术',getWordDic())
['很', '高兴', '分享', '关于', 'NLP', '的', '技术']

统计分词

通过机器学习技术,应用于分词任务上后,能够较好应对新词发现等特殊场景

把每个词看做是由词的最小单位的各个字组成的,如果相连的字在不同的文本中出现的次数越多,就证明这相连的字很可能就是一个词。因此我们就可以利用字与字相邻出现的频率来反应成词的可靠度,统计语料中相邻共现的各个字的组合的频度,当组合频度高于某-一个临界值时,我们便可认为此字组可能会构成-一个词语。

基于统计的分词一般要做如下两步操作

1):建立统计语言模型

2):对句子进行单词划分,然后对划分结果进行概率计算,获得概率最大的分词方式,如隐含马尔科夫(HMM)、条件随机场(CRF)

隐含马尔可夫模型(HMM)

是将分词作为字在字串中的序列标注任务来实现的。其基本思路是:每个字在构造一个特定的词语时都占据着–个确定的构词位置(即词位),现规定每个字最多只有四个构词位置:即B (词首) M (词中)、E (词尾)和S (单独成词), 那么下面句子1)的分词结果就可以直接表示成如2)所示的逐字标注形式:

1)中文/分词/是/.文本处理/不可或缺/的/一步!

2)中/B文/E分/B词/E是/S文/B本/M处/M理/E不/B可/M或/M缺/E的/S一//B步/E!/S

条件随机场(CRF)

在隐含马尔可夫中,有个很经典的假设,那就是每个状态只与它前面的状态有关。这样的假设显然是有偏差的,于是学者们提出了条件随机场算法,使得每个状态不止与他前面的状态有关,还与他后面的状态有关

混合分词

单纯的统计分词也有缺陷,那就是太过于依赖语料的质量,因此实践中多是采用这两种方法的结合,即混合分词

目前不管是基于规则的算法、还是基于HMM、CRF或者deep learning 等的方法,其分词效果在具体任务中,其实差距并没有那么明显。在实际工程应用中,多是基于一种分词算法,然后用其他分词算法加以辅助。最常用的方式就是先基于词典的方式进行分词,然后再用统计分词方法进行辅助。如此,能在保证词典分词准确率的基础上,对未登录词和歧义词有较好的识别,Jieba 分词工具便是基于这种方法的实现。

jieba

Jieba分词结合了基于规则和基于统计这两类方法。首先基于前缀词典进行词图扫描,前缀词典是指词典中的词按照前缀包含的顺序排列,例如词典中出现了“上”,之后以“上”开头的词都会出现在这一部分,例如“上海”,进而会出现“上海市”,从而形成一种层级包含结构。如果将词看作节点,词和词之间的分词符看作边,那么一种分词方案则对应着从第一个字到最后一个字的一-条分词路径。因此,基于前缀词典可以快速构建包含全部可能分词结果的有向无环图,这个图中包含多条分词路径,有向是指全部的路径都始于第一个字、止于最后一个字,无环是指节点之间不构成闭环。基于标注语料,使用动态规划的方法可以找出最大概率路径,并将其作为最终的分词结果。对于未登录词,Jieba使用了基于汉字成词的HMM模型,采用了Viterbi 算法进行推导。

▼精确模式:试图将句子最精确地切开,适合文本分析。

▼全模式:把句子中所有可以成词的词语都扫描出来,速度非常快,但是不能解决歧义。

▼搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

import jieba
sent ="中文分词是文本处理不可或缺的一步"
seg_list = jieba.cut(sent,cut_all=True)
print('全模式: ','/ '.join(seg_list))
seg_list = jieba.cut(sent,cut_all=False)
print('精确模式: ','/ '.join(seg_list))
seg_list = jieba.cut(sent)
print('默认精确模式: ','/ '.join(seg_list))
seg_list = jieba.cut_for_search(sent)
print('搜索引擎模式','/'.join(seg_list) )
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\ADMINI~1\AppData\Local\Temp\jieba.cache
Loading model cost 1.155 seconds.
Prefix dict has been built succesfully.


全模式:  中文/ 分词/ 是/ 文本/ 文本处理/ 本处/ 处理/ 不可/ 不可或缺/ 或缺/ 的/ 一步
精确模式:  中文/ 分词/ 是/ 文本处理/ 不可或缺/ 的/ 一步
默认精确模式:  中文/ 分词/ 是/ 文本处理/ 不可或缺/ 的/ 一步
搜索引擎模式 中文/分词/是/文本/本处/处理/文本处理/不可/或缺/不可或缺/的/一步

如需要代码或数据进群753035545


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值