機器學習之k-means聚類算法(python實現)

上次簡單介紹了kNN算法,簡單來講,經過計算目標值與樣本數據的距離,選取k個最近的值,用出現機率大的分類值表明目標值的分類,算法實現比較簡單,屬於監督學習方法。 這篇文章打算簡單介紹k-means聚類算法,與以前不一樣,是一種非監督的學習方法。 機器學習中兩類大問題,分類和聚類。 分類是根據一些給定的已知類別標號的樣本,訓練某種學習機器,使它可以對未知類別的樣本進行分類。這屬於supervised learning(監督學習)。而聚類指事先並不知道任何樣本的類別標號,但願經過某種算法來把一組未知類別的樣本劃分紅若干類別,這在機器學習中被稱做 unsupervised learning (無監督學習)。python

k-means 聚類算法

一般,根據樣本間的某種距離或者類似性來將樣本分爲不一樣類別,成爲聚類。 好比給定數據集,部分數據(二維, 共80個)以下:git

1.658985    4.285136
-3.453687   3.424321
4.838138    -1.151539
-5.379713   -3.362104
0.972564    2.924086
複製代碼

其可視化以下: github

image.png
從分佈狀態,能夠大概知道能夠聚爲4個cluster。最後目的是將4個不一樣的cluster標上不一樣的顏色。 利用k-means算法以下實現:

  1. 隨機選取k個點做爲初始質心。
  2. 對於樣本中每個點,分別求與k點的距離。距離最小者就屬於該類。
  3. 此時對獲得的k各種,從新計算新的質心。
  4. 當3步獲得的質心與以前的質心偏差很小時,分類結束。 其中用到的公式都特別簡單,後面代碼有詳細敘述。

python 代碼實現

# 數據初始化
import numpy as np
import random
import re
import matplotlib.pyplot as plt

def loadDataSet():
    dataSet = np.loadtxt("dataSet.csv")
    return dataSet
複製代碼

def initCentroids(dataSet, k):
    # 從數據集中隨機選取k個數據返回
    dataSet = list(dataSet)
    return random.sample(dataSet, k)
複製代碼

對應第2步,計算距離並分類,根據到不一樣質心的最短距離分類,用字典保存。算法

def minDistance(dataSet, centroidList):

    # 對每一個屬於dataSet的item, 計算item與centroidList中k個質心的距離,找出距離最小的,並將item加入相應的簇類中
    clusterDict = dict() #dict保存簇類結果
    k = len(centroidList)
    for item in dataSet:
        vec1 = item
        flag = -1
        minDis = float("inf") # 初始化爲最大值
        for i in range(k):
            vec2 = centroidList[i]
            distance = calcuDistance(vec1, vec2)  # error
            if distance < minDis:
                minDis = distance
                flag = i  # 循環結束時, flag保存與當前item最近的蔟標記
        if flag not in clusterDict.keys():
            clusterDict.setdefault(flag, [])
        clusterDict[flag].append(item)  #加入相應的類別中
    return clusterDict  #不一樣的類別
複製代碼

def getCentroids(clusterDict):
    #從新計算k個質心
    centroidList = []
    for key in clusterDict.keys():
        centroid = np.mean(clusterDict[key], axis=0)
        centroidList.append(centroid)
    return centroidList  #獲得新的質心
複製代碼

計算計算各蔟集合間的均方偏差,來衡量聚類的效果bash

def getVar(centroidList, clusterDict):
    # 計算各蔟集合間的均方偏差
    # 將蔟類中各個向量與質心的距離累加求和
    sum = 0.0
    for key in clusterDict.keys():
        vec1 = centroidList[key]
        distance = 0.0
        for item in clusterDict[key]:
            vec2 = item
            distance += calcuDistance(vec1, vec2)
        sum += distance
    return sum
複製代碼

#測試聚類效果,並可視化
def test_k_means():
    dataSet = loadDataSet()
    centroidList = initCentroids(dataSet, 4)
    clusterDict = minDistance(dataSet, centroidList)
    # # getCentroids(clusterDict)
    # showCluster(centroidList, clusterDict)
    newVar = getVar(centroidList, clusterDict)
    oldVar = 1  # 當兩次聚類的偏差小於某個值是,說明質心基本肯定。

    times = 2
    while abs(newVar - oldVar) >= 0.00001:
        centroidList = getCentroids(clusterDict)
        clusterDict = minDistance(dataSet, centroidList)
        oldVar = newVar
        newVar = getVar(centroidList, clusterDict)
        times += 1
        showCluster(centroidList, clusterDict)

if __name__ == '__main__':
    # show_fig()
    test_k_means()
複製代碼

如上如,當兩次計算質心之間的偏差在0.00001以內時,能夠認爲聚類完成。 運行函數: app

image.png
image.png
image.png
image.png

從結果能夠看出,對着不斷的迭代,聚類的效果愈來愈好,直至小於偏差,完成聚類。dom

完成代碼和數據請參考github:
github:k-means機器學習

總結

  • 無監督學習
  • k-means算法
  • 最小化平方差刻畫蔟內向量的緊密程度。

參考資料:(內有公式介紹)
聚類之均值聚類(k-means)算法的python實現
機器學習算法與Python實踐之(五)k均值聚類(k-means)函數

相關文章
相關標籤/搜索