目錄
- 一、前言
- 二、完全切分
- 三、正向最長(zhǎng)匹配
- 四、逆向最長(zhǎng)匹配
- 五、雙向最長(zhǎng)匹配
一、前言
我們需要分析某句話,就必須檢測(cè)該條語(yǔ)句中的詞語(yǔ)。
一般來(lái)說(shuō),一句話肯定包含多個(gè)詞語(yǔ),它們互相重疊,具體輸出哪一個(gè)由自然語(yǔ)言的切分算法決定。常用的切分算法有完全切分、正向最長(zhǎng)匹配、逆向最長(zhǎng)匹配以及雙向最長(zhǎng)匹配。
本篇博文將一一介紹這些常用的切分算法。
二、完全切分
完全切分是指,找出一段文本中的所有單詞。
不考慮效率的話,完全切分算法其實(shí)非常簡(jiǎn)單。只要遍歷文本中的連續(xù)序列,查詢?cè)撔蛄惺欠裨谠~典中即可。上一篇我們獲取了詞典的所有詞語(yǔ)dic,這里我們直接用代碼遍歷某段文本,完全切分出所有的詞語(yǔ)。代碼如下:
from pyhanlp import *
def load_dictionary():
IOUtil = JClass('com.hankcs.hanlp.corpus.io.IOUtil')
path = HanLP.Config.CoreDictionaryPath.replace('.txt', '.mini.txt')
dic = IOUtil.loadDictionary([path])
return set(dic.keySet())
def fully_segment(text, dic):
list = []
for i in range(len(text)):
for j in range(i + 1, len(text) + 1):
temp = text[i:j]
if temp in dic:
list.append(temp)
return list
if __name__ == "__main__":
dic = load_dictionary()
print(fully_segment("在絕對(duì)實(shí)力面前,一切的說(shuō)辭都是枉然", dic))
可以看到,完全切分算法輸出了文本中所有的單字與詞匯。
這里的算法原理是:開(kāi)始遍歷單個(gè)字,以該字為首,將后面每個(gè)字依次組合到單個(gè)字中,分析出這些組合字句是否在詞典中。第二次,從第二個(gè)字開(kāi)始,組合后面的字,以此類推。不懂的看下圖就明白了。
三、正向最長(zhǎng)匹配
雖然說(shuō)完全切分能獲取到所有出現(xiàn)在字典中的單詞,單字,但是我們獲取語(yǔ)句中單字一般來(lái)說(shuō)沒(méi)有任何意義,我們更希望獲取的是中文分詞,那種具有意義的詞語(yǔ)序列。
比如,上面我們希望“絕對(duì)實(shí)力”成為一整個(gè)詞,而不是“絕對(duì)”+“實(shí)力”之類的碎片。為了達(dá)到這個(gè)目的,我們需要完善一下我們的算法。考慮到越長(zhǎng)的單詞表達(dá)的意義更加的豐富,于是我們定義單詞越長(zhǎng)優(yōu)先級(jí)越高。
具體來(lái)說(shuō),就是在某個(gè)下標(biāo)為起點(diǎn)遞增查詞的過(guò)程中,優(yōu)先輸出更長(zhǎng)的單詞,這種規(guī)則被稱為最長(zhǎng)匹配算法。該下標(biāo)的掃描順序如果從前往后,則稱為正向最長(zhǎng)匹配,反之則為逆向最長(zhǎng)匹配。
下面,我們來(lái)實(shí)現(xiàn)正向最長(zhǎng)匹配,代碼如下:
def forward_segment(text, dic):
list = []
i = 0
while i len(text):
long_word = text[i]
for j in range(i + 1, len(text) + 1):
word = text[i:j]
if word in dic:
if len(word) > len(long_word):
long_word = word
list.append(long_word)
i += len(long_word)
return list
算法的原理:首先通過(guò)while循環(huán)判斷i是否超出了字符串的大小,如果沒(méi)有,獲取當(dāng)前第一個(gè)字符串為第一個(gè)最長(zhǎng)匹配結(jié)果,接著遍歷第一個(gè)字符串的所有可能組合結(jié)尾,如果在字典中,判斷當(dāng)前詞語(yǔ)是否大于前面的最長(zhǎng)匹配結(jié)果,如果是替換掉最長(zhǎng)。遍歷完成之后,將最長(zhǎng)的結(jié)果添加到列表中,然后再獲取第二字符,遍歷所有結(jié)尾組合,獲取最長(zhǎng)匹配。以此類推。
四、逆向最長(zhǎng)匹配
既然了解了正向如何匹配,那么逆向算法應(yīng)該也很好寫(xiě)。代碼如下:
def backward_segment(text, dic):
list = []
i = len(text) - 1
while i >= 0:
long_word = text[i]
for j in range(0, i):
word = text[j:i + 1]
if word in dic:
if len(word) > len(long_word):
long_word = word
break
list.append(long_word)
i -= len(long_word)
return list
算法的原理:就是上面的正向反過(guò)來(lái),但是這里并不是倒推文字,文字還是按語(yǔ)句的順序,但是長(zhǎng)度是從最長(zhǎng)到最短,也就是遇到第一個(gè)就可以返回了添加了。比正向最長(zhǎng)匹配算法節(jié)約時(shí)間。
五、雙向最長(zhǎng)匹配
雖然逆向比正向節(jié)約時(shí)間,但本身有一個(gè)很大的漏洞。假如我現(xiàn)在的句子中有一段“項(xiàng)目的”字符串,那么正向會(huì)出現(xiàn)“項(xiàng)目”,“的”兩個(gè)詞匯,而逆向會(huì)出現(xiàn):“項(xiàng)”,“目的”兩個(gè)詞匯。
為此,我們的算法工程師提出了新的匹配規(guī)則,雙向最長(zhǎng)匹配。這是一種融合兩種匹配方法的復(fù)雜規(guī)則,流程如下:
同時(shí)執(zhí)行正向和逆向最長(zhǎng)匹配,若兩者的詞數(shù)不同,則返回詞數(shù)更少的一個(gè)否則,返回兩者中單字更少的那一個(gè)。當(dāng)單字也相同時(shí),優(yōu)先返回逆向最長(zhǎng)匹配結(jié)果
具體代碼如下:
#統(tǒng)計(jì)單字個(gè)數(shù)
def count_single_char(list):
return sum(1 for word in list if len(word) == 1)
#雙向匹配算法
def bidirectional_segment():
f = forward_segment("在絕對(duì)實(shí)力面前,一切的說(shuō)辭都是枉然", dic)
b = backward_segment("在絕對(duì)實(shí)力面前,一切的說(shuō)辭都是枉然", dic)
if len(f) len(b):
return f
elif len(f) > len(b):
return b
else:
if count_single_char(f)count_single_char(b):
return f
else:
return b
到此這篇關(guān)于Python自然語(yǔ)言處理之切分算法詳解的文章就介紹到這了,更多相關(guān)python切分算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- python 算法題——快樂(lè)數(shù)的多種解法
- python使用ProjectQ生成量子算法指令集
- Python機(jī)器學(xué)習(xí)算法之決策樹(shù)算法的實(shí)現(xiàn)與優(yōu)缺點(diǎn)
- Python集成學(xué)習(xí)之Blending算法詳解
- python3實(shí)現(xiàn)Dijkstra算法最短路徑的實(shí)現(xiàn)
- Python實(shí)現(xiàn)K-means聚類算法并可視化生成動(dòng)圖步驟詳解
- python入門之算法學(xué)習(xí)
- Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法的分類