K-Means聚類講解:算法和Sklearn實現(附代碼講解)

K-Means聚類是機器學習領域中最強大的聚類算法之一。他的原因比較簡單,但得出的結果也非常準確。聚類是理解數據集的非常重要的方式,因此在本文中,我們將討論什麼是聚類,為什麼需要聚類以及什麼是k-means聚類。

什麼是聚類

聚類是根據數據的屬性將數據分為兩個或更多組的任務,更確切地說,是基於數據中或多或少明顯的某些模式。目的是在數據中找到那些模式,以幫助我們確保在給定數據集中某個項目的情況下,我們能夠正確地將該項目放置在正確的組中,從而使其與該組中的其他項目相似,但與其他組中的項目不同。這意味著聚類實際上由兩部分組成:一個是識別組,另一個是儘可能地將每個項目放置在正確的組中。聚類算法的理想結果是,同一組中的兩個項目彼此相似,而不同組中的兩個項目則儘可能地不同。

K-Means聚類講解:算法和Sklearn實現(附代碼講解)

一個真實的例子就是客戶細分。作為一家銷售各種產品或服務的企業,很難為每個客戶找到理想的業務策略。但是我們可以嘗試將客戶分為幾個子組,瞭解這些客戶的共同點,並針對每個組調整我們的業務策略。而向客戶提出錯誤的業務策略可能意味著失去該客戶,因此,重要的一點是我們必須實現良好的市場集群。

什麼是無監督機器學習

無監督機器學習是一種機器學習算法,試圖在沒有任何先驗知識的情況下推斷數據中的模式。與之相反的是有監督的機器學習,這裡我們有一個訓練集,該算法將嘗試通過將輸入與預定義的輸出進行匹配來查找數據中的模式。

之所以這樣說,是因為將無監督機器學習任務聚類。在應用聚類算法時,儘管我們可以設置要標識的類別數量,但我們也不會先驗地知道類別。

類別將從分析數據的算法中得出。因此,我們可以將集群稱為探索性機器學習任務,因為我們只知道類別的數量,但不知道其屬性。然後,我們可以嘗試使用不同數量的類別,看看是否可以更好地對數據進行聚類。

然後,我們必須瞭解我們的集群,這實際上可能是最不同的任務。讓我們將示例與客戶細分一起重用。假設我們已經運行了聚類算法,並且將客戶分為三類。但是那些團體是什麼?為什麼算法會確定這些客戶屬於該組,而那些客戶屬於該組?這是需要我們非常豐富的經驗以及非常瞭解業務的人員的任務。他們將查看數據,嘗試分析每個類別中的一些項目並嘗試猜測一些條件。然後,將在找到有效模式後進行推斷。

當我們獲得新客戶時會發生什麼?我們必須將該客戶放入我們已經擁有的一個集群中,因此我們可以通過算法來運行有關該客戶的數據,該算法將使我們的客戶放入一個集群。另外,將來,在獲得大量新客戶之後,我們可能需要重建集群——也許新集群或舊集群會消失。

集群應用

有哪些常見的集群應用程序?

最常見的用例是我們已經討論過的用例:客戶/市場細分。公司一直在進行這些類型的分析,以便他們可以瞭解其客戶和市場,並量身定製其業務戰略,服務和產品,以更好地去適應需求。

另一個常見的用例是信息提取任務。在信息提取任務中,我們經常需要查找實體,單詞,文檔等之間的關係。現在,假設如果直覺發現,我們更有可能找到彼此之間更相似的項目之間的關係,那麼這麼做是可行的,因為對數據點進行聚類可以幫助我們找出在哪裡尋找關係。

另一個非常流行的用例是使用聚類進行圖像分割。圖像分割是查看圖像並嘗試識別該圖像中不同項目的任務。我們可以使用聚類分析圖像的像素並確定圖像中的哪個項目包含哪個像素。

K-均值聚類說明

K-Means聚類算法是一種迭代聚類算法,它試圖將數據點準確分配給我們預定義的K個聚類中的一個聚類。

與其他任何聚類算法一樣,它試圖使一個聚類中的項目儘可能相似,同時也使聚類之間彼此儘可能不同。通過確保群集中的數據點與該群集的質心之間的平方距離之和最小。群集的質心是群集中所有值的

平均值。也可以從本段獲得K-Means名稱的來源。

用更多的技術術語,我們嘗試使數據儘可能地同質化,而使集群儘可能不異質。該ķ號碼是我們試圖獲得集群的數量。我們可以和K一起玩直到對結果滿意為止。

K均值聚類算法

K-Means聚類算法只需幾個簡單步驟即可工作。

  1. 分配K個集群
  2. 隨機整理數據,並將每個數據點隨機分配給K個聚類之一,並分配初始隨機質心。
  3. 計算每個數據點和所有質心之間的平方和。
  4. 根據步驟3的計算,將每個數據點重新分配給最近的質心。
  5. 通過計算每個群集的平均值來重新分配質心
  6. 重複步驟3、4、5,直到我們不再需要更改集群中的任何內容

運行K-Means聚類算法所需的時間取決於數據集的大小,我們定義的K數和數據中的模式。

使用Scikit-Learn和Python的K-Means聚類實現

我們將使用Sckikit-Learn Python庫在較小的數據集上運行K-Means聚類算法。

K均值聚類算法的數據集

數據包含有關倫敦,巴黎和柏林的3種文字。我們將提取有關這3個城市的Wikipedia文章的摘要部分,並通過我們的聚類算法運行它們。

然後,我們將提供我們自己的3個新句子,並檢查它們是否正確分配給各個群體。如果發生這種情況,那麼我們將知道我們的聚類算法有效。

K-Means聚類實施

首先,讓我們安裝依賴項。

<code> 

pip3

install scikit-learn

pip3

install nltk

pip3

install wikipedia

/<code>

現在,讓我們定義一個小類,以幫助從Wikipedia頁面收集文本。我們會將文本存儲到本地的3個文件中,以便在每次運行算法時都不會再次下載文本。第一次使用該算法時,請立即使用class,第二次使用時,可以註釋第8-12行和取消註釋第13-15行。

<code>import wikipedia

class

TextFetcher

:

def

__init__

(

self

, title)

:

self

.title = title page = wikipedia.page(title) f = open(title +

".txt"

,

"w"

) f.write(page.summary) f.close()

self

.text = page.summary

def

getText

(

self

)

:

return

self

.text /<code>

現在,我們來構建數據集。我們將獲取有關每個城市的文字,並刪除停用詞 停用詞是我們通常在每個文本處理任務之前過濾掉的詞。它們是英語中非常常見的單詞,不會給文本帶來任何價值和意義。由於它們大多數都在各處使用,因此它們將阻止我們正確地對文本進行聚類。

<code>

from

text_fetcher

import

TextFetcher

from

nltk.corpus

import

stopwords

from

nltk.tokenize

import

word_tokenize

from

sklearn.feature_extraction.text

import

TfidfVectorizer

from

sklearn.cluster

import

KMeans

import

nltk

def

preprocessor

(text)

:

nltk.download(

'stopwords'

) tokens = word_tokenize(text)

return

(

" "

).join([word

for

word

in

tokens

if

word

not

in

stopwords.words()])

if

__name__ ==

"__main__"

: textFetcher = TextFetcher(

"London"

) text1 = preprocessor(textFetcher.getText()) textFetcher = TextFetcher(

"Paris"

) text2 = preprocessor(textFetcher.getText()) textFetcher = TextFetcher(

"Berlin"

) text3 = preprocessor(textFetcher.getText()) docs = [text1, text2, text3]/<code>

詞向量化技術

眾所周知,計算機在理解文本方面非常差,但是在處理數字方面卻表現得更好。因為我們的數據集是由單詞組成的,所以我們需要將單詞轉換為數字。

詞嵌入或詞向量化表示用於將詞分配給實數向量的技術的集合,機器學習可將這些詞用於某些目的,其中之一是文本聚類。

Scikit-Learn庫包含一些單詞向量器,但是對於本文,我們將選擇TfidfVectorizer。

<code>

tfidf_vectorizer

= TfidfVectorizer()

tfidf

= tfidf_vectorizer.fit_transform(docs)/<code>

現在是時候應用我們的K-Means聚類算法了。我們很幸運,Scikit-Learn很好地實現了K-Means算法,我們將使用它。因為我們知道我們要將文本分為3類(每個城市一個),所以我們將K值定義為3。

<code>

kmeans

=

KMeans(n_clusters

=

3

).fit(tfidf)

print(kmeans)

#輸出:[0

1

2

]

/<code>

簡而言之,這3個值就是我們的3個類。

為了測試它們,我們現在可以提供3個文本,我們可以肯定地知道它們應該在不同的群集中,並查看它們是否分配正確。我們必須確保不要忘記也將這三個文本向量化,以便我們的算法能夠理解它們。

<code>    

test

= [

"This is one is about London."

,

"London is a beautiful city"

,

"I love London"

] results = kmeans.predict(tfidf_vectorizer.transform(

test

))

print

(results)

test

= [

"This is one is about Paris."

,

"Paris is a beautiful city"

,

"I love Paris"

] results = kmeans.predict(tfidf_vectorizer.transform(

test

))

print

(results)

test

= [

"This is one is about Berlin."

,

"Berlin is a beautiful city"

,

"I love Berlin"

] results = kmeans.predict(tfidf_vectorizer.transform(

test

))

print

(results)

test

= [

"This is about London"

,

"This is about Paris"

,

"This is about Vienna"

] results = kmeans.predict(tfidf_vectorizer.transform(

test

))

print

(results) /<code>

假設會得到另一條我們什麼都不知道的文本。我們可以將該文本通過分類器,然後查看其適合的類別。而這是一個非常有效的文本分類器。


分享到:


相關文章: