
1.作者介绍马一超男西安工程大学电子信息学院2025级研究生研究方向模式识别与人工智能电子邮件2424102004qq.com2K-Means算法介绍2.1 算法原理K-Means 是一种基于划分的聚类算法其核心思想是通过迭代优化将数据集划分为k个簇使得簇内样本的相似度最大化簇间样本的相似度最小化。算法通过不断更新簇中心质心和重新分配样本点来达到最优划分。算法流程基于以下关键概念簇中心Centroid每个簇的代表点通常为簇内所有样本的平均值。簇分配Assignment将每个样本点分配到距离最近的簇中心。簇更新Update根据当前簇内样本计算新的簇中心。2.2 算法优缺点优点简单易理解算法直观易于实现。计算效率高适合大规模数据集尤其是样本维度不高时。收敛速度快通过迭代优化误差平方和SSE快速收敛。结果可解释性强每个簇都有明确的中心便于理解和应用。缺点需预设簇数k簇数需要先确定若选择不当会影响聚类效果。对初始中心敏感不同的初始质心可能导致不同的结果。不适合非球形簇算法假设簇为凸形或球形无法处理复杂形状。对离群点敏感异常值会对簇中心计算产生较大影响。高维数据问题距离度量在高维空间可能失效聚类效果下降。2.3 算法实现流程1.随机选择k个初始簇中心2.对每个样本点计算其与k个簇中心的距离并将其分配到距离最近的簇3.更新每个簇的中心为簇内所有样本的均值4.重复步骤 2-3直到簇中心不再发生显著变化或达到迭代上限5.输出最终簇划分结果。图 1 K-mean算法流程图3.葡萄酒数据集分析3.1数据集介绍葡萄酒数据集是 sklearn 内置的经典多分类数据集来源于 UCI Wine 数据集主要用于根据葡萄酒的化学成分判断其所属类别。该数据集共有 178 个样本、13 个特征、3 个类别每类样本数分别为 59、71、48。所有特征都是连续型、正数型数值特征图 2葡萄酒数据集示例3.2实验代码# -*- coding:utf-8 -*- # Author: MYC # Date: 2026/5/28 # File: wine.py # Description: 葡萄酒聚类分析 基于K-means聚类的葡萄酒数据集分析 功能 1. 数据加载与基本信息查看 2. 缺失值检查 3. 标准化前后K-means聚类效果对比 4. k值选择肘部法则、轮廓系数、CH指数、DB指数 5. PCA降维可视化 6. 聚类结果评价 7. 聚类中心分析 8. 与层次聚类、DBSCAN、GMM进行比较 import numpy as np import pandas as pd from sklearn.datasets import load_wine from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA from sklearn.cluster import KMeans, AgglomerativeClustering, DBSCAN from sklearn.mixture import GaussianMixture from sklearn.metrics import ( silhouette_score, calinski_harabasz_score, davies_bouldin_score, adjusted_rand_score, normalized_mutual_info_score, confusion_matrix ) from scipy.optimize import linear_sum_assignment import matplotlib matplotlib.use(TkAgg) import matplotlib.pyplot as plt # 中文显示 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 聚类准确率函数 def clustering_accuracy(y_true, y_pred): y_true np.asarray(y_true) # 将真实标签和预测标签转换为 NumPy 数组。 y_pred np.asarray(y_pred) cm confusion_matrix(y_true, y_pred) # 生成混淆矩阵 cm。 row_ind, col_ind linear_sum_assignment(-cm) # 使用 linear_sum_assignment(-cm) 找到最大匹配。 matched_sum cm[row_ind, col_ind].sum() return matched_sum / len(y_true) # 返回匹配样本数 / 总样本数即准确率。 # 聚类评价函数 def evaluate_clustering(X, y_true, y_pred, method_name): unique_labels np.unique(y_pred) # 获取预测聚类中唯一簇的数量。 if len(unique_labels) 1 and len(unique_labels) len(X): # 只有簇数量大于 1 且小于样本总数才计算这些指标。否则返回 NaN。 silhouette silhouette_score(X, y_pred) ch_score calinski_harabasz_score(X, y_pred) db_score davies_bouldin_score(X, y_pred) else: silhouette np.nan ch_score np.nan db_score np.nan ari adjusted_rand_score(y_true, y_pred) nmi normalized_mutual_info_score(y_true, y_pred) # ARI、NMI 是无监督聚类的评价指标。 acc clustering_accuracy(y_true, y_pred) # acc 使用前面定义的匈牙利匹配方法。 return { 方法: method_name, 簇数量: len(unique_labels), 轮廓系数: silhouette, CH指数: ch_score, DB指数: db_score, ARI指数: ari, NMI指数: nmi, 准确率: acc } # 加载数据 wine load_wine() X wine.data y wine.target feature_names wine.feature_names feature_dict { alcohol: 酒精, malic_acid: 苹果酸, ash: 灰分, alcalinity_of_ash: 灰分碱度, magnesium: 镁, total_phenols: 总酚, flavanoids: 黄酮类化合物, nonflavanoid_phenols: 非黄酮酚, proanthocyanins: 原花青素, color_intensity: 颜色强度, hue: 色调, od280/od315_of_diluted_wines: OD280/OD315, proline: 脯氨酸 } feature_names_cn [] for i in feature_names: result feature_dict[i] feature_names_cn.append(result) df pd.DataFrame(X, columnsfeature_names_cn) df[类别] y print( * 60) print(葡萄酒数据集基本信息) print( * 60) print(样本数量, X.shape[0]) print(特征数量, X.shape[1]) print(\n特征名称) print(feature_names_cn) print(\n前5行数据) print(df.head()) print(\n缺失值检查) print(df.isnull().sum()) # 数据标准化 scaler StandardScaler() X_scaled scaler.fit_transform(X) # 对每个特征做均值 0 方差 1 的标准化 # 标准化前后比较 # 分别对未标准化和标准化数据进行 K-means 聚类簇数设为 3。 kmeans_raw KMeans(n_clusters3, random_state42, n_init10) labels_raw kmeans_raw.fit_predict(X) kmeans_scaled KMeans(n_clusters3, random_state42, n_init10) labels_scaled kmeans_scaled.fit_predict(X_scaled) # 对比标准化前后聚类效果。 compare_standardization pd.DataFrame([ evaluate_clustering(X, y, labels_raw, 未标准化K-means), evaluate_clustering(X_scaled, y, labels_scaled, 标准化K-means) ]) print(\n标准化前后比较) print(compare_standardization) # k值选择 # 循环尝试不同 K 值。 # 记录 SSEinertia、轮廓系数、CH 指数、DB 指数用于选择最佳 K。 k_values range(2, 9) inertias [] silhouette_scores [] ch_scores [] db_scores [] for k in k_values: model KMeans(n_clustersk, random_state42, n_init10) labels model.fit_predict(X_scaled) inertias.append(model.inertia_) silhouette_scores.append(silhouette_score(X_scaled, labels)) ch_scores.append(calinski_harabasz_score(X_scaled, labels)) db_scores.append(davies_bouldin_score(X_scaled, labels)) # 保存指标表 k_evaluation pd.DataFrame({ 聚类数k: list(k_values), 误差平方和: inertias, 轮廓系数: silhouette_scores, CH指数: ch_scores, DB指数: db_scores }) print(k_evaluation) # 图1 肘部法则 plt.figure(figsize(8, 5)) plt.plot(k_values, inertias, markero) plt.xlabel(聚类数k) plt.ylabel(误差平方和) plt.title(肘部法则选择最佳聚类数) plt.grid() plt.savefig( 01_肘部法则.png, dpi300 ) plt.show() # 图2 轮廓系数 plt.figure(figsize(8, 5)) plt.plot(k_values, silhouette_scores, markero) plt.xlabel(聚类数k) plt.ylabel(轮廓系数) plt.title(不同聚类数下的轮廓系数) plt.grid() plt.savefig(02_轮廓系数.png, dpi300) plt.show() # 图3 CH指数 plt.figure(figsize(8, 5)) plt.plot(k_values, ch_scores, markero) plt.xlabel(聚类数k) plt.ylabel(CH指数) plt.title(不同聚类数下CH指数) plt.grid() plt.savefig(03_CH指数.png, dpi300) plt.show() # 图4 DB指数 plt.figure(figsize(8, 5)) plt.plot(k_values, db_scores, markero) plt.xlabel(聚类数k) plt.ylabel(DB指数) plt.title(不同聚类数下DB指数) plt.grid() plt.savefig(04_DB指数.png, dpi300) plt.show() # PCA降维 pca PCA(n_components2) X_pca pca.fit_transform(X_scaled) print(\n累计解释方差) print(pca.explained_variance_ratio_.sum()) # 真实类别 plt.figure(figsize(8, 6)) plt.scatter(X_pca[:, 0], X_pca[:, 1], cy) plt.xlabel(主成分1) plt.ylabel(主成分2) plt.title(PCA降维后的真实类别) plt.colorbar(label真实类别) plt.grid() plt.savefig(05_PCA真实类别.png, dpi300) plt.show() # K-means聚类结果 plt.figure(figsize(8, 6)) plt.scatter(X_pca[:, 0], X_pca[:, 1], clabels_scaled) plt.xlabel(主成分1) plt.ylabel(主成分2) plt.title(PCA降维后的K-means聚类结果) plt.colorbar(label聚类标签) plt.grid() plt.savefig(06_Kmeans聚类结果.png, dpi300) plt.show() # 聚类中心分析 cluster_centers_original scaler.inverse_transform(kmeans_scaled.cluster_centers_) # 将标准化后的聚类中心反变换回原始特征尺度 cluster_centers_df pd.DataFrame(cluster_centers_original, columnsfeature_names_cn) # 用 DataFrame 展示每个簇的中心特征值 print(\n聚类中心) print(cluster_centers_df) # 算法对比 results [] # 将多种聚类算法在同一数据集上对比。 models [ (K-means, KMeans(n_clusters3, random_state42, n_init10)), (层次聚类, AgglomerativeClustering(n_clusters3)), (DBSCAN, DBSCAN(eps2.3, min_samples5)), (GMM, GaussianMixture(n_components3, random_state42)) ] for name, model in models: labels model.fit_predict(X_scaled) results.append(evaluate_clustering(X_scaled, y, labels, name)) algorithm_compare pd.DataFrame(results) print(\n不同聚类算法对比) print(algorithm_compare) # 保存结果 compare_standardization.to_csv(标准化较.csv, indexFalse, encodingutf-8-sig) k_evaluation.to_csv(K值分析.csv, indexFalse, encodingutf-8-sig) cluster_centers_df.to_csv(聚类中心.csv, indexFalse, encodingutf-8-sig) algorithm_compare.to_csv(算法比较.csv, indexFalse, encodingutf-8-sig) print(\n程序运行完成) print(结果文件已保存)3.3实验结果图 3 肘部法则选择最佳聚类数从肘部法则图可以看出当 k2 → k3 时误差平方和SSE下降最明显当 k3 后SSE 下降速度明显减缓曲线在 k3 处出现明显“拐点”。因此肘部法则认为最佳聚类数为 k3。这说明将数据划分为 3 个簇后簇内离散程度已经大幅降低继续增加聚类数带来的收益有限。图 4 不同聚类数下的轮廓系数轮廓系数取值范围越接近 1 表示聚类效果越好接近 0 表示簇间重叠小于 0 表示分类错误。从图中可以看到kSilhouette20.25930.28540.26050.20160.23770.20380.157最高值出现在因此轮廓系数同样认为 k3 时聚类质量最好。图 5 不同聚类数下CH指数分析图CH 指数定义为其特点越大越好表示簇间距离远且簇内更加紧凑。结果如下kCH269.6370.9456.2546.9641.7738.7835.8最大值出现在因此CH 指数也支持 k3图 6 不同聚类数下DB指数分析图DB 指数定义为特点越小越好越小说明簇间分离度越高。结果如下kDB21.5331.3941.8051.8161.5571.6681.74最小值出现在因此DB 指数同样认为 k3 是最佳聚类数。图 7 PCA降维后的真实类别分布图图 8 PCA降维后的K-Means聚类结果图3.4其余实验对比1.不同聚类算法:表 1 不同聚类算法效果对比表方法簇数量轮廓系数CH指数DB指数ARI指数NMI指数准确率K-means30.284970.94001.38920.89750.87590.9663层次聚类30.277467.64751.41860.78990.78650.9270DBSCAN30.173628.36073.71570.38380.47640.6910GMM30.284970.94001.38920.89750.87590.96632.基于随机森林:图 9 随机森林分类结果图图 10 各维度占比结果图随机森林实验代码# -*- coding-UTF-8 -*- # Author: MYC # Date: 2026/5/27 14:53 # File: Random Forest.py # Description: 随机森林 from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report import matplotlib.pyplot as plt import pandas as pd plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 加载数据 wine load_wine() X wine.data y wine.target feature_names wine.feature_names # 划分训练集测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42, stratifyy ) # 随机森林模型 rf RandomForestClassifier( n_estimators200, random_state42 ) rf.fit(X_train, y_train) # 预测 y_pred rf.predict(X_test) # 准确率 acc accuracy_score(y_test, y_pred) print(Accuracy:, acc) print(\n分类报告) print(classification_report(y_test, y_pred)) # 特征重要性 importance pd.Series( rf.feature_importances_, indexfeature_names ).sort_values() plt.figure(figsize(8,6)) importance.plot(kindbarh) plt.xlabel(特征重要性) plt.ylabel(特征名称) plt.title(随机森林特征重要性分析) plt.tight_layout() plt.show()3.MLP神经网络:图 11 MLP 训练损失曲线图图 12 MLP 分类结果图MLP实验代码# -*- coding-UTF-8 -*- # Author: MYC # Date: 2026/5/27 15:01 # File: MLP神经网络.py # Description: 轻量化的深度学习 from sklearn.datasets import load_wine from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neural_network import MLPClassifier from sklearn.metrics import accuracy_score, classification_report from sklearn.decomposition import PCA import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 加载数据 wine load_wine() X wine.data y wine.target # 标准化神经网络必须做 scaler StandardScaler() X_scaled scaler.fit_transform(X) # 划分训练集 X_train, X_test, y_train, y_test train_test_split( X_scaled, y, test_size0.2, random_state42, stratifyy ) # 神经网络 model MLPClassifier( hidden_layer_sizes(64, 32), activationrelu, solveradam, max_iter1000, random_state42 ) model.fit(X_train, y_train) # 预测 y_pred model.predict(X_test) acc accuracy_score(y_test, y_pred) print(Accuracy:, acc) print(\n分类报告) print(classification_report(y_test, y_pred)) # 1. 绘制训练损失曲线 plt.figure(figsize(8, 5)) plt.plot( model.loss_curve_, markero ) plt.xlabel(迭代次数) plt.ylabel(损失值) plt.title(MLP神经网络训练损失曲线) plt.grid(True) plt.tight_layout() plt.savefig( MLP训练损失曲线.png, dpi300 ) plt.show() # 2. PCA降维可视化预测结果 pca PCA(n_components2) X_test_pca pca.fit_transform(X_test) plt.figure(figsize(8, 6)) plt.scatter( X_test_pca[:, 0], X_test_pca[:, 1], cy_pred, s80 ) plt.xlabel(主成分1) plt.ylabel(主成分2) plt.title(MLP神经网络预测结果PCA可视化) plt.colorbar(label预测类别) plt.grid(True) plt.tight_layout() plt.savefig( MLP预测结果PCA可视化.png, dpi300 ) plt.show()