K-means聚类模型


前言

今天我们来复习K-means聚类模型,并用项目教大家快速了解K-means聚类模型,我会将大家编写代码中常见的错误点在代码注释中指出,希望不会浪费大家的时间,高效学习


一、项目背景与数据集

  • 目标:根据鸢尾花的花萼和花瓣尺寸(4个特征),将样本分为3类(与真实类别对比)
  • 数据集:Scikit-learn内置的 load_iris 数据集(150个样本,4个特征)
  • 项目价值:掌握K-Means的核心原理、聚类过程及其可视化

二、完整代码实现

1.加载数据集与探索

提取出数据特征,标签,以及名称等信息,并对前两个特征的样本进行可视化

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

# 加载数据集
data = load_iris()
X = data.data
y = data.target

# 查看数据基本信息
print("特征名称:", data.feature_names)
print("样本数:", X.shape[0], "特征数:", X.shape[1])
print("真实标签分布:\n", pd.Series(y).value_counts())

# 可视化前两个特征分布
plt.figure(figsize=(10, 6))
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', alpha=0.7)
plt.xlabel(data.feature_names[0])
plt.ylabel(data.feature_names[1])
plt.title("鸢尾花数据集前两个特征的分布(真实标签)")
plt.colorbar(label="类别")
plt.show()

输出效果
在这里插入图片描述

在这里插入图片描述

2.数据预处理

# 标准化特征(K-Means对特征尺度敏感!)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 对比标准化前后的特征分布
plt.figure(figsize=(10, 6))
plt.subplot(1,2,1)
plt.hist(X[:, 0], bins=20, color='blue', alpha=0.7)
plt.title("标准化前的特征0分布")
plt.subplot(1,2,2)
plt.hist(X_scaled[:, 0], bins=20, color='red', alpha=0.7)
plt.title("标准化后的特征分布")
plt.show()

输出效果
在这里插入图片描述

3.手动实现K-Means聚类

class KMeansManual:
    def __init__(self, n_clusters=3, max_iters=100):
        self.n_clusters = n_clusters  # 聚类数
        self.max_iters = max_iters
        self.centroids = None   # 聚类中心
        self.labels = None    
    
    def _eculidean_distance(self, x1, x2):
        """计算欧氏距离"""
        return np.sqrt(np.sum((x1 - x2) ** 2))
    
    def _initialize_centroids(self, X):
        """随机初始化聚类中心"""
        indices = np.random.choice(X.shape[0], self.n_clusters, replace=False) # 无放回抽取n_clusters个索引
        return X[indices] 
        # 通过 X[indices] 获取这些索引对应的数据点作为初始聚类中心
    
    def fit(self, X):
        """训练模型:迭代更新聚类中心和样本标签"""
        n_samples, n_features = X.shape
        self.centroids = self._initialize_centroids(X)

		# 进入 for 循环,最多执行 max_iters 次迭代,直到收敛
        for _ in range(self.max_iters):
            # 1.分配样本到最近的聚类中心
            distance = np.zeros((n_samples, self.n_clusters)) 
            for i in range(self.n_clusters):
                distance[:, i] = np.array([self._eculidean_distance(x, self.centroids[i]) for x in X])  # 二维数组,存储每个样本到每个聚类中心的距离
            self.labels = np.argmin(distance, axis=1)
            
            # 2.更新聚类中心
            new_centroids = np.zeros((self.n_clusters, n_features))
            for i in range(self.n_clusters):
                new_centroids[i] = np.mean(X[self.labels == i], axis=0) # 以旧类样本各个特征的平均值作为新的中心
            
            # 3.检查是否收敛
            if np.allclose(self.centroids, new_centroids):
                break
            self.centroids = new_centroids
    def predict(self, X):
        """预测样本的聚类标签"""
        distances = np.zeros((X.shape[0], self.n_clusters))
        for i in range(self.n_clusters):
            distances[:, i] = np.array([self._eculidean_distance(x, self.centroids[i]) for x in X])
        return np.argmin(distances, axis=1)
    
# 训练手动实现的模型
manual_kmeans = KMeansManual(n_clusters=3)
manual_kmeans.fit(X_scaled)

# 预测聚类标签
y_pred_manual = manual_kmeans.predict(X_scaled)

    

4.sklearn实现

from sklearn.cluster import KMeans

# 创建并训练模型
sklearn_kmeans = KMeans(n_clusters=3, random_state=42)
sklearn_kmeans.fit(X_scaled)

# 预测聚类标签
y_pred_sklearn = sklearn_kmeans.predict(X_scaled)

# 查看聚类中心
print("\n聚类中心:\n", sklearn_kmeans.cluster_centers_)

# 可视化聚类结果
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y_pred_manual, cmap='viridis', alpha=0.7) # c表示颜色决定,不同类别颜色不同,cmap控制颜色变化
plt.scatter(manual_kmeans.centroids[:, 0], manual_kmeans.centroids[:, 1], c='red', marker='x', s=200)
plt.title("手动实现K-Means聚类结果")
plt.subplot(1, 2, 2)
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y_pred_sklearn, cmap='viridis', alpha=0.7)
plt.scatter(sklearn_kmeans.cluster_centers_[:, 0], sklearn_kmeans.cluster_centers_[:, 1], c='red', marker='x', s=200)
plt.title("Scikit-learn K-Means聚类结果")
plt.tight_layout()
plt.show()

输出效果
在这里插入图片描述


三、模型评估与对比

from sklearn.metrics import silhouette_score

# 计算轮廓系数(评估聚类效果)
silhouette_manual = silhouette_score(X_scaled, y_pred_manual)
silhouette_sklearn = silhouette_score(X_scaled, y_pred_sklearn)

print("\n手动实现K-Means的轮廓系数:", silhouette_manual)
print("Scikit-learn K-Means的轮廓系数:", silhouette_sklearn)

# 对比聚类结果与真实标签
print("\n手动实现K-Means vs 真实标签:")
print(pd.crosstab(y, y_pred_manual, rownames=['真实标签'], colnames=['预测标签']))
print("\nScikit-learn K-Means vs 真实标签:")
print(pd.crosstab(y, y_pred_sklearn, rownames=['真实标签'], colnames=['预测标签']))

输出效果
在这里插入图片描述


总结

以上就是今天要讲的内容,本文仅仅简单介绍了K-means聚类模型的推导与实现,还有一些其他的优化K-means聚类模型的方法但本文主旨是便于大家复习模型,就不再赘述


以上所有代码在Github仓库

结尾致敬

我是一位新手博客小白,将以复习机器学习与深度学习和强化学习模型为系列进行创作,希望能和大家一起共勉学习,如果有问题或者错误请在评论区@鼠鼠,觉得有帮助大家的可别忘了点赞加关注哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值