python实现k均值聚类(kMeans)基于numpy

1.k均值聚类简介

k均值聚类是一种无监督学习方法,当数据量小,数据维度低时,具有简单、快速、方便的优点,但是当数据量较大时,其速度较慢,也容易陷入局部最优。

2. 步骤

和以前一样,kMeans聚类的原理在网上有很多讲解,所以这里不在赘述,直接给出步骤,而通过伪代码将是一个描述步骤的不错选择:

随机初始化k个聚类中心
while 有样本所属的聚类中心发生改变时:
	for 每个样本i:
		初始化所有簇中心 距离 当前样本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  # 初始化所有簇中心 距离 当前样本i的最短距离dMin为无穷大
		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)  # 更新种类c的新的质心
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

纯手写不易.

——by 神采的二舅

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用Python实现k均值聚类的代码示例: ```python import numpy as np import random class KMeans: def __init__(self, k=3, max_iterations=500): self.k = k self.max_iterations = max_iterations def fit(self, data): self.centroids = self._initialize_centroids(data) for i in range(self.max_iterations): clusters = [[] for _ in range(self.k)] for point in data: distances = [np.linalg.norm(point - c) for c in self.centroids] cluster_index = np.argmin(distances) clusters[cluster_index].append(point) prev_centroids = self.centroids self.centroids = [np.average(cluster, axis=0) if cluster else prev_centroids[i] for i, cluster in enumerate(clusters)] if np.all(prev_centroids == self.centroids): break def predict(self, data): return np.argmin([np.linalg.norm(data - c) for c in self.centroids]) def _initialize_centroids(self, data): indices = random.sample(range(len(data)), self.k) return [data[i] for i in indices] ``` 使用时,可以创建一个KMeans类的实例,并使用fit方法将数据拟合到模型中。然后可以使用predict方法对新数据进行聚类预测。 下面是使用示例: ```python data = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]]) kmeans = KMeans(k=2) kmeans.fit(data) print(kmeans.centroids) # 输出: [array([1., 2.]), array([4., 2.])] print(kmeans.predict([0, 0])) # 输出: 0 ``` 该示例使用了一个包含6个数据点的二维数据集,并使用k=2进行聚类。fit方法会将数据拟合到模型中,并计算出两个聚类的中心点。然后使用predict方法对新的数据点进行预测,输出它属于哪个聚类
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值