1.理论知识
K-means算法,又称为k均值算法。K-means算法中的k表示的是聚类为k个簇,means代表取每一个聚类中数据值的均值作为该簇的中心,或者称为质心,即用每一个的类的质心对该簇进行描述。K-Means算法接受参数K;然后将样本数据集划分为K个聚类。获得的聚类需要满足:同一个聚类中的样本数据集相似度较高;而不同聚类中的样本数据集相似度较小。
算法思想:
以空间中K个点为中心进行聚类(即先从样本集中随机选取 k个样本作为簇中心),对最靠近他们的对象归类(所有样本与这 k个“簇中心”的距离,对于每一个样本,将其划分到与其距离最近的“簇中心”所在的簇中)。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。
2.算法流程
3.算法流程图
4.参考代码
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import f1_score, accuracy_score, normalized_mutual_info_score, rand_score
from sklearn.preprocessing import LabelEncoder
from sklearn.decomposition import PCA
# 数据保存在.csv文件中
iris = pd.read_csv("dataset/Iris.csv", header=0) # 鸢尾花数据集 Iris class=3
# wine = pd.read_csv("dataset/wine.csv") # 葡萄酒数据集 Wine class=3
# seeds = pd.read_csv("dataset/seeds.csv") # 小麦种子数据集 seeds class=3
# wdbc = pd.read_csv("dataset/wdbc.csv") # 威斯康星州乳腺癌数据集 Breast Cancer Wisconsin (Diagnostic) class=2
# glass = pd.read_csv("dataset/glass.csv") # 玻璃辨识数据集 Glass Identification class=6
df = iris # 设置要读取的数据集
columns = list(df.columns) # 获取数据集的第一行,第一行通常为特征名,所以先取出
features = columns[:len(columns) - 1] # 数据集的特征名(去除了最后一列,因为最后一列存放的是标签,不是数据)
dataset = df[features] # 预处理之后的数据,去除掉了第一行的数据(因为其为特征名,如果数据第一行不是特征名,可跳过这一步)
attributes = len(df.columns) - 1 # 属性数量(数据集维度)
class_labels = list(df[columns[-1]]) # 原始标签
k = 3
# 这里已经知道了分3类,其他分类这里的参数需要调试
model = KMeans(n_clusters=k)
# 训练模型
model.fit(dataset)
# 预测全部数据
label = model.predict(dataset)
print(label)
def clustering_indicators(labels_true, labels_pred):
if type(labels_true[0]) != int:
labels_true = LabelEncoder().fit_transform(df[columns[len(columns) - 1]]) # 如果数据集的标签为文本类型,把文本标签转换为数字标签
f_measure = f1_score(labels_true, labels_pred, average='macro') # F值
accuracy = accuracy_score(labels_true, labels_pred) # ACC
normalized_mutual_information = normalized_mutual_info_score(labels_true, labels_pred) # NMI
rand_index = rand_score(labels_true, labels_pred) # RI
return f_measure, accuracy, normalized_mutual_information, rand_index
F_measure, ACC, NMI, RI = clustering_indicators(class_labels, label)
print("F_measure:", F_measure, "ACC:", ACC, "NMI", NMI, "RI", RI)
if attributes > 2:
dataset = PCA(n_components=2).fit_transform(dataset) # 如果属性数量大于2,降维
# 打印出聚类散点图
plt.scatter(dataset[:, 0], dataset[:, 1], marker='o', c='black', s=7) # 原图
plt.show()
colors = np.array(["red", "blue", "green", "orange", "purple", "cyan", "magenta", "beige", "hotpink", "#88c999"])
maker = ['*', '+', 'x', 'D', '8', 's']
# 循换打印k个簇,每个簇使用不同的颜色
for i in range(k):
plt.scatter(dataset[np.nonzero(label == i), 0],
dataset[np.nonzero(label == i), 1],
c=colors[i],
s=100,
marker=maker[i % 5]
)
plt.show()
5.测试数据
(鸢尾花数据集,你需要到网络上下载)
表3.1K-Means算法输入的数据
sepal length | sepal width | petal length | petal width | class |
5.1 | 3.5 | 1.4 | 0.2 | Iris-setosa |
4.9 | 3 | 1.4 | 0.2 | Iris-setosa |
… | … | … | … | … |
4.6 | 3.1 | 1.5 | 0.2 | Iris-setosa |
*输入的数据用于鸢尾花的类型判断,同时K设置为3。
6.实验结果与分析
图3.2鸢尾花数据集
图3.3 鸢尾花数据k-means分类后实验结果
7.算法优缺点
优点:
- 算法简单,容易实现
缺点:
- 对K个初始质心的选择比较敏感,容易陷入局部最小值。
- K值是用户指定的,而用户很难去选择一个合适的完美的K值。又因为没有标签,很难进行评估。
- 对于一些复杂的数据分布就无法进行正确的聚类。