《自然语言处理:基于预训练模型的方法》读书笔记:第2章 自然语言处理基础
目錄
第2章 自然語言處理基礎(chǔ)
2.1 文本的表示
2.1.1 詞的獨熱表示
2.1.2 詞的分布式表示
2.1.3 詞嵌入表示
2.1.4 文本的詞袋表示
2.2 自然語言處理任務
2.2.1 語言模型
2.2.2 自然語言處理基礎(chǔ)任務
2.2.3 自然語言處理應用任務
2.3 基本問題
2.3.1 文本分類問題
2.3.2 結(jié)構(gòu)預測問題
2.3.3 序列到序列問題
2.4 評價指標
第2章 自然語言處理基礎(chǔ)
2.1 文本的表示
字符串是文本最自然,也是最常用的機內(nèi)存儲形式。所謂字符串,即字符序列,而其中的一個字符本質(zhì)上就是一個整數(shù)。基于字符串的文本表示方式可以實現(xiàn)簡單的字符串增刪改查等編輯任務,并能夠通過編輯距離等算法計算兩個字符串之間的字面相似度。
基于規(guī)則的方法存在很多問題。首先,規(guī)則的歸納依賴專家的經(jīng)驗,需要花費大量的人力、物力和財力;其次,規(guī)則的表達能力有限,很多語言現(xiàn)象無法用簡單的規(guī)則描述;最后,隨著規(guī)則的增多,規(guī)則之間可能存在矛盾和沖突的情況,導致最終無法做出決策。
基于機器學習的自然語言處理技術(shù)最本質(zhì)的思想是將文本表示為向量,其中的每一維代表一個特征。在進行決策的時候,只要對這些特征的相應值進行加權(quán)求和,就可以得到一個分數(shù)用于最終的判斷。
除了可以應用于基于機器學習的方法,文本向量表示還可以用于計算兩個文本之間的相似度,即使用余弦函數(shù)等度量函數(shù)表示兩個向量之間的相似度,并應用于信息檢索任務。
2.1.1 詞的獨熱表示
所謂詞的獨熱表示,即使用一個詞表大小的向量表示一個詞,然后將詞表中的第i個詞wi表示為向量:
在該向量中,詞表中第i個詞在第i維上被設(shè)置為1,其余維均為0。這種表示被稱為詞的獨熱表示或獨熱編碼。
獨熱表示的一個主要問題就是不同詞使用完全不同的向量進行表示,這會導致即使兩個詞在語義上很相似,但是通過余弦函數(shù)來度量它們之間的相似度時值卻為0。另外,當應用于基于機器學習的方法時,獨熱模型會導致數(shù)據(jù)稀疏問題。
為了緩解數(shù)據(jù)稀疏問題,傳統(tǒng)的做法是除了詞自身,再提取更多和詞相關(guān)的泛化特征,如詞性特征、詞義特征和詞聚類特征等。
2.1.2 詞的分布式表示
1.分布式語義假設(shè)
詞的含義可由其上下文的分布進行表示。
基于該思想,可以利用大規(guī)模的未標注文本數(shù)據(jù),根據(jù)每個詞的上下文分布對此進行表示。
除了詞,上下文的選擇有很多種方式,而選擇不同的上下文得到的詞向量表示性質(zhì)會有所不同。
2.點互信息
如果一個詞語很多詞共現(xiàn),則降低其權(quán)重;反之,如果一個詞只與個別詞共現(xiàn),則提高其權(quán)重。信息論中的點互信息恰好能做到這一點。對于詞w和上下文c是,其PMI為:
可以通過最大似然估計分別計算相關(guān)的概率值。
import numpy as npM = np.array([[0, 2, 1, 1, 1, 1, 1, 2, 1, 3],[2, 0, 1, 1, 1, 0, 0, 1, 1, 2],[1, 1, 0, 1, 1, 0, 0, 0, 0, 1],[1, 1, 1, 0, 1, 0, 0, 0, 0, 1],[1, 1, 1, 1, 0, 0, 0, 0, 0, 1],[1, 0, 0, 0, 0, 0, 1, 1, 0, 1],[1, 0, 0, 0, 0, 1, 0, 1, 0, 1],[2, 1, 0, 0, 0, 1, 1, 0, 1, 1],[1, 1, 0, 0, 0, 0, 0, 1, 0, 1],[3, 2, 1, 1, 1, 1, 1, 2, 1, 0]])def pmi(M, positive=True):col_totals = M.sum(axis=0) # 按列求和row_totals = M.sum(axis=1) # 按行求和total = col_totals.sum() # 總頻次expected = np.outer(row_totals, col_totals) / total # 獲得每個元素的分子M = M / expectedwith np.errstate(divide='ignore'): # 不顯示log(0)的警告:M = np.log(M)M[np.isinf(M)] = 0.0 # 將log(0)置為0if positive:M[M < 0] = 0.0return MM_pmi = pmi(M) np.set_printoptions(precision=2) # 打印結(jié)果保留兩位小數(shù) print(M_pmi) [[0. 0.17 0.06 0.06 0.06 0.28 0.28 0.28 0.28 0.28][0.17 0. 0.43 0.43 0.43 0. 0. 0. 0.65 0.25][0.06 0.43 0. 1.02 1.02 0. 0. 0. 0. 0.14][0.06 0.43 1.02 0. 1.02 0. 0. 0. 0. 0.14][0.06 0.43 1.02 1.02 0. 0. 0. 0. 0. 0.14][0.28 0. 0. 0. 0. 0. 1.46 0.77 0. 0.36][0.28 0. 0. 0. 0. 1.46 0. 0.77 0. 0.36][0.42 0.09 0. 0. 0. 0.9 0.9 0. 0.9 0. ][0.28 0.65 0. 0. 0. 0. 0. 0.77 0. 0.36][0.2 0.17 0.06 0.06 0.06 0.28 0.28 0.28 0.28 0. ]]3.奇異值分解
import numpy as np import matplotlib.pyplot as plt from pylab import mpl # 設(shè)置顯示中文字體 mpl.rcParams["font.sans-serif"] = ["SimHei"]M = np.array([[0, 2, 1, 1, 1, 1, 1, 2, 1, 3],[2, 0, 1, 1, 1, 0, 0, 1, 1, 2],[1, 1, 0, 1, 1, 0, 0, 0, 0, 1],[1, 1, 1, 0, 1, 0, 0, 0, 0, 1],[1, 1, 1, 1, 0, 0, 0, 0, 0, 1],[1, 0, 0, 0, 0, 0, 1, 1, 0, 1],[1, 0, 0, 0, 0, 1, 0, 1, 0, 1],[2, 1, 0, 0, 0, 1, 1, 0, 1, 1],[1, 1, 0, 0, 0, 0, 0, 1, 0, 1],[3, 2, 1, 1, 1, 1, 1, 2, 1, 0]])def pmi(M, positive=True):col_totals = M.sum(axis=0) # 按列求和row_totals = M.sum(axis=1) # 按行求和total = col_totals.sum() # 總頻次expected = np.outer(row_totals, col_totals) / total # 獲得每個元素的分子M = M / expectedwith np.errstate(divide='ignore'): # 不顯示log(0)的警告:M = np.log(M)M[np.isinf(M)] = 0.0 # 將log(0)置為0if positive:M[M < 0] = 0.0return MM_pmi = pmi(M) np.set_printoptions(precision=2) # 打印結(jié)果保留兩位小數(shù) print(M_pmi)U, s, Vh = np.linalg.svd(M_pmi)words = ['我', '喜歡', '自然', '語言', '處理', '愛', '深度', '學習', '機器', '。']for i in range(len(words)):plt.text(U[i, 0], U[i, 1], words[i])plt.show()可見:上下文比較相近的詞在空間上的距離比較近,如“深度” “學習”等;而“我”和“?!钡雀哳l詞則與其他詞語距離比較遠。
雖然在基于傳統(tǒng)機器學習的方法中,詞的分布式表示取得了不錯的效果,但是其仍然存在一些問題。首先,當共現(xiàn)矩陣規(guī)模較大時,奇異值分解的運行速度非常慢;其次,如果想在原來語料庫的基礎(chǔ)上增加更多的數(shù)據(jù),則需要重新運行奇異值分解算法,代價非常高;另外,分布式表示只能用于表示比較短的單元,如詞或短語等,如果待表示的單元比較長,如段落、句子等,由于與其共現(xiàn)的上下文會非常少,則無法獲得有效的分布式表示;最后,分布式表示一旦訓練完成,則無法修改,也就是說,無法根據(jù)具體的任務調(diào)整其表示方式。為了解決這些問題,可引入一種新的詞表示方式——詞嵌入表示。
2.1.3 詞嵌入表示
與詞的分布式表示相類似,詞嵌入表示也使用一個連續(xù)、低維、稠密的向量來表示詞,經(jīng)常直接簡稱為詞向量,但于分布式表示不同之處在于其賦值方式。在詞的分布式表示中,向量值是通過對語料庫進行統(tǒng)計得到的,然后再經(jīng)過點互信息、奇異值分解等變換,一旦確定則無法修改。而詞向量中的向量值,是隨著目標任務的優(yōu)化過程自動調(diào)整的,也就是說,可以將詞向量中的向量值看作模型的參數(shù)。
2.1.4 文本的詞袋表示
所謂詞袋表示,就是假設(shè)文本中的詞語是沒有順序的集合,將文本中的全部詞所對應的向量表示(既可以是獨熱表示,也可以是分布式表示或詞向量)相加,即構(gòu)成了文本的向量表示。
2.2 自然語言處理任務
2.2.1 語言模型
語言模型是描述自然語言概率分布的模型,是一個非常基礎(chǔ)和重要的自然語言處理任務。
1.N元語言模型
語言模型的基本任務是在給定次序列w1w2...wt-1的條件下,對下一時刻t可能出現(xiàn)的詞wt的條件概率進行估計。
馬爾可夫假設(shè):“下一個詞出現(xiàn)的概率只依賴于它前面n-1個詞”, 即
滿足這種假設(shè)的模型,被稱為N元語法或N元文法模型。特別地,當n=1時,下一個詞的出現(xiàn)獨立于其歷史,相應的一元語法通常記作unigram。當n=2時,下一個詞只依賴于前1個詞,對應的二元語法記作bigram。二元語法模型也被稱為一階馬爾可夫鏈。類似地,三元語法假設(shè)(n=3)也被稱為二階馬爾可夫假設(shè),相應的三元語法記作trigram。n的取值越大,考慮的歷史越完整,在unigram模型中,由于詞與詞之間相互獨立,因此它是與語序無關(guān)的。
2.平滑?
為了避免“零概率”問題,需要使用平滑技術(shù)調(diào)整概率估計的結(jié)果。
折扣法平滑的基本思想是“損有余而補不足”,即從頻繁出現(xiàn)的N-gram中勻出一部分概率并分配給低頻次(含零頻次)的N-gram,從而使得整體概率分布趨于均勻。
加1平滑是一種典型的折扣法,也被稱為拉普拉斯平滑,它假設(shè)所有N-gram的頻次比實際出現(xiàn)的頻次多一次。
對于unigram模型來說,平滑之后的概率可由以下公式計算:
對于bigram模型,則有:
以bigram語言模型為例,使用加平滑之后的條件概率為:
由于引入了馬爾可夫假設(shè),導致N元語言模型無法對長度超過N的長距離詞語依賴關(guān)系進行建模,如果將N擴大,又會帶來更嚴重的數(shù)據(jù)稀疏問題,同時還會急劇增加模型的參數(shù)量,為存儲和計算都帶來極大的挑戰(zhàn)。
3.語言模型性能評價
如何衡量一個語言模型的好壞?一種方法是將其應用于具體的外部任務,并根據(jù)該任務上指標的高低對語言模型進行評價。這種方法也被稱為“外部任務評價”。
目前最為常用的是基于困惑度的“內(nèi)部評價”方式。
測試集的概率:
困惑度則為模型分配給測試集中每一個詞的概率的幾何平均值的倒數(shù):
困惑度越小,意味著單詞序列的概率越大,也意味著模型能夠更好地解釋測試集中的數(shù)據(jù)。困惑度可以作為一種快速評價語言模型性能的指標。
2.2.2 自然語言處理基礎(chǔ)任務
自然語言處理的一大特點是任務種類紛繁復雜,有多種劃分的方式。從處理順序的角度,可以分為底層的基礎(chǔ)任務以及上層的應用任務。
1.中文分詞
詞是最小的能獨立使用的音義結(jié)合體,是能夠獨立運用并能夠表達語義或語用內(nèi)容的最基本單元。為了進行后續(xù)的自然語言處理,通常需要首先對不含分隔符的語言進行分詞操作。
中文分詞就是將一串連續(xù)的字符構(gòu)成的句子分割成詞語序列,最簡單的分詞算法叫作正向最大匹配分詞算法,即從前向后掃描句子中的字符串,盡量找到詞典中較長的單詞作為分詞的結(jié)果。
def fmm_word_seg(sentence, lexicon, max_len):"""sentence: 待分詞的句子lexicon: 詞典(所有單詞集合)max_len: 詞典中最長單詞長度"""begin = 0end = min(begin + max_len, len(sentence))words = []while begin < end:word = sentence[begin:end]if word in lexicon or end - begin == 1:words.append(word)begin = endend = min(begin + max_len, len(sentence))else:end -= 1return wordsdef load_dict():f = open("lexicon.txt") # 詞典文件,每行存儲一個單詞lexicon = set()max_len = 0for line in f:word = line.strip()lexicon.add(word)if len(word) > max_len:max_len = len(word)f.close()return lexicon, max_lenlexicon, max_len = load_dict() words = fmm_word_seg(input('請輸入句子:'), lexicon, max_len)for word in words:print(word)2.子詞切分
詞形還原或詞干提取雖然在一定程度上解決了數(shù)據(jù)稀疏問題,但是需要人工撰寫大量的規(guī)則,這種基于規(guī)則的方法既不容易擴展到新的領(lǐng)域,也不容易擴展到新的語言上。因此,基于統(tǒng)計的無監(jiān)督子詞切分任務應運而生,并在現(xiàn)代的預訓練模型中使用。
所謂子詞切分,就是將一個單詞切分為若干連續(xù)的片段。目前子詞切分算法基本的原理都是使用盡量長且頻次高的子詞對單詞進行切分。常用的有字節(jié)對編碼算法(BPE)。
3.詞性標注
詞性是詞語在句子中扮演的語法角色,也被稱為詞類。詞性可為句法分析、語義理解等提供幫助。詞性標注任務是指給定一個句子,輸出句子中每個詞相應的詞性。
詞性標注的主要難點在于歧義性,即一個詞在不同的上下文可能有不同的詞性。
4.句法分析
句法分析的主要目標是給定一個句子,分析句子的句法成分信息。最終的目標是將詞序列表示的句子轉(zhuǎn)換成樹狀結(jié)構(gòu),從而有助于更準確地理解句子的含義,并輔助下游自然語言處理任務。
典型的句法結(jié)構(gòu)表示方法包含兩種——短語結(jié)構(gòu)句法表示和依存結(jié)構(gòu)句法表示。它們的不同點在于依托的文法規(guī)則不一樣。其中,短語結(jié)構(gòu)句法表示依托上下文無關(guān)文法,屬于一種層次性的表示方法,而依存結(jié)構(gòu)句法表示依托依存文法。
5.語義分析
自然語言處理的核心任務即是讓計算機“理解”自然語言所蘊含的意義,即語義。一般意義上的語義分析指的是通過離散的符號及結(jié)構(gòu)顯性地表示語義。根據(jù)待表示語言單元粒度以及語義表示方法的不同,語義分析又可以被分為多種形式。
根據(jù)詞出現(xiàn)的不同上下文,確定其具體含義的自然語言處理任務被稱為詞義消歧。
由于語言的語義組合性和進化性,無法像詞語一樣使用詞典定義句子、段落或篇章的語義,因此很難用統(tǒng)一的形式對句子等語言單元的語義進行表示。眾多的語言學流派提出了各自不同的語義表示形式,如語義角色標注、語義依存分析等。
語義角色標注也稱謂詞論元結(jié)構(gòu),即首先識別句子中可能的謂詞,然后為每個謂詞確定所攜帶的語義角色。
語義依存分析則利用通用圖表示更豐富的語義信息。根據(jù)圖中節(jié)點類型的不同,又可分為兩種表示——語義依存圖表示和概念語義圖表示。語義依存圖中的節(jié)點是句子中實際存在的詞語,在詞與詞之間創(chuàng)建語義關(guān)系邊,而概念語義圖首先將句子轉(zhuǎn)化為虛擬的概念節(jié)點,然后在概念節(jié)點之間創(chuàng)建語義關(guān)系邊。
2.2.3 自然語言處理應用任務
1.信息抽取
信息抽取是從非結(jié)構(gòu)化的文本中自動提取結(jié)構(gòu)化信息的過程,這種結(jié)構(gòu)化的信息方便計算機進行后續(xù)的處理。另外,抽取的結(jié)果還可以作為新的知識加入知識庫。
信息抽取一般包含一下幾個子任務:
命名實體識別是在文本中抽取每個提及的命名實體并標注其類型,一般包括人名、地名和機構(gòu)名等,也包括專有名稱等。在文本中找到提及的命名實體后,往往還需要將這些命名實體鏈接接到知識庫或知識圖譜中的具體實體,這一過程被稱作實體鏈接。
關(guān)系抽取用于識別和分類文本中提及的實體之間的語義關(guān)系。
事件抽取的任務是從文本中識別人們感興趣的事件以及事件所涉及的時間、地點和人物等關(guān)鍵元素。其中,事件往往使用文本中提及的具體觸發(fā)詞。
事件的發(fā)生時間往往比較關(guān)鍵,因此時間表達式識別也被認為是重要的信息抽取子任務,一般包括兩種類型的時間:絕對時間和相對時間。使用時間表達歸一化將這些時間表達式映射到特定的日期或一天中的時間。
2.情感分析
情感是人類重要的心理認知能力,使用計算機自動感知和處理人類情感已經(jīng)成為人工智能領(lǐng)域重要的研究內(nèi)容之一。自然語言處理中的情感分析主要研究人類通過文字表達的情感,因此也稱為文本情感分析。
情感分析可以從任務角度分為兩個主要的子任務,即情感分類和情感信息抽取。
3.問答系統(tǒng)
問答系統(tǒng)是指系統(tǒng)接受用戶以自然語言形式描述的問題,并從異構(gòu)數(shù)據(jù)中通過檢索、匹配和推理等技術(shù)獲得答案的自然語言處理系統(tǒng)。根據(jù)數(shù)據(jù)來源的不同,問答系統(tǒng)可以分為4種主要的類型:1)檢索式問答系統(tǒng);2)知識庫問答系統(tǒng);3)常問問題集問答系統(tǒng);4)閱讀理解式問答系統(tǒng)。
4.機器翻譯
機器翻譯是指利用計算機實現(xiàn)從一種自然語言(源語言)到另外一種自然語言(目標語言)的自動翻譯。機器翻譯的目標是建立自動翻譯方法、模型和系統(tǒng),打破語言壁壘,最終實現(xiàn)任意時間、任意地點和任意語言之間的自動翻譯,完成人們無障礙自由交流的夢想。
機器翻譯方法一般以句子為基本輸入單位,研究從源語言句子到目標語言句子的映射函數(shù)。
5.對話系統(tǒng)
對話系統(tǒng)是指以自然語言為載體,用戶與計算機通過多輪交互的方式實現(xiàn)特定目標的智能系統(tǒng)。對話系統(tǒng)主要分為任務型對話系統(tǒng)和開放域?qū)υ捪到y(tǒng)。
任務型對話系統(tǒng)一般由順序執(zhí)行的三個模塊構(gòu)成,即自然語言理解、對話管理和自然語言生成。
其中,自然語言理解模塊的主要功能是分析用戶話語的語義,通常的表示形式為該話語的領(lǐng)域、意圖以及相應的槽值等。
對話管理模塊包括對話狀態(tài)跟蹤和對話策略優(yōu)化兩個子模塊。對話狀態(tài)一般表示為語義槽和值的列表。
在任務型對話系統(tǒng)里,自然語言生成模塊工作相對比較簡單,通常通過寫模板即可實現(xiàn)。
2.3 基本問題
2.3.1 文本分類問題
文本分類是最簡單也最基礎(chǔ)的自然語言處理問題,即針對一段文本輸入,輸出該文本所屬的類別。其中,類別是事先定義好的一個封閉的集合。
文本匹配是判斷兩段輸入文本之間的匹配關(guān)系,包括復述關(guān)系、蘊含關(guān)系等。
2.3.2 結(jié)構(gòu)預測問題
1.序列標注
所謂序列標注,指的是為輸入文本序列中的每個詞標注相應的標簽。條件隨機場是一種被廣泛應用的序列標注模型,其不但考慮了每個詞屬于某一標簽的概率,還考慮了標簽之間的相互關(guān)系。
2.序列分割
序列分割問題,就是將字符序列切分成若干連續(xù)的子序列;命名實體識別問題,也是在文本序列中切分出子序列,并為每個子序列賦予一個實體的類別。
3.圖結(jié)構(gòu)生成
圖結(jié)構(gòu)生成輸入是自然語言,輸出結(jié)果是一個以圖表示的結(jié)構(gòu)。圖中的節(jié)點既可以來自原始輸入,也可以是新生成的;邊連接了兩個節(jié)點,并可以賦予相應的類型。
圖結(jié)構(gòu)生成算法主要包括兩大類:基于圖的算法和基于轉(zhuǎn)移的算法。
基于圖的算法首先為圖中任意兩個節(jié)點構(gòu)成的邊賦予一定的分數(shù),算法的目標是求解出一個滿足約束的分數(shù)最大的子圖。
基于轉(zhuǎn)移的算法將圖結(jié)構(gòu)的構(gòu)建過程轉(zhuǎn)化為一個狀態(tài)轉(zhuǎn)移序列。
2.3.3 序列到序列問題
序列到序列問題,輸入是一個由若干詞組成的序列,輸出則是一個新的序列,其中,輸入和輸出的序列不要求等長,同時也不要求詞表一致。
由于序列到序列模型具備強大的建模能力,其已成為自然語言處理的大一統(tǒng)框架,越來越多的問題都可以嘗試使用該模型加以解決。也就是說,可以將復雜的自然語言處理問題轉(zhuǎn)化為編碼、解碼兩個子問題,然后就可以分別使用獨立的模型建模了。
2.4 評價指標
由于自然語言處理任務的多樣性以及評價的主觀性,因此很難使用單一的評價指標衡量所有任務的性能,所以針對不同類型的任務,往往采用不同的評價方法。
準確率是最簡單、直觀的評價指標,經(jīng)常被應用于文本分類等問題。
F值是精確率和召回率的加權(quán)調(diào)和平均,具體公式為:
對人機對話系統(tǒng)的評價,雖然也可以利用歷史上人人對話數(shù)據(jù),采用BLEU值等指標,但是由于回復的開放性,這種自動評價的結(jié)果很難保證公正、客觀。
人工評價的代價往往非常高,很難在系統(tǒng)開發(fā)的過程中多次進行。
人機對話系統(tǒng)的評價方法仍是目前自然語言處理領(lǐng)域一個非常棘手的開放性問題,并沒有很好地被解決。
?
總結(jié)
以上是生活随笔為你收集整理的《自然语言处理:基于预训练模型的方法》读书笔记:第2章 自然语言处理基础的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态代理 ---- 框架基础技术
- 下一篇: Arduino基础入门篇30—数字温度传