1. 程式人生 > >scikit-learn 為機器學習

scikit-learn 為機器學習

個數 toolbar tran 特殊 單向散列 分數 有效 row 數學

歡迎大家前往雲+社區,獲取更多騰訊海量技術實踐幹貨哦~

文本數據需要特殊處理,然後才能開始將其用於預測建模。

我們需要解析文本,以刪除被稱為標記化的單詞。然後,這些詞還需要被編碼為整型或浮點型,以用作機器學習算法的輸入,這一過程稱為特征提取(或矢量化)。

scikit-learn 庫提供易於使用的工具來對文本數據進行標記和特征提取。

在本教程中,您可以學到如何使用 scikit-learn 為 Python 中的預測建模準備文本數據。

完成本教程後,您可以學到:

  • 如何使用 CountVectorizer 將文本轉換為文字計數向量。
  • 如何使用 TfidfVectorizer 將文本轉換為詞頻向量。
  • 如何使用 HashingVectorizer 將文本轉換為唯一的整數。

讓我們開始吧。

技術分享圖片

詞袋模型( Bag-of-Words Model )

使用機器學習算法時,我們不能直接使用文本。

相反,我們需要將文本轉換為數字。

我們可能想對文檔進行分類,每一類文檔都是“輸入”,而類別標簽是我們預測算法的“輸出”。算法將數字向量作為輸入,因此我們需要將文檔轉換為固定長度的數字向量。

在機器學習中,Bag-of-Words 模型(BoW)是一種簡單而有效的讓計算機“理解”文本文檔的模型。

這個模型非常簡單,它移除了單詞的諸如詞序、語法等順序信息,只關註文檔中該單詞的出現情況。

上面這一步可以通過為每個單詞分配一個唯一的編碼來完成。我們所看到的任何文檔都可以被編碼為一個固定長度的矢量,其長度為文檔中全部已知單詞的詞匯量。矢量中每個位置的值可以用編碼文檔中每個單詞的出現個數或頻率填充。

在詞袋模型中,我們只關心編碼方案,而編碼方案描述了文檔中出現了什麽單詞,以及這些單詞在編碼文檔中出現的頻率,而沒有任何關於順序的信息。

有很多方法來擴展這個簡單的方法,例如,我們可以想辦法更好地解釋一個單詞的含義,或是更好地規定向量中每個單詞的編碼方式。

scikit-learn 庫提供了3種不同的方案供我們使用,下面簡要地介紹一下。

使用 CountVectorizer 計算字數

CountVectorizer 提供了一個簡單的方法,既可以標記文本文檔的集合, 也可以生成每個已知單詞的索引, 還可以使用這一套索引對新文檔進行編碼。

下面是一種使用方法:

  1. 實例化一個 CountVectorizer
    類。
  2. 調用 fit() 函數以從一個或多個文檔中建立索引。
  3. 根據需要在一個或多個文檔中調用 transform() 函數,將每個文檔編碼為一個向量。

最終會返回一個已編碼的向量, 其長度為索引的個數,該向量還攜帶有文檔中每個單詞出現的次數信息。

包含很多零的向量被稱為稀疏向量。Python 的 scipy.sparse 包中提供了一種處理稀疏向量的有效方法。

調用 transform() 返回的向量是稀疏向量,這裏可以通過調用 toarray() 函數將它們轉換回 numpy 數組以便查看並更好地理解這個過程。

下面是使用 CountVectorizer 標記,構建索引,然後編碼文檔的示例。

技術分享圖片
from sklearn.feature_extraction.text import CountVectorizer

# 下面是一個文本文檔的列表

text = ["The quick brown fox jumped over the lazy dog."]

# 實例化 CountVectorizer 類

vectorizer = CountVectorizer()

# 標記並建立索引

vectorizer.fit(text)

# 查看結果

print(vectorizer.vocabulary_)

# 編碼文檔

vector = vectorizer.transform(text)

# 查看編碼後的向量

print(vector.shape)

print(type(vector))

print(vector.toarray())
技術分享圖片

在上面的代碼中,如下一行是用來幫助我們訪問這個索引並查看標記的結果的:

print(vectorizer.vocabulary_)

我們可以看到,所有的單詞默認都是小寫字母,標點符號也被忽略了。標記的許多方面都是可以配置的,您可以查看API文檔中的所有選項。

運行示例之後,首先輸出的是索引,然後輸出的是編碼文檔的結構。我們可以看到索引中有8個詞,因此編碼向量長度為 8。

從接下來輸出的類型中可以看出,編碼向量是一個稀疏向量。而最後的輸出是編碼向量的數組版本,其表達的含義是,索引值為 7 的單詞出現次數為 2,其余單詞出現次數為 1。

技術分享圖片
{‘dog‘: 1, ‘fox‘: 2, ‘over‘: 5, ‘brown‘: 0, ‘quick‘: 6, ‘the‘: 7, ‘lazy‘: 4, ‘jumped‘: 3}

(1, 8)

<class ‘scipy.sparse.csr.csr_matrix‘>

[[1 1 1 1 1 1 1 2]]
技術分享圖片

重要的是,同一個矢量化器可以用在包含詞匯表中沒有包括的單詞的文檔上。不過,沒有包括的詞會被忽略,並且不會在結果向量中計數。

舉個例子,下面是使用上述向量化器對另一個文檔進行編碼的例子。這個文本文檔包含兩個詞,一個詞包含在索引中,另一個不包含在索引中。

將另一個文檔編碼

text2 = ["the puppy"]

vector = vectorizer.transform(text2)

print(vector.toarray())

運行這個例子,會輸出編碼的稀疏向量的數組版本,從這個輸出中可以看出,在詞匯中出現的單詞的沒有被忽略,而另一個不在詞匯中的單詞被忽略了。

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

這之後,編碼向量就可以直接使用到機器學習算法中了。

使用 TfidfVectorizer 統計詞頻

單詞計數是一個非常好、非常簡單的起點。

不過,簡單計數也存在不足。例如,簡單計數中像“ the ” 這樣的詞會出現很多次,在編碼的向量中,這樣的單詞計數會很大,卻沒有太大意義。

除了統計個數外的另一種方法是計算詞頻,到目前為止,最流行的方法是TF-IDF。TF-IDF 是 Term Frequency - Inverse Document Frequency 的首字母縮寫詞,它是分配給每個單詞的結果分數的組成部分。

  • 詞頻(Term Frequency):該值表示給定單詞在這份文檔中出現的頻率。
  • 逆向文件頻率(Inverse Document Frequency):該值用於降低其他文檔中普遍出現的單詞的最終評分。

沒有進入數學,TF-IDF是詞頻分數,可以突出個性化的單詞,例如在只在這份文檔中頻繁出現,但其他文檔中較少出現的單詞。

TfidfVectorizer 將標記文件、建立索引、求出逆文檔頻率權重,並允許您編碼新的文件。或者,如果您已經有了一個已經訓練過的 CountVectorizer,您可以將其與 TfidfTransformer 一起使用,以計算逆文檔頻率並開始編碼文檔。

TfidfVectorizer 的實例化、擬合和轉換方法和 CountVectorizer 類似。

下面的示例展示了如何是使用 TfidfVectorizer 訓練 3 個小文檔的索引和逆文檔頻率,並編碼其中一個文檔。

技術分享圖片
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(text0)

# 查看編碼後的向量

print(vector.shape)

print(vector.toarray())
技術分享圖片

從文檔中學習 8 個單詞的得到索引,並且每個單詞在輸出向量中被分配唯一的整數索引值。

計算每個單詞的逆文檔頻率,將最低分數 1.0 分配給最常見的詞:索引值為 7 的“the”

最後,第一個文檔被編碼為一個8元素的稀疏數組,我們可以從結果中的其他單詞中查看諸如“the”,“fox”和“dog”等不同值的最終評分。

技術分享圖片
{‘fox‘: 2, ‘lazy‘: 4, ‘dog‘: 1, ‘quick‘: 6, ‘the‘: 7, ‘over‘: 5, ‘brown‘: 0, ‘jumped‘: 3}

[ 1.69314718 1.28768207 1.28768207 1.69314718 1.69314718 1.69314718

1.69314718 1. ]

(1, 8)

[[ 0.36388646 0.27674503 0.27674503 0.36388646 0.36388646 0.36388646

0.36388646 0.42983441]]
技術分享圖片

將評分標準化為 0 到 1 之間的值。在這之後,編碼過的文檔向量即可直接用於大多數機器學習算法中了。

使用 HashingVectorizer 建立散列表

統計個數和計算頻率兩種方法雖然非常實用,但是也由其局限性導致詞匯量可能變得非常大。

詞匯量過大又將導致需要非常大的矢量來編碼文檔,從而對內存產生很大的要求,同時拖慢算法的速度。

這裏有一個巧妙的解決方法,即建立單詞的單向散列表,進而將每個單詞轉換為整數。這麽做的優點是不需要專門建立索引,並且你可以將定長向量的長度定為任意值。缺點是散列是一個單向函數,所以沒有辦法將編碼轉換回單詞(不過這一步對於許多監督學習任務可能並不重要)。

HashingVectorizer 類實現了此方法,使其可用於一致地散列單詞,然後根據需要標記和編碼文件。

下面的示例演示了用於編碼單個文檔的 HashingVectorizer。

選擇長度為 20 的定長向量。這個長度對應於散列函數的範圍,不過例如 20 這樣的小值可能導致散列表沖突。回想計算機科學課裏相關的知識,這裏可以使用試探法,根據估計的詞匯量的大小和碰撞概率來挑選哈希長度。

請註意,這個矢量化器不需要調用 fit() 函數來訓練數據文檔。實例化之後,它可以直接用於編碼文檔。

技術分享圖片
from sklearn.feature_extraction.text import HashingVectorizer

# 下面是一個文本文檔的列表

text = ["The quick brown fox jumped over the lazy dog."]

# 實例化 HashingVectorizer

vectorizer = HashingVectorizer(n_features=20)

# 編碼文檔

vector = vectorizer.transform(text)

# 查看編碼後的向量

print(vector.shape)

print(vector.toarray())
技術分享圖片

運行上述示例代碼,樣例文檔將被編碼為包含 20 個元素的稀疏數組。

編碼文檔的值默認將字數標準化到 -1 和 1 之間,這裏也可以通過更改默認配置使其進行簡單的整數計數。

技術分享圖片
(1, 20)

[[ 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.        ]]
技術分享圖片

進一步探究

如果您想進行深入研究,下面提供更多有關該主題的資源。

自然語言處理

  • 維基百科中的詞袋模型(Bag-of-Word Model)
  • Tokenization on Wikipedia
  • TF-IDF維基百科

sciki-learn

  • 4.2節 特征提取,scikit-learn用戶指南
  • sckit-learn特征提取API
  • 使用文本數據,scikit學習教程

API

  • CountVectorizer scikit-learn API
  • TfidfVectorizer scikit學習API
  • TfidfTransformer scikit-learn API
  • HashingVectorizer scikit學習API

概要

在本教程中,你可以了解如何使用scikit-learn為機器學習準備文本文檔。

這些例子只是抓住了表面,但是,這些類有很多配置細節影響著文檔的標記,這些都是值得深究的。

翻譯人:Bay,該成員來自雲+社區翻譯社

原文鏈接:https://machinelearningmastery.com/prepare-news-articles-text-summarization/

原文作者:Jason Brownlee

相關閱讀

Android圖像處理 - 高斯模糊的原理及實現

通過Pandas實現快速別致的數據分析

如何使用scikit-learn在Python中生成測試數據集

scikit-learn 為機器學習