Kmeans-機器學習入門

1、K-均值聚類算法

  K-均值聚類的目的是將各個樣本點映射到距離某個質心最近的聚類中。假設樣本點爲$\textbf{x}^{t},t=1,2,3,...,n$,第$i$個聚類的質心爲$\textbf{m}_{i},i=1,2,...,k$。則,$\textbf{x}^{t}$屬於聚類$i$能夠表示爲:app

$||\textbf{x}^{t}-\textbf{m}_{i}||==min_{j}||\textbf{x}^{t}-\textbf{m}_{j}||$dom

  其中,將$\textbf{x}^{t}$劃分爲聚類$i$的偏差表示爲:$||\textbf{x}^{t}-\textbf{m}_{i}||^{2}$。全體樣本的總偏差表示爲:ide

$E=\sum_{t}\sum_{i}b_{i}^{t}||\textbf{x}^{t}-\textbf{m}_{i}||^{2}$spa

其中,若是$||\textbf{x}^{t}-\textbf{m}_{i}||==min_{j}||\textbf{x}^{t}-\textbf{m}_{j}||$,$b_{i}^{t}=1$,不然,$b_{i}^{t}=0$。3d

  選擇的質心必須可以最小化總偏差。可是因爲$b_{i}^{t}$的取值依賴於$\textbf{m}_{i}$,反過來$\textbf{m}_{i}$又依賴與$\textbf{m}_{i}$,這樣使得最小化問題沒法直接求解。對此,Kmeans的解法是首先肯定$\textbf{m}_{i}$的值,而後依據$\textbf{m}_{i}$的值去肯定每一個樣本點的$\textbf{m}_{i}$,有了$\textbf{m}_{i}$,在總偏差的公式中$\textbf{m}_{i}$爲已知項,只存在一個未知量,所以最小化問題得以求解。總偏差經過對$\textbf{m}_{i}$求導並令其等於0,獲得code

$\textbf{m}_{i}=\frac{\sum_{t}b_{i}^{t}\textbf{x}^{t}}{\sum_{t}b_{i}^{t}}$blog

這樣$\textbf{m}_{i}$得以更新。這是一個迭代的過程,一旦咱們計算出心的$\textbf{m}_{i}$,$\textbf{m}_{i}$就會發生改變並須要從新計算,這反過來又會影響$\textbf{m}_{i}$,這樣反反覆覆的重複,知道$\textbf{m}_{i}$再也不發生改變。ip

  Kmeans的僞代碼:utf-8

  初始化$\textbf{m}_{i},i=1,2,3...,k$。

    Repeat

      For 全部的$\textbf{x}^{t} \in X$

         若是$||\textbf{x}^{t}-\textbf{m}_{i}||==min_{j}||\textbf{x}^{t}-\textbf{m}_{j}||$,$b_{i}^{t}=1$,不然,$b_{i}^{t}=0$

      For 全部的$\textbf{m}_{i},i=1,2,...,k$

          $\textbf{m}_{i}=\frac{\sum_{t}b_{i}^{t}\textbf{x}^{t}}{\sum_{t}b_{i}^{t}}$

    Unitill $\textbf{m}_{i}$收斂

  Kmeans的缺點是,它是一個局部搜索的過程,而且最終的$\textbf{m}_{i}$高度依賴於出事的$\textbf{m}_{i}$的選擇。所以初始化至關重要,常見的初始化方法包括:

  •   簡單的隨機選擇$k$個實例做爲出事的$\textbf{m}_{i}$;
  •   計算全部數據的均值,並將一些小的隨機向量加到均值上,獲得$k$個初始的$\textbf{m}_{i}$;
  •   計算主成分,將它的值域劃分爲$k$個相等的去見,將數據劃分爲$k$個分組,而後取每一個分組的質心做爲初始的質心。
  1 # -*- coding=utf-8 -*-
  2 """
  3 kmeans:
  4 1. 加載數據
  5 2. 計算歐式距離
  6 3. 隨機生成k箇中心
  7 """
  8 from mpl_toolkits.mplot3d import Axes3D
  9 import matplotlib.pyplot as plt
 10 from numpy import *
 11 #加載文件數據,將標籤轉換爲數值類型
 12 def loadDataSet(filename):
 13     dataMat = []
 14     fr = open(filename, 'r')
 15     #依次讀取數據,將每行數據分別加入到list中
 16     for line in fr:
 17         curLine = line.strip().split('\t')
 18         #fltLine = map(float, curLine)
 19         dataMat.append(curLine)
 20     dataMat = mat(dataMat)
 21      #標籤類型是string,須要轉換爲123這樣的
 22     labels = dataMat[:,shape(dataMat)[1] - 1]
 23     #set集合,獲得全部種類的標籤
 24     labelsVec = []
 25     for i in range(shape(labels)[0]):
 26         labelsVec.append(labels[i,0])
 27     labelsSet = set(labelsVec)
 28     #print labelsSet
 29     labelFlag = 0
 30     #對相同的標籤賦予相同的值
 31     for item in labelsSet:
 32         index = nonzero(dataMat[:,shape(dataMat)[1] - 1].A == item)[0]
 33      #   print index
 34         dataMat[index,shape(dataMat)[1] - 1] = labelFlag
 35         labelFlag += 1
 36     #print dataMat
 37     fr.close()
 38     dataMat = dataMat.tolist()
 39     resMat = []
 40     #將string類型數據轉化爲數值類型
 41     for i in range(shape(dataMat)[0]):
 42         item = dataMat[i]
 43         tmp = map(float, item)
 44         resMat.append(tmp)
 45     resMat = mat(resMat)
 46     return resMat
 47 #計算歐式距離
 48 def distEclud(vecA, vecB):
 49     return sqrt(sum(power(vecA - vecB, 2)))
 50 #隨即選擇中心
 51 def randCent(dataSet, k):
 52     col = shape(dataSet)[1]
 53     centrals = mat(zeros((k, col)))
 54     for j in range(col):
 55         #取最大最小值,注意max與min返回的是matrix,須要轉化爲單個數值
 56         minJ = min(dataSet[:, j])[0, 0]
 57         maxJ = max(dataSet[:, j])[0, 0]
 58         rangeJ = maxJ - minJ
 59         centrals[:, j] = minJ + rangeJ * random.rand(k, 1)
 60     return centrals
 61 #kmeans算法
 62 def kMeans(dataSet, k, distMeans = distEclud, createCent = randCent):
 63     #m表示數據集的size,行數
 64     m = shape(dataSet)[0]
 65     clusterAssment = mat(zeros((m, 2)))
 66     #隨機生成k箇中心
 67     centrals = createCent(dataSet, k)
 68     #彙集再也不發生改變時中止循環
 69     clusterChanged = True
 70     while clusterChanged:
 71         clusterChanged = False
 72         #依次測量每一個數據點到各個彙集的距離
 73         for i in range(m):
 74             minDist = inf
 75             minIndex = -1
 76             #依次處理k個彙集的中心
 77             for j in range(k):
 78                 distJI = distMeans(centrals[j,:], dataSet[i,:])
 79                 #比較相對每一箇中心的距離,取最小距離對應的彙集
 80                 if distJI < minDist:
 81                     minDist = distJI
 82                     minIndex = j
 83             #判斷第i個樣本點的最小距離是否發生變化
 84             if clusterAssment[i,0] != minIndex:
 85                 clusterChanged = True
 86             #將每一個樣本點按距離分配到不一樣的彙集中
 87             clusterAssment[i,:] = minIndex, minDist**2
 88         #print central
 89         #更新各個彙集的中心
 90         for cent in range(k):
 91             ptsInClust = dataSet[nonzero(clusterAssment[:,0] == cent)[0]]
 92             centrals[cent,:] = mean(ptsInClust, axis = 0)
 93     return centrals, clusterAssment
 94 datingSet = loadDataSet("/home/lichao/DataSet/datingtestset.txt")
 95 dataSet = datingSet[:, 0:(shape(datingSet)[1] - 1)]
 96 labelSet = datingSet[:, shape(datingSet)[1]-1]
 97 central, clusterAssment = kMeans(dataSet, 3)
 98 print "kmeans算法使用後獲得的k箇中心的座標:"
 99 print central 
100 fig = plt.figure()
101 ax = Axes3D(fig)
102 for i in range(shape(dataSet)[0]):
103     if clusterAssment[i,0] == 0:
104         ax.scatter(dataSet[i,0],dataSet[i,1],dataSet[i,2],c='r', marker='D')
105     elif clusterAssment[i,0] == 1:
106         ax.scatter(dataSet[i,0],dataSet[i,1],dataSet[i,2],c='b', marker='+')
107     else:
108         ax.scatter(dataSet[i,0],dataSet[i,1],dataSet[i,2],c='G', marker='o')
109 plt.show()
View Code

運行結果:

相關文章
相關標籤/搜索