1. 程式人生 > >SVM演算法 K-means的python實現

SVM演算法 K-means的python實現

arg

argument of the maximum/minimum

arg max f(x): 當f(x)取最大值時,x的取值

arg min f(x):當f(x)取最小值時,x的取值

 

 

s.t.是subject to (such that)的縮寫,受約束的意思。

按中文習慣可以翻譯成:使得...滿足...(約束條件

 

 

在求解最優化問題中,拉格朗日乘子法(Lagrange Multiplier)和KKT(Karush Kuhn Tucker)條件是兩種最常用的方法。在有等式約束時使用拉格朗日乘子法,在有不等約束時使用KKT條件

(1)無約束條件

  這是最簡單的情況,解決方法通常是函式對變數求導,令求導函式等於0的點可能是極值點。將結果帶回原函式進行驗證即可

2)等式約束條件

      設目標函式為f(x),約束條件為h_k(x)

則解決方法是消元法或者拉格朗日法。消元法比較簡單不在贅述,這裡主要講拉格朗日法,因為後面提到的KKT條件是對拉格朗日乘子法的一種泛化。

 

3)不等式約束條件(KKT

http://www.cnblogs.com/zhangchaoyang/articles/2726873.html

https://blog.csdn.net/johnnyconstantine/article/details/46335763

 

4.如果資料集中存在噪點的話----鬆弛變數

https://blog.csdn.net/d__760/article/details/80387432

5.資料並不是線性可分----核函式

 

K-Means演算法

# coding:utf-8

import numpy as np
import matplotlib.pyplot as plt


def loadDataSet(fileName):
    '''
    載入測試資料集,返回一個列表,列表的元素是一個座標
    '''
    dataList = []
    with open(fileName) as fr:
        for line in fr.readlines():
            curLine = line.strip().split('\t')
            fltLine = list(map(float,curLine))
            dataList.append(fltLine)
    return dataList


def randCent(dataSet, k):
    '''
    隨機生成k個初始的質心
    '''
    n = np.shape(dataSet)[1] # n表示資料集的維度
    centroids = np.mat(np.zeros((k,n)))
    for j in range(n):
        minJ = min(dataSet[:,j])
        rangeJ = float(max(dataSet[:,j]) - minJ)
        centroids[:,j] = np.mat(minJ + rangeJ * np.random.rand(k,1))
    return centroids


def kMeans(dataSet, k):
    '''
    KMeans演算法,返回最終的質心座標和每個點所在的簇
    '''
    m = np.shape(dataSet)[0] # m表示資料集的長度(個數)
    clusterAssment = np.mat(np.zeros((m,2)))

    centroids = randCent(dataSet, k) # 儲存k個初始質心的座標
    clusterChanged = True
    iterIndex=1 # 迭代次數
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            minDist = np.inf; minIndex = -1
            for j in range(k):
                distJI = np.linalg.norm(np.array(centroids[j,:])-np.array(dataSet[i,:]))
                if distJI < minDist:
                    minDist = distJI; minIndex = j
            if clusterAssment[i,0] != minIndex: clusterChanged = True
            clusterAssment[i,:] = minIndex,minDist**2
            print("第%d次迭代後%d個質心的座標:\n%s"%(iterIndex,k,centroids)) # 第一次迭代的質心座標就是初始的質心座標
            iterIndex+=1
        for cent in range(k):
            ptsInClust = dataSet[np.nonzero(clusterAssment[:,0].A==cent)[0]]#get all the point in this cluster
            centroids[cent,:] = np.mean(ptsInClust, axis=0)
    return centroids, clusterAssment


def showCluster(dataSet, k, centroids, clusterAssment):
    '''
    資料視覺化,只能畫二維的圖(若是三維的座標圖則直接返回1)
    '''
    numSamples, dim = dataSet.shape
    if dim != 2:
        return 1

    mark = ['or', 'ob', 'og', 'ok','oy','om','oc', '^r', '+r', 'sr', 'dr', '<r', 'pr']

    # draw all samples
    for i in range(numSamples):
        markIndex = int(clusterAssment[i, 0])
        plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex])

    mark = ['Pr', 'Pb', 'Pg', 'Pk','Py','Pm','Pc','^b', '+b', 'sb', 'db', '<b', 'pb']
    # draw the centroids
    for i in range(k):
        plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 12)

    plt.show()

if __name__ == '__main__':

    dataMat = np.mat(loadDataSet('./testSet')) #mat是numpy中的函式,將列表轉化成矩陣

    k = 4 # 選定k值,也就是簇的個數(可以指定為其他數)
    cent, clust = kMeans(dataMat, k)

    showCluster(dataMat, k, cent, clust)