機器學習:K-Means聚類算法

本文來自同步博客

前面幾篇文章介紹了回歸或分類的幾個算法般眉,它們的共同點是訓練數(shù)據(jù)包含了輸出結果,要求算法能夠通過訓練數(shù)據(jù)掌握規(guī)律甸赃,用于預測新輸入數(shù)據(jù)的輸出值柿汛。因此,回歸算法或分類算法被稱之為監(jiān)督學習(Supervised Learning)埠对。

本篇文章將接觸有別于監(jiān)督學習的另一類機器學習算法——無監(jiān)督學習(Unsupervised Learning)苛茂。無監(jiān)督學習是尋找缺乏標準答案的輸入數(shù)據(jù)的規(guī)律。其中聚類算法是無監(jiān)督學習主要的分支鸠窗。今天介紹的K-Means算法就是聚類算法的其中一種比較常見的算法妓羊。

K-Means算法原理

K-Means算法的K指的是輸出類別的數(shù)目。該算法是一個迭代過程稍计,每一次迭代分為兩個步驟躁绸,第一步為分類成簇,第二步為移動簇中心净刮,直到簇中心不變。

分類成簇的判定方法是將與簇中心的歐幾里得距離最小的數(shù)據(jù)點歸為對應的一類硅则。而簇中心的計算方式是該類所有數(shù)據(jù)點的平均值淹父,這就是均值‘Mean’一詞的由來。

下圖演示了K-Means算法每一次迭代數(shù)據(jù)點的分類情況:


迭代過程圖

可以從上圖看到怎虫,K-Means經(jīng)過4次迭代就完成了聚類過程暑认。每次迭代,圓圈表示的數(shù)據(jù)點都被分類到離它最近的“x”表示的中心點大审,然后對中心點進行了更新蘸际。

K-Means算法實現(xiàn)

下面的代碼展示了K-Means算法的原理,上面的圖片也是通過這塊代碼生成的徒扶。依舊通過注釋方式講代碼,請看:

import numpy as np
import matplotlib.pyplot as plt

# Input data set
X = np.array([
    [-4, -3.5], [-3.5, -5], [-2.7, -4.5],
    [-2, -4.5], [-2.9, -2.9], [-0.4, -4.5],
    [-1.4, -2.5], [-1.6, -2], [-1.5, -1.3],
    [-0.5, -2.1], [-0.6, -1], [0, -1.6],
    [-2.8, -1], [-2.4, -0.6], [-3.5, 0],
    [-0.2, 4], [0.9, 1.8], [1, 2.2],
    [1.1, 2.8], [1.1, 3.4], [1, 4.5],
    [1.8, 0.3], [2.2, 1.3], [2.9, 0],
    [2.7, 1.2], [3, 3], [3.4, 2.8],
    [3, 5], [5.4, 1.2], [6.3, 2]
])


# K-Means
def k_means(data, k=2):
    if not isinstance(k, int) or k <= 0 or len(data) < k:
        return

    # Select first K points as centroids
    centroids = {0: data[0], 1: data[1]}

    # configurations
    limit = 0.0001
    max_loop_count = 300
    total_steps = []
    # Loop
    for i in range(max_loop_count):
        # Classification data into K groups
        groups = {}

        for j in range(k):
            groups[j] = []

        for item in data:
            dist = [np.linalg.norm(centroids[centroid] - item) for centroid in centroids]
            index = dist.index(min(dist))
            groups[index].append(item)

        # Calculate new centroids
        new_centroids = [np.average(groups[i], axis=0) for i in groups]
        # Store data for matplotlib
        total_steps.append({
            'loop': i,
            'groups': groups,
            'centroids': centroids.copy()
        })

        # Check whether they change or not
        stop_loop = True
        for c in centroids:
            if abs(np.sum((new_centroids[c] - centroids[c])/centroids[c]*100.0)) > limit:
                stop_loop = False
                break

        if stop_loop:
            break

        # Update centroids
        for c in centroids:
            centroids[c] = new_centroids[c]

    # Draw pictures
    colors = k*['g', 'r', 'b', 'c', 'm', 'y', 'k', 'w']
    fig = plt.figure()
    for step in total_steps:
        # This may cause error if len(total_steps) > 9
        ax = fig.add_subplot(1, len(total_steps), step['loop'] + 1)
        for g in step['groups']:
            for point in step['groups'][g]:
                ax.scatter(point[0], point[1], s=20, color=colors[g])
            ax.scatter(step['centroids'][g][0], step['centroids'][g][1], marker='x', s=30, color=colors[g])
    plt.show()


k_means(X)

代碼鏈接

scikit-learn中的KMeans

scikit-learn中的KMeans存在cluster模塊中,在官方有關KMeans的API文檔中可以看到导坟,數(shù)據(jù)處理結果存放在‘cluster_centers_’屿良、‘labels_’和‘ inertia_’中。下面用到了前兩者惫周,分別是聚類中心點和標簽尘惧。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

# Input data set
X = np.array([
    [-4, -3.5], [-3.5, -5], [-2.7, -4.5],
    [-2, -4.5], [-2.9, -2.9], [-0.4, -4.5],
    [-1.4, -2.5], [-1.6, -2], [-1.5, -1.3],
    [-0.5, -2.1], [-0.6, -1], [0, -1.6],
    [-2.8, -1], [-2.4, -0.6], [-3.5, 0],
    [-0.2, 4], [0.9, 1.8], [1, 2.2],
    [1.1, 2.8], [1.1, 3.4], [1, 4.5],
    [1.8, 0.3], [2.2, 1.3], [2.9, 0],
    [2.7, 1.2], [3, 3], [3.4, 2.8],
    [3, 5], [5.4, 1.2], [6.3, 2]
])

clf = KMeans(n_clusters=2)
clf.fit(X)
centroids = clf.cluster_centers_
labels = clf.labels_

colors = ['r', 'g']
for i in range(len(X)):
    plt.scatter(X[i][0], X[i][1], color=colors[labels[i]], s=20)
plt.scatter(centroids[:, 0], centroids[:, 1], marker='x', s=30)
plt.show()

代碼鏈接

執(zhí)行結果如下:


sklearn的KMeans執(zhí)行結果
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闯两,隨后出現(xiàn)的幾起案子褥伴,更是在濱河造成了極大的恐慌谅将,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饥臂,死亡現(xiàn)場離奇詭異逊躁,居然都是意外死亡,警方通過查閱死者的電腦和手機隅熙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門稽煤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人囚戚,你說我怎么就攤上這事酵熙。” “怎么了驰坊?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵匾二,是天一觀的道長拳芙。 經(jīng)常有香客問我察藐,道長,這世上最難降的妖魔是什么舟扎? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任分飞,我火速辦了婚禮,結果婚禮上譬猫,老公的妹妹穿的比我還像新娘。我一直安慰自己羡疗,他們只是感情好删窒,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著顺囊,像睡著了一般肌索。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天诚亚,我揣著相機與錄音晕换,去河邊找鬼。 笑死站宗,一個胖子當著我的面吹牛闸准,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播夷家,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼敏释!你這毒婦竟也來了库快?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钥顽,失蹤者是張志新(化名)和其女友劉穎义屏,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜂大,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡闽铐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了奶浦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兄墅。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡澳叉,死狀恐怖隙咸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情耳高,我是刑警寧澤扎瓶,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站概荷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碌燕。R本人自食惡果不足惜误证,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望修壕。 院中可真熱鬧愈捅,春花似錦、人聲如沸慈鸠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至譬巫,卻和暖如春咖楣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芦昔。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咕缎,地道東北人珠十。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像凭豪,于是被迫代替她去往敵國和親焙蹭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容