🍖 原作者:K同学啊 | 接辅导、项目定制
聚类算法的定义:
聚类就是将一个庞杂数据集中具有相似特征的数据自动归类到一起,称为一个簇,簇内的对象越相似,聚类的效果越好。"相似"这一概念,是利用距离标准来衡量的,我们通过计算对象与对象之间的距离远近来判断它们是否属于同一类别,即是否是同一个簇。
聚类是一种无监督学习(Unsupervised Learning)的方法,不需要预先标注好训练集。聚类与分类最大的区别就是分类的目标事先已知,对于一个动物集来说,你并不清楚这个数据集内部有多少种类的动物,你能做的只是利用聚类方法将它自动按照特征分为多类,然后人为给出这个聚类结果的定义(即簇识别)。例如,你将一个动物集分为了三簇(类),然后通过观察这三类动物的特征,你为每一个簇起一个名字,如大象、狗、猫等,这就是聚类的基本思想。
K-means就是一个聚类的算法,属于无监督学习算法,也是就样本没有标签。算法会根据某种规则进行"分割",把相同的或者相近的数据放在一起。K-means算法的基本思想是通过不断更新簇的中心点,将数据集划分为预定数量的簇。这一过程涉及到计算数据点之间的距离,通常使用欧式距离作为相似性度量。在算法执行过程中,每个数据点被分配到距离最近的簇,然后更新簇的中心,迭代进行直至收敛。
聚类过程
K-means算法接受一个参数K用以决定结果中簇的数目。算法开始时,要在数据集中随机选择K
个数据对象用来当做K
个簇的初始中心,而将剩下的各个数据对象就根据他们和每个聚类簇心的距离选择簇心最近的簇分配到其中。然后重新计算各个聚类簇中的所有数据对象的平均值,并将得到的结果作为新的簇心;逐步重复上述的过程直至目标函数收敛为止。其步骤具体地:
- 第一步 :从N个样本数据中随机选取
K
个对象,作为初始的聚类中心; - 第二步:分别计算每个样本点到各个聚类中心的距离,并逐个分配到距离其最近的簇中;
- 第三步:所有对象分配完成后,更新K个类中心位置,类中心定义为簇内所有对象在各个维度的均值;
- 第四步 :与前一次计算得到的
K
个聚类中心比较,如果聚类中心发生变化,转至步骤2,否则转至步骤5; - 第五步:当类中心不再发生变化,停止并输出聚类结果,然后整理我们所需要的信息,如各个样本所属的类等等,进行后续的统计和分析。
聚类结束之前,类中心会不断移动,而随着类中心的移动,样本的划分情况也会持续发生改变。
代码
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from numpy import nonzero, array
from sklearn.decomposition import PCA
# 数据保存在.csv文件中
iris = pd.read_csv("dataset/Iris.csv", header=0) # 鸢尾花数据集 Iris class=3
df = iris # 设置要读取的数据集
df
python
columns = list(df.columns) # 获取数据集的第一行,第一行通常为特征名,所以先取出
columns
python
# 数据集的特征名(去除了最后一列,因为最后一列存放的是标签,不是数据)
features = columns[:-1]
features
python
# 预处理之后的数据,去除掉了第一行的数据(因为其为特征名,如果数据第一行不是特征名,可跳过这一步)
dataset = df[features]
dataset
python
attributes = len(df.columns) - 1 # 属性数量(数据集维度)
original_labels = list(df[columns[-1]]) # 原始标签
python
def draw_cluster(dataset, centers, labels, k):
center_array = array(centers)
if attributes > 2:
# 将三维数据降为二维,方便进行可视化
dataset = PCA(n_components=2).fit_transform(dataset) # 如果属性数量大于2,降维
center_array = PCA(n_components=2).fit_transform(center_array) # 如果属性数量大于2,降维
else:
dataset = array(dataset)
# 做散点图
label = array(labels)
plt.scatter(dataset[:, 0],
dataset[:, 1],
marker='o',
c='black', s=7) # 原图
colors = np.array(
["#FF0000", "#0000FF", "#00FF00", "#FFFF00", "#00FFFF", "#FF00FF", "#800000", "#008000", "#000080", "#808000",
"#800080", "#008080", "#444444", "#FFD700", "#008080"])
# 循换打印k个簇,每个簇使用不同的颜色
for i in range(k):
plt.scatter(dataset[nonzero(label == i), 0],
dataset[nonzero(label == i), 1],
c=colors[i],
s=7, marker='o')
plt.show()
python
from sklearn.cluster import KMeans
k = 3
# 使用KMeans进行聚类
kmeans = KMeans(n_clusters=k, n_init=10).fit(dataset) # 指定要分的簇数
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
# 提供的数据
data = {
'K1': [3, 3, 4, 4, 1, 1, 2, 2],
'K2': [1, 2, 1, 2, 3, 4, 3, 4]
}
# 创建DataFrame
df = pd.DataFrame(data)
# 提取用于聚类的特征
X = df[['K1', 'K2']]
# 初始化KMeans模型列表,并设定k的范围
range_n_clusters = [1, 2, 3, 4, 5, 6, 7, 8] # 扩大了k的范围
inertia_scores = []
# 对每个k值进行聚类并计算SSE值
for n_clusters in range_n_clusters:
# 使用KMeans算法
kmeans = KMeans(n_init=10,
n_clusters=n_clusters,
random_state=123)
kmeans.fit(X)
# 获取SSE值
inertia = kmeans.inertia_
inertia_scores.append(inertia)
# 绘制惯性指标随聚类数量变化的图形
plt.figure(figsize=(8, 4))
plt.plot(range_n_clusters, inertia_scores, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('SSE')
plt.title('SSE for Different Number of Clusters')
plt.xticks(range_n_clusters) # 显示所有x轴刻度
plt.show()