Python实现简单k-means聚类

目录

1.导入原始数据集

 2.首次计算中心点

3.进行迭代循环,不断优化样本中心点和聚类结果

4.聚类可视化

通过手动书写k-means聚类算法的逻辑实现聚类(而非使用python内置的sklearn)

不了解k-means聚类算法的话可以先去了解以下这种算法的原理,下面就直接进入正题啦~


1.导入原始数据集

首先我们导入原始样本点,这里我们通过execl表记录原始数据,原始数据为假设为某班学术的平时成绩 和 期末成绩。原始数据如下图所示

import pandas as pd
import random
import math
import matplotlib.pyplot as plt

documentObject = pd.read_excel(r"C:\Users\DELL\Desktop\proData.xlsx")
documentLst = documentObject.values.tolist()
print(documentLst)

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
for i in range(len(documentLst)):
    x = documentLst[i][0]
    y = documentLst[i][1]
    plt.scatter(x, y, s = 50)
    plt.xlabel('平时成绩')
    plt.ylabel('期末成绩')
plt.show()

除了导入原始样本数据以外,原始数据在坐标系中的散点图如下

 2.首次计算中心点

我们设置k值,以及最大迭代次数等初始变量

首次的样本中心点通过randint函数在所有样本点中随机选取,由于最后通过迭代聚类算法总能找到合适的样本中心点,所以首次的样本中心点选取可以随机选取

dataLength = len(documentLst)
#k为聚类中心点个数
k = 3
#iteraions为起始的迭代量
iterations = 0
#maxIteraions表示最大迭代次数
maxIteraions = 400
#centre用来保存中心点的坐标,随机出k个样本数据作为中心点
centre = []
for i in range(k):
    centre.append([0]*2)
for i in range(k):
    tempIndex = random.randint(0, dataLength - 1)
    centre[i][0] = documentLst[tempIndex][0]
    centre[i][1] = documentLst[tempIndex][1]
print(centre)
#disRecord用于记录每一个样本点里中心点的距离
disRecord = []
for i in range(dataLength):
    disRecord.append([0]*3)
#定义distance函数计算两点间距离
def distance(samples, centres):
    return math.sqrt((samples[0] - centres[0])**2 + (samples[1] - centres[1])**2)

finalClusters = []
for i in range(k):
    finalClusters.append([])

3.进行迭代循环,不断优化样本中心点和聚类结果

每一次迭代后新的样本中心点的坐标值取自于某一个类的所有样本点的坐标平均值

这里简单地将迭代终止条件为——最大迭代次数(这里只是为了简单所以才选择了400次迭代作为终止条件,并不是一定要以此为标准!),最后的聚类结果随着迭代次数增加而更加准确,也可以设置其他阈值为迭代停止条件!

#进行k-means主体
while iterations < maxIteraions:
    #用于记录新的k个样本中心点的坐标
    new_centres = []
    for i in range(k):
        new_centres.append([0]*2)
    # cluster用于记录聚类结果[[], [], []]
    clusters = []
    for i in range(k):
        clusters.append([])

    for i in range(dataLength):
        for j in range(k):
            disRecord[i][j] = distance(documentLst[i], centre[j])
    #将某一个样本点的坐标添加至cluster列表中
    for i in range(dataLength):
        index = disRecord[i].index(min(disRecord[i]))
        clusters[index].append(i)
        new_centres[index][0] += documentLst[i][0]
        new_centres[index][1] += documentLst[i][1]
    #创建用于迭代的中心点数组
    temp_centre = []
    for i in range(k):
        temp_centre.append([0]*2)
    for i in range(k):
        temp_centre[i][0] = (new_centres[i][0])/len(clusters[i])
        temp_centre[i][1] = (new_centres[i][1])/len(clusters[i])

    if(temp_centre == centre):
        break;
    else:
        centre = temp_centre
        iterations += 1
        finalClusters = clusters
print("聚类中心为:", centre)
print("分类情况为:", finalClusters)

4.聚类可视化

通过为不同聚类的样本点添加不同的颜色,从而能直观地在散点图中看到聚类结果

colors = ['red', 'yellow', 'aqua']
for i, j in zip(range(k), colors):
    for index in finalClusters[i]:
        plt.scatter(x = documentLst[index][0], y = documentLst[index][1], c=j)
plt.xlabel('平时成绩')
plt.ylabel('期末成绩')
plt.show()

 

  • 9
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我为您提供一份Python代码来实现这个任务,其中使用了`sklearn`库来进行KMeans聚类,使用了`pso`库来进行粒子群聚类: ```python import numpy as np import cv2 from sklearn.cluster import KMeans from pso import PSO # 读入图像 img = cv2.imread('01.jpg', 0) # 进行KMeans聚类 kmeans = KMeans(n_clusters=4, random_state=0).fit(img.reshape(-1, 1)) init_centers = kmeans.cluster_centers_ # 定义FCM算法 def fcm(data, clusters, m, epsilon=0.01, max_iter=100): centers = np.random.rand(clusters, data.shape[1]) centers /= np.sum(centers, axis=1, keepdims=True) for i in range(max_iter): dist = np.linalg.norm(data[:, None, :] - centers[None, :, :], axis=2) membership = 1 / dist ** (2 / (m - 1)) membership /= np.sum(membership, axis=1, keepdims=True) new_centers = np.sum(membership[:, :, None] * data[:, None, :], axis=0) / np.sum(membership, axis=0)[:, None] if np.linalg.norm(new_centers - centers) < epsilon: break centers = new_centers return centers, membership # 定义适应度函数 def fitness(x): _, membership = fcm(img.reshape(-1, 1), 4, 2, max_iter=10, centers=x) return -np.sum(membership ** 2) # 进行粒子群聚类 pso = PSO(func=fitness, dim=4, pop=40, max_iter=50, lb=np.zeros((4,)), ub=np.ones((4,))*255, w=0.8, c1=0.6, c2=0.6) pso.run() global_centers = pso.gbest # 最终的聚类中心 centers = np.vstack((init_centers, global_centers)) # 进行FCM分割 _, membership = fcm(img.reshape(-1, 1), 8, 2, max_iter=10, centers=centers) labels = np.argmax(membership, axis=1).reshape(img.shape) # 显示结果 cv2.imshow('input', img) cv2.imshow('output', labels*64) cv2.waitKey(0) ``` 这个代码会先读入`01.jpg`这张灰度图像,然后使用`sklearn`库进行KMeans聚类,得到4个初始聚类中心。然后使用`pso`库进行粒子群聚类,得到全局最优聚类中心。最后将初始聚类中心和全局最优聚类中心合并,带入FCM算法进行图像分割。最终结果以灰度图像的形式显示出来。 请注意,这个代码需要安装`sklearn`和`pso`库。您可以使用以下命令来安装: ```bash pip install scikit-learn pip install pso ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值