利用Python如何实现K-means聚类算法

作者:尚歌 时间:2023-09-16 09:17:38 

目录
  • 前言

  • 算法原理

  • 目标函数

  • 算法流程

  •  Python实现

  • 总结

前言

K-Means 是一种非常简单的聚类算法(聚类算法都属于无监督学习)。给定固定数量的聚类和输入数据集,该算法试图将数据划分为聚类,使得聚类内部具有较高的相似性,聚类与聚类之间具有较低的相似性。

算法原理

1. 初始化聚类中心,或者在输入数据范围内随机选择,或者使用一些现有的训练样本(推荐)

2. 直到收敛

  • 将每个数据点分配到最近的聚类。点与聚类中心之间的距离是通过欧几里德距离测量得到的。

  • 通过将聚类中心的当前估计值设置为属于该聚类的所有实例的平均值,来更新它们的当前估计值。

目标函数

聚类算法的目标函数试图找到聚类中心,以便数据将划分到相应的聚类中,并使得数据与其最接近的聚类中心之间的距离尽可能小。

给定一组数据X1,...,Xn和一个正数k,找到k个聚类中心C1,...,Ck并最小化目标函数:

利用Python如何实现K-means聚类算法其中利用Python如何实现K-means聚类算法是质心,计算表达式为利用Python如何实现K-means聚类算法

利用Python如何实现K-means聚类算法

上图a表达了初始的数据集,假设k=2。在图b中,我们随机选择了两个k类所对应的类别质心,即图中的红色质心和蓝色质心,然后分别求样本中所有点到这两个质心的距离,并标记每个样本的类别为和该样本距离最小的质心的类别,如图c所示,经过计算样本和红色质心和蓝色质心的距离,我们得到了所有样本点的第一轮迭代后的类别。此时我们对我们当前标记为红色和蓝色的点分别求其新的质心,如图4所示,新的红色质心和蓝色质心的位置已经发生了变动。图e和图f重复了我们在图c和图d的过程,即将所有点的类别标记为距离最近的质心的类别并求新的质心。最终我们得到的两个类别如图f。当然在实际K-Mean算法中,我们一般会多次运行图c和图d,才能达到最终的比较优的类别。

算法流程

注意点:

  1. 对于K-Means算法,首先要注意的是k值的选择,一般来说,我们会根据对数据的先验经验选择一个合适的k值,如果没有什么先验知识,则可以通过交叉验证选择一个合适的k值

  2. 在确定了k的个数后,我们需要选择k个初始化的质心,就像上图b中的随机质心。由于我们是启发式方法,k个初始化的质心的位置选择对最后的聚类结果和运行时间都有很大的影响,因此需要选择合适的k个质心,最好这些质心不能太近。

流程:

输入是样本集D={x1,x2,...xm},聚类的簇树k,最大迭代次数N

输出是簇划分C={C1,C2,...Ck}

1) 从数据集D中随机选择k个样本作为初始的k个质心向量: {μ1,μ2,...,μk}

2)对于n=1,2,...,N

a) 将簇划分C初始化为Ct=∅  t=1,2...k

b) 对于i=1,2...m,计算样本xi和各个质心向量μj(j=1,2,...k)的距离:利用Python如何实现K-means聚类算法,将xixi标记最小的为利用Python如何实现K-means聚类算法所对应的类别利用Python如何实现K-means聚类算法。此时更新利用Python如何实现K-means聚类算法

c) 对于j=1,2,...,k,对Cj中所有的样本点重新计算新的质心利用Python如何实现K-means聚类算法

e) 如果所有的k个质心向量都没有发生变化,则转到步骤3)

3) 输出簇划分C={C1,C2,...Ck}

 Python实现


import numpy as np
import matplotlib.pyplot as plt
import random
from sklearn.datasets import make_blobs
np.random.seed(123)
from sklearn.cluster import KMeans
class Kmeans:
   def __init__(self,data,k):
       self.data=data
       self.k = k
   def cluster_data_Bysklearn(self):
       kmeans_model = KMeans(self.k,random_state=1)
       labels = kmeans_model.fit(self.data).labels_
       print(labels)
       return labels

def kmeans(self):
       # 获取4个随机数
       rarray = np.random.random(size=self.k)
       # 乘以数据集大小——>数据集中随机的4个点
       rarray = np.floor(rarray * len(self.data))
       # 转为int
       rarray = rarray.astype(int)
       print('数据集中随机索引', rarray)
       # 随机取数据集中的4个点作为初始中心点
       center = data[rarray]
       # 测试比较偏、比较集中的点,效果依然完美,测试需要删除以上代码
       # center = np.array([[4.6,-2.5],[4.4,-1.7],[4.3,-0.7],[4.8,-1.1]])
       # 1行80列的0数组,标记每个样本所属的类(k[i])
       cls = np.zeros([len(self.data)], np.int)
       print('初始center=\n', center)
       run = True
       time = 0
       n = len(self.data)
       while run:
           time = time + 1
           for i in range(n):
               # 求差
               tmp = data[i] - center
               # 求平方
               tmp = np.square(tmp)
               # axis=1表示按行求和
               tmp = np.sum(tmp, axis=1)
               # 取最小(最近)的给该点“染色”(标记每个样本所属的类(k[i]))
               cls[i] = np.argmin(tmp)
           # 如果没有修改各分类中心点,就结束循环
           run = False
           # 计算更新每个类的中心点
           for i in range(self.k):
               # 找到属于该类的所有样本
               club = data[cls == i]
               # axis=0表示按列求平均值,计算出新的中心点
               newcenter = np.mean(club, axis=0)
               # 如果新旧center的差距很小,看做他们相等,否则更新之。run置true,再来一次循环
               ss = np.abs(center[i] - newcenter)
               if np.sum(ss, axis=0) > 1e-4:
                   center[i] = newcenter
                   run = True
           print('new center=\n', center)
       print('程序结束,迭代次数:', time)
       # 按类打印图表,因为每打印一次,颜色都不一样,所以可区分出来
       # for i in range(self.k):
       #     club = data[cls == i]
       #     self.showtable(club)
       # 打印最后的中心点
       self.showtable(center)
       #打印聚类标签
       print(cls)

def showtable(self,data):
       x = data.T[0]
       y = data.T[1]
       plt.scatter(x, y)
       plt.show()

if __name__ == '__main__':
   data = np.random.rand(10,2)
   K = 4
   model = Kmeans(data,K)

model.kmeans()
   model.cluster_data_Bysklearn()

结果:

自写得出的    [0 2 0 0 0 2 3 2 1 2]
调用模型的出的[0 2 0 1 0 2 3 2 3 0]

jupyter notebook实现


import numpy as np
import matplotlib.pyplot as plt
import random
from sklearn.datasets import make_blobs

%matplotlib inline

X, y = make_blobs(centers=6, n_samples=1000)
print(f'Shape of dataset: {X.shape}')

fig = plt.figure(figsize=(8,6))
plt.scatter(X[:,0], X[:,1], c=y)
plt.title("Dataset with 6 clusters")
plt.xlabel("First feature")
plt.ylabel("Second feature")
plt.show()

利用Python如何实现K-means聚类算法 


class KMeans():
   def __init__(self, n_clusters=6):
       self.k = n_clusters

def fit(self, data):
       """
       Fits the k-means model to the given dataset
       """
       n_samples, _ = data.shape
       # initialize cluster centers
       self.centers = np.array(random.sample(list(data), self.k))
       self.initial_centers = np.copy(self.centers)

# We will keep track of whether the assignment of data points
       # to the clusters has changed. If it stops changing, we are
       # done fitting the model
       old_assigns = None
       n_iters = 0

while True:
           new_assigns = [self.classify(datapoint) for datapoint in data]

if new_assigns == old_assigns:
               print(f"Training finished after {n_iters} iterations!")
               return

old_assigns = new_assigns
           n_iters += 1

# recalculate centers
           for id_ in range(self.k):
               points_idx = np.where(np.array(new_assigns) == id_)
               datapoints = data[points_idx]
               self.centers[id_] = datapoints.mean(axis=0)

def l2_distance(self, datapoint):
       dists = np.sqrt(np.sum((self.centers - datapoint)**2, axis=1))
       return dists

def classify(self, datapoint):
       """
       Given a datapoint, compute the cluster closest to the
       datapoint. Return the cluster ID of that cluster.
       """
       dists = self.l2_distance(datapoint)
       return np.argmin(dists)

def plot_clusters(self, data):
       plt.figure(figsize=(12,10))
       plt.title("Initial centers in black, final centers in red")
       plt.scatter(data[:, 0], data[:, 1], marker='.', c='y')
       plt.scatter(self.centers[:, 0], self.centers[:,1], c='r')
       plt.scatter(self.initial_centers[:, 0], self.initial_centers[:,1], c='k')
       plt.show()

X = np.random.randn(10,100)
kmeans = KMeans(n_clusters=6)
kmeans.fit(X)
for data in X:
   print(kmeans.classify(data))

总结

K-Means的主要优点:

1)原理简单,容易实现

2)可解释度较强

K-Means的主要缺点:

1)K值很难确定

2)局部最优

3)对噪音和异常点敏感

4)需样本存在均值(限定数据种类)

5)聚类效果依赖于聚类中心的初始化

6)对于非凸数据集或类别规模差异太大的数据效果不好

来源:https://blog.csdn.net/wudibaba21/article/details/119704339

标签:python,k-means,聚类
0
投稿

猜你喜欢

  • MySQL时间字段究竟使用INT还是DateTime

    2010-03-09 14:46:00
  • node.js的事件机制

    2024-05-03 15:58:31
  • Vue实现购物车功能

    2024-04-30 10:26:21
  • python统计函数库scipy.stats的用法解析

    2022-08-12 07:15:32
  • Python中的字典遍历备忘

    2021-12-08 05:59:37
  • 关于php开启错误提示的总结

    2023-11-04 10:46:21
  • python数据结构算法分析

    2022-06-11 02:57:15
  • python3+selenium实现qq邮箱登陆并发送邮件功能

    2023-02-04 17:54:23
  • python获得一个月有多少天的方法

    2022-02-21 00:55:15
  • Python使用psutil获取进程信息的例子

    2021-11-03 07:29:47
  • 对Python 数组的切片操作详解

    2022-06-09 23:29:39
  • 教你利用python实现企业微信发送消息

    2023-09-06 11:20:55
  • python 梯度法求解函数极值的实例

    2023-08-11 07:33:05
  • mac下给python3安装requests库和scrapy库的实例

    2023-11-06 09:44:52
  • pandas带有重复索引操作方法

    2023-04-19 20:22:12
  • jsp自定义标签之ifelse与遍历自定义标签示例

    2023-06-25 21:09:34
  • 一个简单的python爬虫程序 爬取豆瓣热度Top100以内的电影信息

    2023-01-09 19:50:16
  • OpenCV 图像对比度的实践

    2023-07-29 09:09:27
  • pywinauto自动化测试使用经验

    2022-12-21 02:36:10
  • mysql主从服务器同步心得体会第1/2页

    2024-01-18 13:34:20
  • asp之家 网络编程 m.aspxhome.com