日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自然语言处理3 -- 词性标注

發(fā)布時間:2023/12/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自然语言处理3 -- 词性标注 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

系列文章,請多關(guān)注
Tensorflow源碼解析1 – 內(nèi)核架構(gòu)和源碼結(jié)構(gòu)
NLP預(yù)訓(xùn)練模型1 – 綜述
Transformer家族1 – Transformer詳解和源碼分析

自然語言處理1 – 分詞
自然語言處理2 – jieba分詞用法及原理
自然語言處理3 – 詞性標注
自然語言處理4 – 句法分析
自然語言處理5 – 詞向量
自然語言處理6 – 情感分析

1 概述

詞性標注在自然語言處理中也屬于基礎(chǔ)性的模塊,為句法分析、信息抽取等工作打下基礎(chǔ)。和分詞一樣,中文詞性標注也存在著很多難點,比如一詞多詞性,未登錄詞處理等諸多問題。通過基于字符串匹配的字典查詢算法和基于統(tǒng)計的詞性標注算法,可以很好的解決這些問題。一般需要先將語句進行分詞,然后再進行詞性標注。

2 詞性標注難點

詞性作為詞語基本的語法屬性,是詞語和語句的關(guān)鍵性特征。詞性種類也很多,ICTCLAS 漢語詞性標注集歸納的詞性種類及其表示見 https://www.cnblogs.com/chenbjin/p/4341930.html。詞性標注中的難點主要有

  • 相對于英文,中文缺少詞形態(tài)變化,不能從詞的形態(tài)來識別詞性
  • 一詞多詞性很常見。統(tǒng)計發(fā)現(xiàn),一詞多詞性的概率高達22.5%。而且越常用的詞,多詞性現(xiàn)象越嚴重。比如“研究”既可以是名詞(“基礎(chǔ)性研究”),也可以是動詞(“研究計算機科學(xué)”)。
  • 詞性劃分標準不統(tǒng)一。詞類劃分粒度和標記符號等,目前還沒有一個廣泛認可的統(tǒng)一的標準。比如LDC標注語料中,將漢語一級詞性劃分為33類,而北京大學(xué)語料庫則將其劃分為26類。詞類劃分標準和標記符號的不統(tǒng)一,以及分詞規(guī)范的含糊,都給詞性標注帶來了很大的困難。jieba分詞采用了使用較為廣泛的ICTCLAS 漢語詞性標注集規(guī)范。
  • 未登錄詞問題。和分詞一樣,未登錄詞的詞性也是一個比較大的課題。未登錄詞不能通過查找字典的方式獲取詞性,可以采用HMM隱馬爾科夫模型等基于統(tǒng)計的算法。
  • 3 詞性標注算法

    和分詞一樣,詞性標注算法也分為兩大類,基于字符串匹配的字典查找算法和基于統(tǒng)計的算法。jieba分詞就綜合了兩種算法,對于分詞后識別出來的詞語,直接從字典中查找其詞性。而對于未登錄詞,則采用HMM隱馬爾科夫模型和viterbi算法來識別。

    3.1 基于字符串匹配的字典查找算法

    先對語句進行分詞,然后從字典中查找每個詞語的詞性,對其進行標注即可。jieba詞性標注中,對于識別出來的詞語,就是采用了這種方法。這種方法比較簡單,通俗易懂,但是不能解決一詞多詞性的問題,因此存在一定的誤差。

    下圖即為jieba分詞中的詞典的一部分詞語。每一行對應(yīng)一個詞語,分為三部分,分別為詞語名 詞數(shù) 詞性。因此分詞完成后只需要在字典中查找該詞語的詞性即可對其完成標注。

    3.2 基于統(tǒng)計的詞性標注算法

    和分詞一樣,我們也可以通過HMM隱馬爾科夫模型來進行詞性標注。觀測序列即為分詞后的語句,隱藏序列即為經(jīng)過標注后的詞性標注序列。起始概率 發(fā)射概率和轉(zhuǎn)移概率和分詞中的含義大同小異,可以通過大規(guī)模語料統(tǒng)計得到。觀測序列到隱藏序列的計算可以通過viterbi算法,利用統(tǒng)計得到的起始概率 發(fā)射概率和轉(zhuǎn)移概率來得到。得到隱藏序列后,就完成了詞性標注過程。

    4 jieba詞性標注原理

    jieba在分詞的同時,可以進行詞性標注。利用jieba.posseg模塊來進行詞性標注,會給出分詞后每個詞的詞性。詞性標示兼容ICTCLAS 漢語詞性標注集,可查閱網(wǎng)站https://www.cnblogs.com/chenbjin/p/4341930.html

    import jieba.posseg as pseg words = pseg.cut("我愛北京天安門") for word, flag in words: ... print('%s %s' % (word, flag)) ... 我 r # 代詞 愛 v # 動詞 北京 ns # 名詞 天安門 ns # 名詞

    下面來對pseg.cut()進行詳細的分析,其主要流程為

  • 準備工作:check字典是否初始化好,如果沒有則先初始化字典。將語句轉(zhuǎn)為UTF-8或者GBK。根據(jù)正則匹配,將輸入文本分隔成一個個語句。
  • 遍歷語句list,對每個語句進行單獨分詞和詞性標注。
  • 對于未登錄詞,使用HMM隱馬爾科夫模型處理。
  • 4.1 準備工作

    準備工作中做的事情和jieba分詞基本一致,check字典是否初始化好,如果沒有則先初始化字典。將語句轉(zhuǎn)為UTF-8或者GBK。根據(jù)正則匹配,將輸入文本分隔成一個個語句。代碼如下。

    def __cut_internal(self, sentence, HMM=True):# 如果沒有字典沒有初始化,則先加載字典。否則直接使用字典緩存即可。self.makesure_userdict_loaded()# 將語句轉(zhuǎn)為UTF-8或者GBKsentence = strdecode(sentence)# 根據(jù)正則匹配,將輸入文本分隔成一個個語句。分隔符包括空格 逗號 句號等。blocks = re_han_internal.split(sentence)# 根據(jù)是否采用了HMM模型來進行不同方法的選擇if HMM:cut_blk = self.__cut_DAGelse:cut_blk = self.__cut_DAG_NO_HMM# 遍歷正則匹配分隔好的語句,對每個語句進行單獨的分詞和詞性標注for blk in blocks:if re_han_internal.match(blk):# 分詞和詞性標注for word in cut_blk(blk):yield wordelse:tmp = re_skip_internal.split(blk)for x in tmp:if re_skip_internal.match(x):yield pair(x, 'x')else:for xx in x:if re_num.match(xx):yield pair(xx, 'm')elif re_eng.match(x):yield pair(xx, 'eng')else:yield pair(xx, 'x')

    4.2 遍歷語句,進行分詞和詞性標注

    步驟和jieba分詞基本一致,主體步驟如下,詳細的每個步驟見 自然語言處理2jieba分詞用法及原理

  • 得到語句的有向無環(huán)圖DAG
  • 動態(tài)規(guī)劃構(gòu)建Route,計算從語句末尾到語句起始,DAG中每個節(jié)點到語句結(jié)束位置的最大路徑概率,以及概率最大時節(jié)點對應(yīng)詞語的結(jié)束位置
  • 遍歷每個節(jié)點的Route,組裝詞語組合。
  • 如果詞語不在字典中,也就是新詞,使用HMM隱馬爾科夫模型進行分割
  • 通過yield將詞語逐個返回。
  • def __cut_DAG(self, sentence):# 構(gòu)建DAG有向無環(huán)圖,得到語句分詞所有可能的路徑DAG = self.tokenizer.get_DAG(sentence)route = {}# 動態(tài)規(guī)劃,計算從語句末尾到語句起始,DAG中每個節(jié)點到語句結(jié)束位置的最大路徑概率,以及概率最大時節(jié)點對應(yīng)詞語的結(jié)束位置self.tokenizer.calc(sentence, DAG, route)# 遍歷每個節(jié)點的Route,組裝詞語組合。x = 0buf = ''N = len(sentence)while x < N:# y表示詞語的結(jié)束位置,x為詞語的起始位置y = route[x][1] + 1# 從起始位置x到結(jié)束位置y,取出一個詞語l_word = sentence[x:y]if y - x == 1:# 單字,一個漢字構(gòu)成的一個詞語buf += l_wordelse:# 多漢字詞語if buf:if len(buf) == 1:# 單字直接從字典中取出其詞性。使用pair將分詞和詞性一起輸出。yield pair(buf, self.word_tag_tab.get(buf, 'x'))elif not self.tokenizer.FREQ.get(buf):# 詞語不在字典中,也就是新詞,使用HMM隱馬爾科夫模型進行分割recognized = self.__cut_detail(buf)for t in recognized:yield telse:# 詞語在字典中,直接查找字典并取出詞性。for elem in buf:yield pair(elem, self.word_tag_tab.get(elem, 'x'))buf = ''yield pair(l_word, self.word_tag_tab.get(l_word, 'x'))# 該節(jié)點取詞完畢,跳到下一個詞語的開始位置x = y# 通過yield,逐詞返回上一步切分好的詞語if buf:if len(buf) == 1:yield pair(buf, self.word_tag_tab.get(buf, 'x'))elif not self.tokenizer.FREQ.get(buf):recognized = self.__cut_detail(buf)for t in recognized:yield telse:for elem in buf:yield pair(elem, self.word_tag_tab.get(elem, 'x'))

    其中word_tag_tab在初始化加載詞典階段構(gòu)建得到,它使用詞語為key,對應(yīng)詞性為value。代碼如下

    def load_word_tag(self, f):self.word_tag_tab = {}f_name = resolve_filename(f)# 遍歷字典的每一行。每一行對應(yīng)一個詞語。包含詞語 詞數(shù) 詞性三部分for lineno, line in enumerate(f, 1):try:# 去除首尾空格符line = line.strip().decode("utf-8")if not line:continue# 利用空格將一行分隔為詞語 詞數(shù) 詞性三部分word, _, tag = line.split(" ")# 使用詞語為key,詞性為value,構(gòu)造Dictself.word_tag_tab[word] = tagexcept Exception:raise ValueError('invalid POS dictionary entry in %s at Line %s: %s' % (f_name, lineno, line))f.close()

    4.3 未登錄詞,HMM隱馬爾科夫模型處理

    和分詞一樣,詞性標注中,也使用HMM隱馬爾科夫模型來處理未登錄詞。通過大規(guī)模語料統(tǒng)計,得到起始概率 發(fā)射概率和轉(zhuǎn)移概率。分別對應(yīng)prob_start.py prob_emit.py和prob_trans.py三個文件,他們給出了詞語在BEMS四種情況下,每種詞性對應(yīng)的概率。然后使用viterbi算法,利用得到的三個概率,將觀測序列(分詞后的語句)轉(zhuǎn)化得到隱藏序列(詞性標注序列)。這樣就完成了未登錄詞的詞性標注。代碼如下。

    # 通過HMM隱馬爾科夫模型獲取詞性標注序列,解決未登錄的問題def __cut(self, sentence):# 通過viterbi算法,利用三個概率,由語句觀測序列,得到詞性標注隱藏序列# prob為# pos_list對應(yīng)每個漢字,包含分詞標注BEMS和詞語詞性兩部分。prob, pos_list = viterbi(sentence, char_state_tab_P, start_P, trans_P, emit_P)begin, nexti = 0, 0# 遍歷語句的每個漢字,如果是E或者S時,也就是詞語結(jié)束或者單字詞語,則分隔得到詞語和詞性pairfor i, char in enumerate(sentence):pos = pos_list[i][0]if pos == 'B':# B表示詞語的開始begin = ielif pos == 'E':# E表示詞語的結(jié)束,此時輸出詞語和他的詞性yield pair(sentence[begin:i + 1], pos_list[i][1])nexti = i + 1elif pos == 'S':# S表示單字詞語,此時也輸出詞語和他的詞性yield pair(char, pos_list[i][1])nexti = i + 1# 一般不會走到這兒,以防萬一。對剩余的所有漢字一起輸出一個詞語和詞性。if nexti < len(sentence):yield pair(sentence[nexti:], pos_list[nexti][1])

    觀測序列到隱藏序列的計算,則通過viterbi算法實現(xiàn)。代碼如下

    # 通過viterbi算法,由觀測序列,也就是語句,來得到隱藏序列,也就是BEMS標注序列和詞性標注序列 # obs為語句,states為"BEMS"四種狀態(tài), # start_p為起始概率, trans_p為轉(zhuǎn)移概率, emit_p為發(fā)射概率,三者通過語料訓(xùn)練得到 def viterbi(obs, states, start_p, trans_p, emit_p):V = [{}] # 每個漢字的每個BEMS狀態(tài)的最大概率。mem_path = [{}] # 分詞路徑# 初始化每個state,states為"BEMS"all_states = trans_p.keys()for y in states.get(obs[0], all_states): # initV[0][y] = start_p[y] + emit_p[y].get(obs[0], MIN_FLOAT)mem_path[0][y] = ''# 逐字進行處理for t in xrange(1, len(obs)):V.append({})mem_path.append({})#prev_states = get_top_states(V[t-1])prev_states = [x for x in mem_path[t - 1].keys() if len(trans_p[x]) > 0]prev_states_expect_next = set((y for x in prev_states for y in trans_p[x].keys()))obs_states = set(states.get(obs[t], all_states)) & prev_states_expect_nextif not obs_states:obs_states = prev_states_expect_next if prev_states_expect_next else all_states# 遍歷每個狀態(tài)for y in obs_states:# 計算前一個狀態(tài)到本狀態(tài)的最大概率和它的前一個狀態(tài)prob, state = max((V[t - 1][y0] + trans_p[y0].get(y, MIN_INF) +emit_p[y].get(obs[t], MIN_FLOAT), y0) for y0 in prev_states)# 將該漢字下的某狀態(tài)(BEMS)的最大概率記下來V[t][y] = prob# 記錄狀態(tài)轉(zhuǎn)換路徑mem_path[t][y] = statelast = [(V[-1][y], y) for y in mem_path[-1].keys()]# if len(last)==0:# print obsprob, state = max(last)route = [None] * len(obs)i = len(obs) - 1while i >= 0:route[i] = statestate = mem_path[i][state]i -= 1return (prob, route)

    5 總結(jié)

    jieba可以在分詞的同時,完成詞性標注,因此標注速度可以得到保證。通過查詢字典的方式獲取識別詞的詞性,通過HMM隱馬爾科夫模型來獲取未登錄詞的詞性,從而完成整個語句的詞性標注。但可以看到查詢字典的方式不能解決一詞多詞性的問題,也就是詞性歧義問題。故精度上還是有所欠缺的。

    系列文章,請多關(guān)注
    Tensorflow源碼解析1 – 內(nèi)核架構(gòu)和源碼結(jié)構(gòu)
    NLP預(yù)訓(xùn)練模型1 – 綜述
    Transformer家族1 – Transformer詳解和源碼分析

    自然語言處理1 – 分詞
    自然語言處理2 – jieba分詞用法及原理
    自然語言處理3 – 詞性標注
    自然語言處理4 – 句法分析
    自然語言處理5 – 詞向量
    自然語言處理6 – 情感分析

    總結(jié)

    以上是生活随笔為你收集整理的自然语言处理3 -- 词性标注的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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