1. 程式人生 > >K-means演算法優化(二分K-means演算法)

K-means演算法優化(二分K-means演算法)

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

# 計算歐氏距離
def distEclud(vector1, vector2):
    '''
    :param vector1: 第j個均值向量
    :param vector2: 第i個樣本
    :return: 距離值
    '''
    return sqrt(sum(power(vector2 - vector1, 2)))

#構建聚簇中心
def randCent(dataSet, k):
    n = shape(dataSet)[1]
    centroids = mat(zeros((k,n)))
    for j in range(n):
        minJ = min(dataSet[:,j])
        maxJ = max(dataSet[:,j])
        rangeJ = float(maxJ - minJ)
        centroids[:,j] = minJ + rangeJ * random.rand(k, 1)
    return centroids

def biKmeans(dataSet, k, distMeas=distEclud):
    m = shape(dataSet)[0]
    #首先建立一個矩陣來儲存資料集中每個點的簇分配結果及平方誤差
    clusterAssment = mat(zeros((m,2)))
    #----建立一個初始簇----
    #計算整個資料集的質心
    centroid0 = mean(dataSet, axis=0).tolist()[0]

    #使用一個列表來保留所有的質心
    centList = [centroid0]
    #遍歷資料集中所有點來計算每個點到質心的誤差值
    for j in range(m):
        clusterAssment[j,1] = distMeas(mat(centroid0), dataSet[j,:])**2
    #while迴圈會不停的對簇進行劃分,直到得到想要的簇數目為止
    while(len(centList) < k):
        lowestSSE = inf    #python中inf表示正無窮
        #遍歷簇列表centList中的每一個簇
        for i in range(len(centList)):
            #-----嘗試劃分每一簇----
            #對每個簇,將該簇中的所有點看成一個小的資料集ptsInCurrCluster
            ptsInCurrCluster = dataSet[nonzero(clusterAssment[:,0].A==i)[0],:]
            #將ptsInCurrCluster輸入到函式KMeans()中進行處理(k=2)。K-均值演算法會生成兩個質心(簇),同時給出每個簇的誤差值
            centroidMat, splitClustAss = kMeans(ptsInCurrCluster, 2, distMeas)

            #劃分後的樣本誤差之和
            sseSplit = sum(splitClustAss[:, 1])
            #剩餘資料集的誤差之和
            sseNotSplit = sum(clusterAssment[nonzero(clusterAssment[:, 0].A != i)[0], 1])
            print("sseSplit, and notSplit: ", sseSplit, sseNotSplit)
            #將劃分後的樣本誤差之和+剩餘資料集的誤差之和作為本次劃分的誤差
            if(sseSplit + sseNotSplit) < lowestSSE:
                #決定要劃分某一個簇
                bestCentToSplit = i
                #劃分後的質心
                bestNewCents = centroidMat
                #劃分後的簇分配結果矩陣,包含兩列:第一列記錄簇索引,第二列儲存誤差
                bestClustAss = splitClustAss.copy()
                # 本次劃分的誤差
                lowestSSE = sseSplit + sseNotSplit
            #----更新簇的分配結果----
        #將劃分簇中所有點的簇分配結果進行修改,當使用KMeans()函式並且指定簇數為2時,會得到兩個編號分別為0和1的結果簇
        #需要將這些簇編號修改為劃分簇及新加簇的編號,該過程可以通過兩個陣列過濾器來完成。
        bestClustAss[nonzero(bestClustAss[:, 0].A == 1)[0], 0] = len(centList)
        bestClustAss[nonzero(bestClustAss[:, 0].A == 0)[0], 0] = bestCentToSplit
        print('the bestCentToSplit is: ', bestCentToSplit)
        print('the len of bestClustAss is: ', len(bestClustAss))
        #新的質心會被新增到centList中
        centList[bestCentToSplit] = bestNewCents[0, :].tolist()[0]
        centList.append(bestNewCents[1, :].tolist()[0])
        # 更新SSE的值(sum of squared errors)
        clusterAssment[nonzero(clusterAssment[:, 0].A == bestCentToSplit)[0],:] = bestClustAss
    return mat(centList),clusterAssment

#k-means 聚類演算法
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
        print(centroids)
        for cent in range(k):
            ptsInClust = dataSet[nonzero(clusterAssment[:,0].A == cent)[0]]   # 去第一列等於cent的所有列
            centroids[cent,:] = mean(ptsInClust, axis = 0)
    return centroids, clusterAssment

# show your cluster only available with 2-D data
def showCluster(dataSet, k, centroids, clusterAssment):
    numSamples, dim = dataSet.shape
    if dim != 2:
        print ("Sorry! I can not draw because the dimension of your data is not 2!")
        return 1

    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
    if k > len(mark):
        print ("Sorry! Your k is too large! please contact Zouxy")
        return 1

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

    mark = ['Dr', 'Db', 'Dg', 'Dk', '^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()

def main():
    ## step 1: load data
    print ("step 1: load data...")
    dataSet = []
    data = xlrd.open_workbook('C:/Users/Microstrong/Desktop/watermelon4.0.xlsx')
    table = data.sheets()[0]
    for line in range(0,table.nrows):
        lineArr = table.row_values(line)
        dataSet.append([float(lineArr[0]), float(lineArr[1])])

    ## step 2: clustering...
    print ("step 2: clustering...")
    dataSet = mat(dataSet)
    k = 3
    centroids, clusterAssment = biKmeans(dataSet, k)

    ## step 3: show the result
    print ("step 3: show the result...")
    showCluster(dataSet, k, centroids, clusterAssment)

if __name__ == '__main__':
 main()

相關推薦

K-means演算法優化二分K-means演算法

from numpy import * import xlrd import matplotlib.pyplot as plt # 計算歐氏距離 def distEclud(vector1, vector2): ''' :param vector1: 第j個均值向量 :param v

插入排序演算法+優化 二分查詢優化有序部分C語言實現

直接插入排序 插入排序思想        直接插入排序思想是將待排序的陣列看作兩個部分:有序部分和無序部分,排序過程就是不斷將無序部分的元素插入到有序部分合適的位置上,使有序部分元素不斷增加而無序部分資料不斷減少,直到陣列全部有序為止。         假設陣列A[0...

二分K-means聚類bisecting K-means

1 def biKmeans(dataSet, k, distMeas=distEclud): 2 m = shape(dataSet)[0] 3 clusterAssment = mat(zeros((m,2)))#記錄簇分配的結果及誤差 4 centroid0 = me

《機器學習實戰》二分-kMeans演算法二分K均值聚類

首先二分-K均值是為了解決k-均值的使用者自定義輸入簇值k所延伸出來的自己判斷k數目,其基本思路是: 為了得到k個簇,將所有點的集合分裂成兩個簇,從這些簇中選取一個繼續分裂,如此下去,直到產生k個簇。 虛擬碼: 初始化簇表,使之包含由所有的點組成的簇。 repeat   &n

k-means k均值聚類 及二分k均值聚類

from numpy import * def load_data(file_name): data=[] fr=open(file_name) for line in fr.readlines(): cur_line=line.st

演算法】topK問題:得到序列中前k小的數含複雜度分析

思路一 利用排序方法(快排/堆排序)對序列從小到大進行排序 輸出序列前k個數  void TopK( int a[], int n, int k ) { if(k<0 || k>n) return;    sort(a,n);

資料探勘領域十大經典演算法之—K-鄰近演算法/kNN超詳細附程式碼

簡介 又叫K-鄰近演算法,是監督學習中的一種分類演算法。目的是根據已知類別的樣本點集求出待分類的資料點類別。 基本思想 kNN的思想很簡單:在訓練集中選取離輸入的資料點最近的k個鄰居,根據這個k個鄰居中出現次數最多的類別(最大表決規則),作為該資料

nyoj 第k個互質數二分+容斥原理

第k個互質數 描述 兩個數的a,b的gcd為1,即a,b互質,現在給你一個數m,你知道與它互質的第k個數是多少嗎?與m互質的數按照升序排列。 輸入輸入m ,k (1<=m<=10000

熱身訓練-k皇後問題主副對角線計算

tro 變量 線下 with prev span med cell edi Gargari is jealous that his friend Caisa won the game from the previous problem. He wants to prove

FZU 1919 -- K-way Merging sort記憶化搜索

one initial map from max task sys fzu pointer 題目鏈接 Problem Description As we all known, merge sort is an O(nlogn) comparison-based s

hdu-1150二分圖+匈牙利演算法

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=1150 思路:題目中給出兩個機器A,B;給出k個任務,每個任務可以由A的x狀態或者B的y狀態來完成。 完成任務的順序可以任意改變,每次改變一次狀態需要重啟一次機器。 將每個狀態看做一個點,每個任務看做兩個狀態

【LeetCode題解】347_前K個高頻元素Top-K-Frequent-Elements

目錄 描述 解法一:排序演算法(不滿足時間複雜度要求) Java 實現 Python 實現 複雜度分析 解法二:最小堆 思路 Java 實現 Python 實現 複雜度分析 解法三:桶排序(bucket s

演算法優化1:基礎知識-凸集,單峰函式,擬凸函式與凸函式,函式凹凸性定義

本文筆記介紹我最近學習的演算法優化的基礎知識,有: 最優化問題的一般形式 約束問題的分類及形式 優化問題的分類 單峰函式(Unimodal function)的定義 擬凸函式(Quasiconvex function)的定義

匈牙利演算法二分圖匹配問題

匈牙利演算法(二分圖匹配問題) 問題連結(杭電2063題):http://acm.hdu.edu.cn/showproblem.php?pid=2063 參考部落格:https://blog.csdn.net/cillyb/article/details/55511666 找伴侶是個遞迴

【NOIP2012提高】藍書演算法競賽進階指南刷題記錄——疫情控制二分+樹上倍增+貪心

題目:luogu1084. 題目大意:給定一棵樹,以及一些在樹上的軍隊.現在這些軍隊可以走動,並能在點上駐紮,從一條邊的一段走到另一端需要與這條的長度等價的時間.現在要求用最短的時間,使得所有葉子節點到根節點的路徑上有軍隊,且軍隊不能在根節點駐紮. 由於我們肯定更想讓一個點覆蓋的葉子節點

演算法模板:匈牙利演算法模板二分圖匹配

 pascal匈牙利演算法模板 //匈牙利演算法模板 var i,j,n,m,so,x,y,ans,t:longint; h:array[1..200]of longint; p:array[1..400]of longint; bz,gcl:array[0..40

最短路演算法優化dijkstra演算法+鄰接表+佇列優化,bellman演算法+鄰接表+佇列優化

dijkstra演算法+鄰接表+佇列優化: #include<bits/stdc++.h> using namespace std; const int M=1000000000;

1281二分圖--匈牙利演算法

HDU - 1281(二分圖–匈牙利演算法) 小希和Gardon在玩一個遊戲:對一個N*M的棋盤,在格子裡放盡量多的一些國際象棋裡面的“車”,並且使得他們不能互相攻擊,這當然很簡單,但是Gardon限制了只有某些格子才可以放,小希還是很輕鬆的解決了這個問題(見下

K-inversions URAL - 1523 DP+樹狀陣列

連結 https://cn.vjudge.net/problem/URAL-1523 題意 給你一個1-n的序列 問長度為K的序列有多少種 思路 首先想到DP 遞推式 dp[i][j] =  ∑dp[x][j-1] ( 1<x<i,a[x] > a[i

協同過濾推薦演算法優化稀疏矩陣的處理

簡單的協同過濾演算法流程如下 (1)、計算其他使用者和你的相似度,可以使用反差表忽略一部分使用者 (2)、根據相似度的高低找出K個與你最相似的鄰居 (3)、在這些鄰居喜歡的物品中,根據鄰居與你的遠近程度算出每一件物品的推薦度 (4)、根據每一件物品的推薦度高低給你推薦物品。