天天看點

keras自然語言處理(六)第三章 如何使用scikit-learn準備文本資料

第三章 如何使用scikit-learn準備文本資料

在開始使用文本資料進行預測模組化之前,需要進行大量的預備工作。必須解析文本标記化,删除不必要的單詞,接着,這些單詞需要被編碼為整數或浮點值,以用于機器學習算法的輸入,這一過程稱之為特征提取(或矢量化)scikit-learn庫提供很多簡單易用的工具類,可以幫助你進行文本資料是的标記化和特征提取。在本教程中,你将了解如何使用scikit-learn在python中為預測模組化準備文本資料。接下來你将了解:

  1. 使用CountVectorizer将文本轉換為字數統計向量
  2. 使用TfidfVectorizer将文本轉換為字頻向量
  3. 使用HashingVectorizer将文本裝換為唯一的整數

3.1 詞袋模型

如果我們想對文檔進行分類 ,要進行的工作是對每個輸入的文檔,進行預測算法處理後能給出對應類别的标簽。因為機器學習算法是無法直接使用文本的,是以我們需要将文本轉化為數字,這樣就能輸入到機器學習中進行學習。這裡需要将文本轉化為數字,算法将轉換的數字向量作為輸入,這樣機器學習才能對文章類别進行預測,在轉化的過程中為了友善機器處理,可以考慮将文檔轉換為固定長度的數字向量。

在機器學習中處理文本文檔的簡單有效的模型成為bag-of-words模型,簡稱BOW。注意:我們将在下一章講解BOW模型,這個模型很簡單,它會抛棄單詞中的所有順序資訊,并關注文檔中單詞的出現次數。這可以通過為每個單詞配置設定唯一的編号來完成,然後我們可以看到任何文檔都可以編碼為具有已知單詞詞彙長度的固定長度向量,矢量中每個位置的值可以用編碼文檔中每個單詞的計數或頻率填充。

這是詞袋模型,我們隻關注編碼方案,這些編碼方案表示存在的單詞或他們在編碼文檔中存在的程度,而沒有關于順序的資訊,有許多方法可以擴充這個簡單方法:既可以更好地闡明單詞是什麼,也可以定義對向量中每個單詞進行編碼的内容,scikit-learn庫提供了我們可以使用的三種不同的方法,我接下來将作簡要介紹

3.2 Word計數和CountVectorizer

CountVectorizer提供了一種簡單的方法,既可以标記文本文檔的集合,也可以建構已知單詞的詞彙表,還可以使用該詞彙對新文檔進行編碼。你可以按照如下方式使用:

建立CountVectorizer類的執行個體

調用fit()函數以便從一個或多個文檔中學習詞彙表。

根據需要在一個或多個文檔上調用transform()函數,将每個文檔編碼為向量。

傳回的編碼向量表示文檔中每個單詞出現的次數的整數計數,向量的長度是整個詞彙表的長度,因為傳回的文本向量将包含很多零,是以我們稱它們為稀疏。python的scipy.sparse包中提供了處理稀疏向量的有效方法。調用transform()傳回稀疏向量,可以通過調用Numpy中的toarray()方法将稀疏向量轉換會數組,以調用函數來檢視并更好地了解正在發生的事情,下面是使用CountVectorizer進行标記,建構詞彙表,然後對文檔進行編碼。

from sklearn.feature_extraction.text import CountVectorizer
text = ['The quick brown fox junped over the lazy dog.']
vect =CountVectorizer()
vect.fit(text)
print(vect.vocabulary_)
vector = vect.transform(text)
print(vector)
print(vector.shape)
print(type(vector))
print(vector.toarray())
           

為了區分開來,我将print代碼放入其中:

print(vect.vocabulary_):
{'the': 7, 'quick': 6, 'brown': 0, 'fox': 2, 'junped': 3, 'over': 5, 'lazy': 4, 'dog': 1}
print(vector):
  (0, 0)	1
  (0, 1)	1
  (0, 2)	1
  (0, 3)	1
  (0, 4)	1
  (0, 5)	1
  (0, 6)	1
  (0, 7)	2
print(vector.shape):
(1, 8)
print(type(vector)):
<class 'scipy.sparse.csr.csr_matrix'>
print(vector.toarray()):
[[1 1 1 1 1 1 1 2]]

           

通過觀察結果可以知道:vect.vocabulary_可以檢視每個單詞将對應一個數字。上面所有的單詞都是小寫,并且都忽略了标點符号。可以配置對應的參數來決定忽略上面使用什麼,建議檢視API文檔中的所有選項。首先運作執行個體列印詞彙表,然後列印文檔向量的大小。詞彙中有8個單詞,是以編碼的向量長度為8,接着我們可以看到編碼的向量是稀疏矩陣,最後可以看到編碼向量的數組版本,顯示除了出現2的(index和id7)之外的每個單詞的1次出現次數。

最重要的是,相同的矢量化器可以用于包含詞彙表中未包含的單詞文檔。忽略這些單詞,并在結果向量中不給出記數。例如下面是使用上面的矢量化器來編碼文檔中的一個單詞和單詞不是單詞是執行個體:

text2 = ['the puppy']
vector_2 = vect.transform(text2)
print(vector_2.toarray())
           

運作示例列印編碼稀疏向量的數組版本,顯示詞彙中一個單詞出現一次,而詞彙表中沒有的另一個完全被忽略。

[[0 0 0 0 0 0 0 1]]
           

3.2使用TfidfVectorizer的單詞頻率

單詞計數是一個很好的起點,但非常基本,簡單計數的一個問題是:某些像will這樣的單詞會出現很多次,但他們在編碼向量中的意義不大。另一個方法是計算字頻率,到目前為止,最流行的方法稱為TF-IDF,這是一個縮寫,全稱是:Trem Frequency —Inverse Document Frequency,它表示的是每個單詞在文本中出現的分值。

Trem Frequency:給定單詞在文檔中出現的頻率

Inverse Document Frequency:這個縮小了文檔中出現的很多單詞

不用去考慮數字的含義及計算方法,TF-IDF是文檔中單詞評率分數,試圖突出文本中更重要的單詞,我們通常在文檔中計算單詞的頻率是不跨文檔,很難一下子确認具體一篇文獻中哪些詞語是關鍵詞,利用TF-IDF就可以快速的确認文本中的關鍵詞,TfidfVectorizer對庫中文檔分詞、學習詞彙和反向每個詞的文檔頻率權重,用學習後的結果,來處理新加入的文本,如果你學會了CountVectorizer,則可以與TfidfVectorizer一起使用,以計算逆文檔頻率并處理新文檔,與CountVectorizer一樣使用相同的建立,拟合和轉換過程。下面是使用TfidfVectorizer學習三個小文檔中的詞彙和逆文旦頻率然後編碼其中一個文檔。

from sklearn.feature_extraction.text import TfidfVectorizer
text = ['The quick brown fox jumped over the lazy dog.','The dog','The fox']
vectorizer = TfidfVectorizer()
vectorizer.fit(text)
print(vectorizer.vocabulary_)
print(vectorizer.idf_)
vector = vectorizer.transform([text[0]])
print(vector)
print(vector.shape)
print(vector.toarray())
           

為了區分開來,我将print代碼放入其中:

print(vectorizer.vocabulary_):
{'the': 7, 'quick': 6, 'brown': 0, 'fox': 2, 'jumped': 3, 'over': 5, 'lazy': 4, 'dog': 1}
print(vectorizer.idf_):
[1.69314718 1.28768207 1.28768207 1.69314718 1.69314718 1.69314718
 1.69314718 1.        ]
 print(vector):
  (0, 7)	0.4298344050159891
  (0, 6)	0.3638864554802418
  (0, 5)	0.3638864554802418
  (0, 4)	0.3638864554802418
  (0, 3)	0.3638864554802418
  (0, 2)	0.27674502873103346
  (0, 1)	0.27674502873103346
  (0, 0)	0.3638864554802418
print(vector.shape):(1, 8)
print(vector.toarray()):
[[0.36388646 0.27674503 0.27674503 0.36388646 0.36388646 0.36388646
  0.36388646 0.42983441]]

           

從文檔中學習了8個單詞的詞彙表,并且輸出向量中為每個單詞配置設定唯一的整數索引。計算詞彙表中每個單詞的逆文檔頻率,将最低分數1.0配置設定給最常觀察的單詞:索引7.最後,将第一個文檔編碼為8個單元的稀疏數組,我們可以檢視每個單詞的最終評分,其中包含詞彙表中其他單詞的不同值,fox和dog。

然後将得分歸一為0和1之間,然後将編碼的文檔向量直接用于大多數機器學習。

3.4 使用HashingVectorizer處理文本

計數和頻率可能非常有用,但是這些方法的一個限制就是詞彙量會變得非常大,反過來,這将需要大的向量來編碼文檔,對記憶體的需求非常大,并可能降低算法的速度。一個比較好的方法是使用單向哈希值将他們轉換為整數。這個方法的好處是不需要詞彙表,你可以選擇固定長度矢量的任意長度的句子,這個方法的缺點是哈希函數是一個單向的,沒有辦法将編碼轉換回一個單詞(這個缺點可能對許多監督學習無關緊要。)

HashingVectorizer類實作了這個方法,可以用于一緻地散列單詞,然後根據需要對文檔進行token和編碼。下面的示例示範了HashingVectorizer處理單文檔的過程。選擇矢量長度為20,這對應于散列函數的範圍,其中最小值可能導緻哈希沖突。請注意,此向量化程式不需要調用fit訓練資料文檔。相反執行個體化之後,它可以直接用于編碼文檔

from sklearn.feature_extraction.text import HashingVectorizer
text = ['The quick brown fox jumped over the lazy dog.']
vectorizer = HashingVectorizer(n_features=20)
vector = vectorizer.transform(text)
print(vector)
print(vector.shape)
print(vector.toarray())
           

為了區分開來,我将print代碼放入其中:

print(vector):
  (0, 5)	0.3333333333333333
  (0, 7)	-0.3333333333333333
  (0, 8)	0.3333333333333333
  (0, 11)	0.3333333333333333
  (0, 13)	0.0
  (0, 15)	-0.3333333333333333
  (0, 18)	-0.6666666666666666
print(vector.shape):(1, 20)
print(vector.toarray()):
[[ 0.          0.          0.          0.          0.          0.33333333
   0.         -0.33333333  0.33333333  0.          0.          0.33333333
   0.          0.          0.         -0.33333333  0.          0.
  -0.66666667  0.        ]]
           

以上是三個工具的介紹。

繼續閱讀