日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

python實現k均值聚類(kMeans)基于numpy

作者:神采的二舅 更新時間: 2022-10-29 編程語言

1.k均值聚類簡介

k均值聚類是一種無監督學習方法,當數據量小,數據維度低時,具有簡單、快速、方便的優點,但是當數據量較大時,其速度較慢,也容易陷入局部最優。

2. 步驟

和以前一樣,kMeans聚類的原理在網上有很多講解,所以這里不在贅述,直接給出步驟,而通過偽代碼將是一個描述步驟的不錯選擇:

隨機初始化k個聚類中心
while 有樣本所屬的聚類中心發生改變時:
	for 每個樣本i:
		初始化最短距離dMin為無窮大
		初始化距離其最近的簇中心的索引為jNearest
		for 每個聚類中心j:
			計算當前樣本到當前聚類中心的距離di
			如果di小于dMin:
				dMin<-di
				jNearest=j
		對每個樣本所屬于的簇進行標記
	計算各個簇中的樣本的中心點,作為新的聚類中心

3. 代碼實現

3.1 輔助函數

我們第一件要做的事就是定義一個能夠在合理范圍內隨機產生聚類中心的函數,主要思想是,通過計算數據每個特征的最大值和最小值,然后在該范圍內隨機選擇一個值即可:

import numpy as np


def randCenters(data:np.matrix,k:int):
	n=data.shape[1]
    cent=np.mat(np.zeros((k,n)))    # 初始化k個質心
    for j in range(n):
        minJ=data[:,j].min()
        maxJ=data[:,j].max()
        rangeJ=float(maxJ-minJ)    # 第j個特征的范圍
        cent[:,j]=minJ+rangeJ*np.random.rand(k,1)
    return cent
	

我們還需要做一件事情,那就是完成距離的計算的函數,顯然,這個函數將會被多次調用,用于計算當前樣本與當前聚類中心的距離,你可以自定義距離的計算方式,比如我選擇的是歐幾里得距離:

def distance(a: np.matrix, b: np.matrix):
	"""計算a,b兩個向量之間的歐幾里得距離"""
	return np.sqrt(np.sum(np.power(a-b,2)))

3.2 分步驟實現各個模塊

我并不打算直接將一大串最終的實現代碼給出,因為這樣不便于讀者看出每段代碼的目的,所以我將先將代碼分功能講解,最后在給出完整的代碼。

1. 首先來做一些初始化:

m=data.shape[0]
clusterCenter=randCenters(data,k)
clusterChanged=True
clusterAss-np.mat(np.zeros((m,2)))

其中,m是樣本的個數,clusterChanged是一個標志,方便我們控制接下來的while循環。
最令人費解的可能是clusterAss,它的第一列將為每個樣本做標記,標記其屬于哪個簇,第二列將保存該樣本到該簇的距離distance.

2. 進入循環體(你可以結合偽代碼來看)

while clusterChanged:
	clusterChanged=False
	for i in range(m):    # 對每個樣本,找到其歸屬,并計算到該歸屬的距離
		minDist=np.inf
		belongClust=-1
		for j in range(k):    # 為當前樣本遍歷每個簇中心
			dist=distance(data[i,:],cluterCenter[j,:])
			if dist<minDist:
				minDist=dist
				belongClust=j
		# 看看當前樣本所屬的簇有沒有發生變化,如果有,則改變標志clusterChanged,繼續迭代
		if clusterAss[i,:].A[0][0] != j:
			clusterChanged=True
			clusterAss[i,:]=belongClust,minDist

上面的代碼所做的事如下:計算每個樣本對所有聚類中心的距離,然后按照距離最小的原則,給出其歸屬,并將該歸屬和對應的距離保存到clusterAss中。

3. 更新聚類中心

不要忘了,我們以上所做的工作只是對我們最開始所隨機產生的聚類中心所做的計算,我們還需要根據每次聚類的結果,更新每個簇所在的簇中心。這里我們使用每個簇內樣本點的平均值來作為其幾何中心,也就是更新后的新的簇中心:

for c in range(k):
	pointsInCluster=data[np.nonzero(clusterAss.A[:,0]==c)[0],:]    # 獲取屬于簇c的數據,數組切片一定要熟練!
	clusterCenter[c,:]=np.mean(pointsInCluster,axis-0)

4. 最后返回聚類中心和每個樣本的歸屬

return clusterCenter,clusterAss

完整代碼

def kMeans1(data:np.matrix, k=3):
    m=data.shape[0]
    clusterAss=np.mat(np.zeros((m,2)))
    clusterChanged=True
    clusterCenter=randCent(data,k)    # 隨機初始化各個簇的質心
    
    while clusterChanged:
        clusterChanged=False
        for i in range(m):    # 對每個樣本
            minDist=np.inf
            belongClust=-1
            for j in range(len(clusterCenter)):    # 對每個聚類中心
                dist=distEclud(data[i,:].A[0],clusterCenter[j,:].A[0])
                if dist < minDist:
                    minDist=dist
                    belongClust=j
            if clusterAss[i,:].A[0][0]!=belongClust:
                clusterChanged=True
            clusterAss[i,:]=belongClust,minDist
            
        for c in range(k):
            pointsInClust = data[np.nonzero(clusterAss[:, 0].A == c)[0], :]
            clusterCenter[c,:]=np.mean(pointsInClust,axis=0)    # 更新聚類中心
            
    return clusterCenter,clusterAss

原文鏈接:https://blog.csdn.net/weixin_57005504/article/details/127578020

欄目分類
最近更新