日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

零基础入门NLP之搭建中文分词工具

發(fā)布時(shí)間:2025/3/15 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 零基础入门NLP之搭建中文分词工具 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 文本分析的基本過(guò)程

分詞就是中學(xué)學(xué)的斷句:

舉個(gè)例子來(lái)說(shuō)明:假設(shè)我們輸入一句話:北京歡迎你。則有可能的斷句為:

北,京,歡,迎,你

北京,歡,迎,你

北京,歡迎,你? 等等如果沒(méi)有語(yǔ)料庫(kù)的話就是這樣的枚舉。

分詞我們可以根據(jù)語(yǔ)料庫(kù)里面的次來(lái)分,比如語(yǔ)料庫(kù)里面有[北京,歡迎,你,歡,迎]則上面列出的就是我們可能的分詞結(jié)果用程序來(lái)是實(shí)現(xiàn)就是

需要的語(yǔ)料庫(kù):

https://github.com/liangqi/chinese-frequency-word-list

給出了每個(gè)詞出現(xiàn)的概率。相當(dāng)于建立unigram模型代碼如下

from collections import Counter import random import numpy as np with open('./data/現(xiàn)代漢語(yǔ)常用詞表.txt') as f:lines = f.readlines() sum = 0 word_prob = Counter() for line in lines:columns = line.strip().split()# 重復(fù)詞頻率直接相加,(相同詞多次出現(xiàn)是因?yàn)榘l(fā)音不同,即語(yǔ)義也不同,這里不做區(qū)分)word_prob[columns[0]] += int(columns[-1])sum += int(columns[-1]) # 頻率轉(zhuǎn)為概率 for word in word_prob:word_prob[word] /= sum

這段代碼的功能是讀取語(yǔ)料庫(kù)中的單詞,并統(tǒng)計(jì)每個(gè)詞出現(xiàn)的概率,我們可以去測(cè)試一下。

print([{word: word_prob[word]} for word in random.sample(word_prob.keys(), 2)]) print("詞典大小:%d" % len(word_prob)) print(np.sum(list(word_prob.values())))

成功讀取語(yǔ)料庫(kù)并計(jì)算出每個(gè)詞的概率后,我們可以開(kāi)始基于每個(gè)詞的概率開(kāi)始進(jìn)行分割。代碼如下

def sentence_break(str):"""求該句話在當(dāng)前詞典下的全切分。思路:狀態(tài)轉(zhuǎn)移,設(shè)M[i]是從句子開(kāi)始到第i個(gè)字所組成句的全切分,word是以字i結(jié)尾的可在詞典中找到的詞,則M[i] = M[i-len(word)] + wordstr: 字符串,傳入的句子"""# 存儲(chǔ)狀態(tài)memory = [[] for _ in range(len(str))]for i in range(0, len(str)):for j in range(0, i+1):# 從開(kāi)始到當(dāng)前cursor視為一個(gè)詞if j == 0:if str[j:i+1] in word_prob:memory[i].append([str[j:i+1]])continue# 確定依賴的之前狀態(tài)存在且(達(dá)成轉(zhuǎn)移條件:詞存在)if memory[j-1] and str[j:i+1] in word_prob:# 狀態(tài)轉(zhuǎn)移過(guò)程for state in memory[j-1]:memory[i].append(state + [str[j:i+1]])return memory[-1]

測(cè)試

print(sentence_break("北京歡迎你"))

計(jì)算每一句話出現(xiàn)的概率,并返回最大概率的一句話?

## TODO 編寫word_segment_naive函數(shù)來(lái)實(shí)現(xiàn)對(duì)輸入字符串的分詞 import mathdef word_segment_naive(input_str):"""1. 對(duì)于輸入字符串做分詞,并返回所有可行的分詞之后的結(jié)果。2. 針對(duì)于每一個(gè)返回結(jié)果,計(jì)算句子的概率3. 返回概率最高的最作為最后結(jié)果input_str: 輸入字符串 輸入格式:“今天天氣好”best_segment: 最好的分詞結(jié)果 輸出格式:["今天","天氣","好"]"""# TODO: 第一步: 計(jì)算所有可能的分詞結(jié)果,要保證每個(gè)分完的詞存在于詞典里,這個(gè)結(jié)果有可能會(huì)非常多。 segments = sentence_break(input_str) # 存儲(chǔ)所有分詞的結(jié)果。如果次字符串不可能被完全切分,則返回空列表(list)# 格式為:segments = [["今天",“天氣”,“好”],["今天",“天“,”氣”,“好”],["今“,”天",“天氣”,“好”],...]# TODO: 第二步:循環(huán)所有的分詞結(jié)果,并計(jì)算出概率最高的分詞結(jié)果,并返回best_segment = list()best_score = 0for seg in segments:# TODO ...if seg:score = 0for word in seg:# 防止下溢,取logscore += math.log(word_prob[word])if best_score == 0:best_segment = segbest_score = scoreelse:if score > best_score:best_segment = segbest_score = scorereturn best_segment

因?yàn)樯厦娴姆衷~和計(jì)算概率分開(kāi)進(jìn)行,我們可以通過(guò)建立一個(gè)有向無(wú)環(huán)圖來(lái)實(shí)現(xiàn)同時(shí)進(jìn)行(維特比算法)

## TODO 編寫word_segment_viterbi函數(shù)來(lái)實(shí)現(xiàn)對(duì)輸入字符串的分詞 import mathdef word_segment_viterbi(input_str):"""1. 基于輸入字符串,詞典,以及給定的unigram概率來(lái)創(chuàng)建DAG(有向圖)。2. 編寫維特比算法來(lái)尋找最優(yōu)的PATH3. 返回分詞結(jié)果input_str: 輸入字符串 輸入格式:“今天天氣好”best_segment: 最好的分詞結(jié)果 輸出格式:["今天","天氣","好"]"""# TODO: 第一步:根據(jù)詞典,輸入的句子,以及給定的unigram概率來(lái)創(chuàng)建帶權(quán)重的有向圖(Directed Graph)# 有向圖的每一條邊是一個(gè)單詞的概率(只要存在于詞典里的都可以作為一個(gè)合法的單詞),這些概率在 word_prob,如果不在word_prob里的單詞但在# 詞典里存在的,統(tǒng)一用概率值1e-100。# 圖是為了直觀起見(jiàn),邊表示字或詞及其概率,節(jié)點(diǎn)存儲(chǔ)狀態(tài),圖有沒(méi)有其實(shí)無(wú)所謂,從本質(zhì)上講其實(shí)就是個(gè)狀態(tài)轉(zhuǎn)移算法# 每個(gè)節(jié)點(diǎn)的狀態(tài)包含-log(P)和當(dāng)前最優(yōu)切分memory = [[0, []] for _ in range(len(input_str)+1)]# TODO: 第二步: 利用維特比算法來(lái)找出最好的PATH, 這個(gè)PATH是P(sentence)最大或者 -log P(sentence)最小的PATH。# TODO: 第三步: 根據(jù)最好的PATH, 返回最好的切分for i in range(1, len(input_str)+1):for j in range(i):# 這里偷個(gè)懶,默認(rèn)沒(méi)有形成詞的單字可以在詞典中找到(如果不成立事實(shí)上會(huì)返回完整句子,因?yàn)?log(1e-100)必然小于該值加某個(gè)非負(fù)數(shù)word = input_str[j:i]prob = word_prob[word] if word in word_prob else 1e-100score = memory[j][0] - math.log(prob)# 狀態(tài)更新if memory[i][0] == 0:memory[i][0] = scorememory[i][1] = memory[j][1] + [word]else:if score < memory[i][0]:memory[i][0] = scorememory[i][1] = memory[j][1] + [word]return memory[-1][1]

?

目前比較流行的中文分詞工具

jieba:做最好的 Python 中文分詞組件https://github.com/fxsjy/jieba
清華大學(xué)THULAC:一個(gè)高效的中文詞法分析工具包
中科院計(jì)算所NLPIR
哈工大LTP
FoolNLTK可能不是最快的開(kāi)源中文分詞,但很可能是最準(zhǔn)的開(kāi)源中文分詞
參考資料:https://zhuanlan.zhihu.com/p/95599399

總結(jié)

以上是生活随笔為你收集整理的零基础入门NLP之搭建中文分词工具的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。