03中文分词

03中文分词,第1张

1. 为什么要分词 1.1 中文分词的目的

让机器更好的“理解”文章。


1.2 英文天然分词,比中文更适合做相似度比对?

No,英文中每个单词包含很多不同的意思。


1.3 分词是越细越好吗?

视情况而定

搜索——>越细越好——>因为其比较注重召回

推荐——>粗一点好——>因为其更注重精准度(精准推荐),粒度粗有利于“保留语义”

2. 怎么分词

里面涉及的一些算法:

容易切分的:用字典匹配,动态规划,vterbi算法

不容易切分的:隐马尔可夫模型

2.1 字典匹配 2.1.1前缀树

如下图所示,一共包含了8个键的trie结构:"A", "to", "tea", "ted", "ten", "i", "in", "inn".

详情见:https://zh.wikipedia.org/wiki/Trie

2.1.2字典匹配案例

词库为:北京,北京大学,大学生,生活,学生,中心,活动

需要切分的句子:北京大学生活动中心

(1) 将词库存到前缀树中:

 

(2) 正向匹配

计算词库中单词的最大长度maxLen。


“北京大学生活动中心”正向匹配的分词结果为:[北京大学,生活,动,中心]

(3) 反向匹配

正向匹配和反向匹配的原理相同,唯一不同的是,正向匹配是从左到右依次滑窗,反向匹配是从右向左依次滑窗。


“北京大学生活动中心”反向匹配的分词结果为:[北京,大学生,活动,中心]

2.1.3 字典匹配实现

下面是一个反向最大匹配的例子

import sys

WordDic = {}
MaxWordLen = 1

def LoadLexicon(lexiconFile):
    global MaxWordLen
    infile = open(lexiconFile, 'r', encoding='gb2312')
    s = infile.readline().strip()
    while len(s) > 0:
        #s = s.decode("gb2312")
        WordDic[s] = 1
        if len(s) > MaxWordLen:
            MaxWordLen = len(s)
        s = infile.readline().strip()
    infile.close()

def BMM(s):
    global MaxWordLen
    wordlist = []
    i = len(s)
    while i > 0:
        start = i - MaxWordLen
        if start < 0:
            start = 0
        while start < i:
            tmpWord = s[start:i]
            if tmpWord in WordDic:
                wordlist.insert(0, tmpWord)
                break
            else:
                start += 1
        if start >= i:
            wordlist.insert(0, s[i-1:i])
            start = i - 1
        i = start
    return wordlist

def PrintSegResult(wordlist):
    print("After word-seg:")
    for i in range(len(wordlist)-1):
        print(wordlist[i])
    print(wordlist[len(wordlist)-1])

LoadLexicon("./lexicon.txt")

# inputStr = u"南京市长江大桥"
inputStr = u"北京大学生活动中心"

wordlist = BMM(inputStr)
PrintSegResult(wordlist)

其中BMM为Back Max Match,./lexicon.txt 为词库,比如:

正向匹配代码实现,待续:

Q:正向/反向匹配效果不好?

———主要是因为词库(lexicon)不好,词库准全的问题;

———用规则的方式永远也解决不了所有的问题。


那用什么来解决呢?

Q有两种切分方法,正向匹配:[北京大学,生活,动,中心],反向匹配:[北京,大学生,活动,中心], 到底用哪一个呢?机器怎么判断哪一个更好呢?

——使用概率语言模型 

2.2概率语言模型

顾名思义:找概率最大方案。


2.2.1 概率语言模型的理论知识

其中C表示句子,S表示句子的切分方案。


P(C): 句子出现的概率,往往是常数。


P(C|S):在切分方案S的条件下,得到句子C的概率。


为1,把切分方案S中的词拼到一起就是句子C了。


故:

其中假设: 句子中,每个词的出现独立同分布,所以:

Q每个词出现的概率一般要怎么算呢?从哪里来呢?

 

Q如果一个句子很长,切分出来了很多个词,且每个词的概率又不高,P(S)很小,向下溢出或是很难比较出两个方案的优劣(因为两个方案的P(S)很小,差0.00000000001,如果精度不够,可能就会认为两个方案是一样的?)

——万能的log登场

——使用log,一举两得

      a. 防止最终结果向下溢出

      b. 乘法变加法,计算速度更快

Q:句子中的词真的是独立同分布的吗?

No,实际中,独立性假设并不成立。


一元概率语言模型:我们上述的认为一个词的出现不依赖与它前面出现的词(即句子中的词是独立同分布的),叫做一元概率模型(Unigram),该模型只考虑了切分出的词数和词频。


二元概率语言模型:假设当前单词只与前一个单词有关

三元概率语言模型:假设当前单词只与前个单词有关 

 

……

N元概率语言模型:假设当前单词与前N个单词有关

2.2.2 概率语言模型的案例

接着2.1.2 的案例来说

词库为:北京,北京大学,大学生,生活,学生,中心,活动

需要切分的句子:北京大学生活动中心

现在有两种切分方案:

第一种正向匹配:[北京大学,生活,动,中心]

第二种反向匹配:[北京,大学生,活动,中心]

下面我们就用概率语言模型,来看一下,哪种方案更好:

P(S1) = P([北京大学,生活,动,中心]) = P(北京大学) * P(生活) * P(生活)* P(中心)

P(S2) = P([北京,大学生,活动,中心]) = P(北京) * P(大学生) * P(活动)* P(中心)

 一起用代码来实现一下一元概率和二元概率模型吧:

 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/607183.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-14
下一篇 2022-04-14

发表评论

登录后才能评论

评论列表(0条)

保存