1. 程式人生 > >NLP知識整理(上)

NLP知識整理(上)

by 翰林

資料預處理

資料清洗

  • 在拿到文字後需要使用re工具庫來利用正則表示式對文字進行一些資料預處理和資料清洗的操作,目的是去除髒資料,保證資料的規範性和一致性,便於後期處理。
  • 常見的操作有:
    ①統一計量單位,如將mg,g,kg,‘克’,‘千克’統一為kg,使不同單位之間的數字可以相互比較和計算。
    ②縮略詞替換,如將’can’t’轉換成’can not’。
    ③標點處理,去除掉’,/./。/!/…'等文字中的標點符號。
    ④去除空格,有時文字中會穿插一些空格,需要剔除。
    ⑤詞歸一化,針對英文文字,需要將不同時態的變種詞進行統一,如playing => play
    ⑥去除HTML標籤

分詞

  • 分詞就是對連續完整的語料文字進行詞粒度或者字粒度的切分,如將 [‘我愛自然語言處理’] 轉換為 [ ‘我’,‘愛’,‘自然’,‘語言’,‘處理’ ] 。其中中文分詞與英文分詞略有不同,原因在於英文句子中單詞之間是有空格的,而中文沒有,因此在中文分詞要比英文分詞更麻煩一些。

  • 常見的英文分詞工具有NLTK,常見的中文分詞工具有jieba,SnowNLP, nlpir。

  • 分詞有幾種以下幾種不同的模式:
    ①精確模式 ( 我/ 來到/ 北京/ 清華大學)
    ②搜尋模式 (我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學)
    ③新詞識別模式 (他/來到/了/網易/杭研/大廈)“杭研”並沒有在詞典中,但是也被Viterbi演算法識別出來了

  • 對於一些語料庫中沒有的新詞或者特殊詞,可以構建一個自定義詞表,新增到jieba中

去停用詞

  • 去停用詞是在分詞操作後去除一些提供資訊量較小同時出現頻率又比較高的詞彙(如:啊/哎/額/了/嗎/也/的…)。
  • 具體操作方式為提供一個stop words list

特徵抽取

CountVectorizer 詞袋模型

  • 為了將文字型詞彙表示為計算機可以理解的數字符號,我們需要進行一些特徵抽取工作,其中最為簡單的是詞袋模型,使用的工具是CountVectorizer。首先為模型提供語料料庫進行訓練(fit),CountVectorizer會將出現的每一個詞建立dictionary, 其中key是該單詞,value是該單詞在接下來向量化表示中所處的位置的index。然後我們為訓練好的詞袋模型提供新的文字資料,詞袋模型就根據該詞對應的value/index和該詞出現的頻次可以對文字進行向量化表示。
  • 如我們訓練好了一個dictionary{‘john’: 4, ‘likes’: 5, ‘ice’: 3, ‘cream’: 1, ‘hates’: 2, ‘chocolate’: 0}
    提供文字’John likes ice cream John
    則將其轉化為[0 1 0 1 2 1],注意因為John在文字中出現兩次,所以index為4的位置的值為2。
  • 詞袋模型值得注意的點有三個:
    ①詞袋模型嚴格意義上說並不是一種’模型’,更像是類似OneHotEncoder一樣的轉換工具,並不產出預測結果,只是對文字進行向量化表示。
    ②詞袋模型中出現的值並不是只產生0/1,而是該詞在該條文字中出現的頻次(注意是該條而不是所有)。
    ③詞袋模型在生成字典時,並沒有邏輯上的順序,但是在生成字典後,每個index就固定下來,只表示一個特定的詞。

N-Gram

  • 由於詞袋模型在生成字典時是無序的,因此’我愛你’和’你愛我’在詞袋模型進行向量化表示後的結果是一樣的,都是我、愛、你三個字對應位置的value置1,其他位置置0。為了避免這種不同語義的文字產生相同向量表示的情況發生,引入N-Gram將語序也作為一個因素考慮進特徵表示的過程中。
  • 以2-Gram為例,對’我愛你’的特徵抽取對應詞為[我,愛,你,我愛,愛你],而’你愛我’的特徵抽取對應詞為[你,愛,我,你愛,愛我],這樣就不會將兩個文字混淆了。

TF-IDF

  • TF-IDF分為TF(詞頻)和IDF(逆文件頻率)兩個部分,
  • TF詞頻統計的意義在於,在一篇文字中出現頻次越高的單詞越能表徵這篇文字的特點。
    如:我愛中文自然語言處理,因為自然語言處理很有趣。'自然語言處理’出現頻次較多的自然語言處理一定程度上更能代表該文字的含義。
  • IDF逆文件頻率的意義在於,在其他文字中出現頻率很低但在該文字中出現的詞,IDF認為該詞比較能表徵這篇文章的特點。
    如: 我愛中文自然語言處理,其中我、愛、自然語言處理都只出現了一次,但自然語言處理相對於中文、我、愛更屬於稀有詞,因此這篇文字的內容更可能是關於自然語言處理的而不是關於中文的。
  • CountVectorizer是將文字表示為[0,1,0,2,0]這樣形式,每個值是離散的,代表的是該詞出現的詞頻。
  • TfidfVectorizer是將文字表示為[0.213,1.982,3.456,4.768,9.231]這樣的形式,每個值是連續的,代表的是該詞計算出的權重。值越高,代表該詞在該文字中越重要
  • CountVectorizer和TfidfVectorizer為了節省儲存資源,將向量儲存成了特殊的形式,取出需要使用.toarray()操作,但要注意記憶體容量。
  • CountVectorizer和TfidfVectorizer本質上都是稀疏的儲存形式,因為語料庫訓練出來的每一個詞都在該向量中佔有一個位置,實際使用過程中,該向量會非常稀疏(有很多位置是0)。

TextRank

  • 常見的針對關鍵詞抽取的方式有兩種,一種是基於上文的TF-IDF給出權重最高的n個詞作為該文字的關鍵詞,另外一種就是基於TextRank的方式。
  • TextRank和搜尋引擎中使用的PageRank很像,區別在於PageRank是通過網頁和網頁之間連結的指向來構建圖,而TextRank是通過構建N-Gram滑窗,通過詞與詞之間的共現關係來構建圖,再通過指向分配權重,選取權重最大的n個詞作為文字的關鍵詞。

Tokenizer

  • 不論是CountVectorizer還是TfidfVectorizer,產出的都是稀疏矩陣,對於計算和儲存都帶來了很多的不便。若想用稠密向量來表示文字則可以使用Tokenizer。
  • Tokenizer直接使用對應的索引做為值來表示。如’I love you’如果使用CountVectorizer表示可能是[0,1,0,0,0,1,0,1],而使用Tokenizer則表示為[1,5,7],其中1,5,7分別為I、love、you三個詞在字典中對應的索引。
  • 但Tokenizer依然不能很好的解決一些問題:
    ① Tokenizer表徵後的向量維度和原文字詞彙數是相同的,但不同文字的詞彙數又是不同的,這會導致產出的特徵維度不一致。解決的方法是使用pad_sequence()來填充0補齊向量
    ② Tokenizer表徵後的向量依然不能很好的捕捉詞與詞之間的相關性,如男人/女人兩個詞的相關性和皇帝/女王兩個詞應該類似,為了解決這個問題我們可以使用下文提到的詞嵌入。

Word Embedding 詞嵌入

  • Word Embedding通過神經網路訓練出稠密向量來表示文字,能夠很好的捕捉詞與詞之間的相關性。
    可採用的方式有:
    ①Word2vec的特點是層次化softmax(構建哈夫曼樹將搜尋時間指數級別下降)和負例取樣(對詞頻加權的欠取樣操作),大幅縮短了訓練時間。
    ②Glove
    ③使用Gensim自定義訓練。
  • Word2vec是最為常見的一種詞嵌入模型,具體分為CBOW和Skip-Gram兩種方式,前者用周圍的詞來預測中心詞,後者用中心詞來預測周圍詞,這樣就將沒有標籤的文字資料轉化成為了有標籤的監督學習模式,具體操作方式為:
    ①下載並讀取預訓練好的Word2vec模型
    ②構建神經網路嵌入層,其中需要指定input_dim(詞典長度),output_dim(設定的詞向量表示維度),input_length(輸入資料長度)
    ③通過weight=word2vec_matrix將預訓練好的word2vec對嵌入層引數進行填充(預訓練的向量維度可能與我們設定的目標維度不一致,需要做填充或者截斷)
    ④將引數trainable設為True,訓練模型,得到微調後的引數矩陣。