機器學習—K-均值聚類(K-means)算法

1 K-均值聚類(K-means)概述

1.1 聚類

“類”指的是具有相似性的集合。聚類是指將數據集劃分為若干類,使得類內之間的數據最為相似,各類之間的數據相似度差別盡可能大。聚類分析就是以相似性為基礎,對數據集進行聚類劃分,屬于無監督學習

1.2 無監督學習和監督學習

和KNN所不同,K-均值聚類屬于無監督學習。那么監督學習和無監督學習的區別在哪兒呢?監督學習知道從對象(數據)中學習什么,而無監督學習無需知道所要搜尋的目標,它是根據算法得到數據的共同特征。比如用分類和聚類來說,分類事先就知道所要得到的類別,而聚類則不一樣,只是以相似度為基礎,將對象分得不同的簇。

1.3 K-means

K-means算法具有悠久的歷史,并且也是最常用的聚類算法之一。K-means算法實施起來非常簡單,因此,它非常適用于機器學習新手愛好者。
1967年,James MacQueen在他的論文《用于多變量觀測分類和分析的一些方法》中首次提出 “K-means”這一術語。1957年,貝爾實驗室也將標準算法用于脈沖編碼調制技術。1965年,E.W. Forgy發表了本質上相同的算法——Lloyd-Forgy算法。

k-means算法是一種簡單的迭代型聚類算法,采用距離作為相似性指標,從而發現給定數據集中的K個類,且每個類的中心是根據類中所有值的均值得到,每個類用聚類中心來描述。對于給定的一個包含n個d維數據點的數據集X以及要分得的類別K,選取歐式距離作為相似度指標,聚類目標是使得各類的聚類平方和最小,即最小化:


結合最小二乘法和拉格朗日原理,聚類中心為對應類別中各數據點的平均值,同時為了使得算法收斂,在迭代過程中,應使最終的聚類中心盡可能的不變。

1.4 K-Means算法的十大用例

K-means算法通常可以應用于維數、數值都很小且連續的數據集,比如:從隨機分布的事物集合中將相同事物進行分組

  • 1.文檔分類器
    根據標簽、主題和文檔內容將文檔分為多個不同的類別。這是一個非常標準且經典的K-means算法分類問題。首先,需要對文檔進行初始化處理,將每個文檔都用矢量來表示,并使用術語頻率來識別常用術語進行文檔分類,這一步很有必要。然后對文檔向量進行聚類,識別文檔組中的相似性。 這里是用于文檔分類的K-means算法實現案例。

  • 2.物品傳輸優化
    使用K-means算法的組合找到無人機最佳發射位置和遺傳算法來解決旅行商的行車路線問題,優化無人機物品傳輸過程。

  • 3.識別犯罪地點
    使用城市中特定地區的相關犯罪數據,分析犯罪類別、犯罪地點以及兩者之間的關聯,可以對城市或區域中容易犯罪的地區做高質量的勘察。這是基于德里飛行情報區犯罪數據的論文。

  • 4.客戶分類
    聚類能過幫助營銷人員改善他們的客戶群(在其目標區域內工作),并根據客戶的購買歷史、興趣或活動監控來對客戶類別做進一步細分。這是關于電信運營商如何將預付費客戶分為充值模式、發送短信和瀏覽網站幾個類別的白皮書。對客戶進行分類有助于公司針對特定客戶群制定特定的廣告。

  • 5.球隊狀態分析
    分析球員的狀態一直都是體育界的一個關鍵要素。隨著競爭越來愈激烈,機器學習在這個領域也扮演著至關重要的角色。如果你想創建一個優秀的隊伍并且喜歡根據球員狀態來識別類似的球員,那么K-means算法是一個很好的選擇。

  • 6.保險欺詐檢測
    機器學習在欺詐檢測中也扮演著一個至關重要的角色,在汽車、醫療保險和保險欺詐檢測領域中廣泛應用。利用以往欺詐性索賠的歷史數據,根據它和欺詐性模式聚類的相似性來識別新的索賠。由于保險欺詐可能會對公司造成數百萬美元的損失,因此欺詐檢測對公司來說至關重要。這是汽車保險中使用聚類來檢測欺詐的白皮書。

  • 7.乘車數據分析
    面向大眾公開的Uber乘車信息的數據集,為我們提供了大量關于交通、運輸時間、高峰乘車地點等有價值的數據集。分析這些數據不僅對Uber大有好處,而且有助于我們對城市的交通模式進行深入的了解,來幫助我們做城市未來規劃。這是一篇使用單個樣本數據集來分析Uber數據過程的文章。

  • 8.網絡分析犯罪分子
    網絡分析是從個人和團體中收集數據來識別二者之間的重要關系的過程。網絡分析源自于犯罪檔案,該檔案提供了調查部門的信息,以對犯罪現場的罪犯進行分類。這是一篇在學術環境中,如何根據用戶數據偏好對網絡用戶進行 cyber-profile的論文。

  • 9.呼叫記錄詳細分析
    通話詳細記錄(CDR)是電信公司在對用戶的通話、短信和網絡活動信息的收集。將通話詳細記錄與客戶個人資料結合在一起,這能夠幫助電信公司對客戶需求做更多的預測。在這篇文章中,你將了解如何使用無監督K-Means聚類算法對客戶一天24小時的活動進行聚類,來了解客戶數小時內的使用情況。

  • 10.IT警報的自動化聚類
    大型企業IT基礎架構技術組件(如網絡,存儲或數據庫)會生成大量的警報消息。由于警報消息可以指向具體的操作,因此必須對警報信息進行手動篩選,確保后續過程的優先級。對數據進行聚類可以對警報類別和平均修復時間做深入了解,有助于對未來故障進行預測。

1.5 應用示例

想要將一組數據,分為三類,粉色數值大,黃色數值小。
最開心先初始化,這里面選了最簡單的 3,2,1 作為各類的初始值。
剩下的數據里,每個都與三個初始值計算距離,然后歸類到離它最近的初始值所在類別。



分好類后,計算每一類的平均值,作為新一輪的中心點。



幾輪之后,分組不再變化了,就可以停止了。

1.6 算法流程

K-means是一個反復迭代的過程,算法分為四個步驟:
1) 選取數據空間中的K個對象作為初始中心,每個對象代表一個聚類中心;
2) 對于樣本中的數據對象,根據它們與這些聚類中心的歐氏距離,按距離最近的準則將它們分到距離它們最近的聚類中心(最相似)所對應的類;
3) 更新聚類中心:將每個類別中所有對象所對應的均值作為該類別的聚類中心,計算目標函數的值;
4) 判斷聚類中心和目標函數的值是否發生改變,若不變,則輸出結果,若改變,則返回2)。

用以下例子加以說明:


圖1:給定一個數據集;
圖2:根據K = 5初始化聚類中心,保證 聚類中心處于數據空間內;
圖3:根據計算類內對象和聚類中心之間的相似度指標,將數據進行劃分;
圖4:將類內之間數據的均值作為聚類中心,更新聚類中心。
最后判斷算法結束與否即可,目的是為了保證算法的收斂。

2 Python實現

2.1 計算過程

st=>start: 開始
e=>end: 結束
op1=>operation: 讀入數據
op2=>operation: 隨機初始化聚類中心
cond=>condition: 是否聚類是否變化
op3=>operation: 尋找最近的點加入聚類
op4=>operation: 更新聚類中心
op5=>operation: 輸出結果

st->op1->op2->op3->op4->cond
cond(yes)->op3
cond(no)->op5->e

2.2 輸入樣例

15.55,28.65
14.9,27.55
14.45,28.35
14.15,28.8
13.75,28.05
13.35,28.45
13,29.15
13.45,27.5
13.6,26.5
12.8,27.35

2.3 代碼實現

__author__ = 'Bobby'

from numpy import *
import matplotlib.pyplot as plt
import time

INF = 9999999.0

def loadDataSet(fileName, splitChar='\t'):
    """
    輸入:文件名
    輸出:數據集
    描述:從文件讀入數據集
    """
    dataSet = []
    with open(fileName) as fr:
        for line in fr.readlines():
            curline = line.strip().split(splitChar)
            fltline = list(map(float, curline))
            dataSet.append(fltline)
    return dataSet

def createDataSet():
    """
    輸出:數據集
    描述:生成數據集
    """
    dataSet = [[0.0, 2.0],
               [0.0, 0.0],
               [1.5, 0.0],
               [5.0, 0.0],
               [5.0, 2.0]]
    return dataSet

def distEclud(vecA, vecB):
    """
    輸入:向量A, 向量B
    輸出:兩個向量的歐式距離
    """
    return sqrt(sum(power(vecA - vecB, 2)))

def randCent(dataSet, k):
    """
    輸入:數據集, 聚類個數
    輸出:k個隨機質心的矩陣
    """
    n = shape(dataSet)[1]
    centroids = mat(zeros((k, n)))
    for j in range(n):
        minJ = min(dataSet[:, j])
        rangeJ = float(max(dataSet[:, j]) - minJ)
        centroids[:, j] = minJ + rangeJ * random.rand(k, 1)
    return centroids

def kMeans(dataSet, k, distMeans=distEclud, createCent=randCent):
    """
    輸入:數據集, 聚類個數, 距離計算函數, 生成隨機質心函數
    輸出:質心矩陣, 簇分配和距離矩陣
    """
    m = shape(dataSet)[0]
    clusterAssment = mat(zeros((m, 2)))
    centroids = createCent(dataSet, k)
    clusterChanged = True
    while clusterChanged:
        clusterChanged = False
        for i in range(m): # 尋找最近的質心
            minDist = INF
            minIndex = -1
            for j in range(k):
                distJI = distMeans(centroids[j, :], dataSet[i, :])
                if distJI < minDist:
                    minDist = distJI
                    minIndex = j
            if clusterAssment[i, 0] != minIndex:
                clusterChanged = True
            clusterAssment[i, :] = minIndex, minDist**2
        for cent in range(k): # 更新質心的位置
            ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]
            centroids[cent, :] = mean(ptsInClust, axis=0)
    return centroids, clusterAssment

def plotFeature(dataSet, centroids, clusterAssment):
    m = shape(centroids)[0]
    fig = plt.figure()
    scatterMarkers = ['s', 'o', '^', '8', 'p', 'd', 'v', 'h', '>', '<']
    scatterColors = ['blue', 'green', 'yellow', 'purple', 'orange', 'black', 'brown']
    ax = fig.add_subplot(111)
    for i in range(m):
        ptsInCurCluster = dataSet[nonzero(clusterAssment[:, 0].A == i)[0], :]
        markerStyle = scatterMarkers[i % len(scatterMarkers)]
        colorSytle = scatterColors[i % len(scatterColors)]
        ax.scatter(ptsInCurCluster[:, 0].flatten().A[0], ptsInCurCluster[:, 1].flatten().A[0], marker=markerStyle, c=colorSytle, s=90)
    ax.scatter(centroids[:, 0].flatten().A[0], centroids[:, 1].flatten().A[0], marker='+', c='red', s=300)

def main():
    #dataSet = loadDataSet('testSet2.txt')
    dataSet = loadDataSet('788points.txt', splitChar=',')
    #dataSet = createDataSet()
    dataSet = mat(dataSet)
    resultCentroids, clustAssing = kMeans(dataSet, 6)
    print('*******************')
    print(resultCentroids)
    print('*******************')
    plotFeature(dataSet, resultCentroids, clustAssing)

if __name__ == '__main__':
    start = time.clock()
    main()
    end = time.clock()
    print('finish all in %s' % str(end - start))
    plt.show()

2.4 輸出樣例

*******************
[[32.69453125 22.13789062]
 [33.14278846  8.79375   ]
 [21.16041667 22.89895833]
 [ 9.25928144 22.98113772]
 [ 9.81847826  7.59311594]
 [19.0637931   7.06551724]]
*******************
finish all in 2.270720974
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380