聚类
类别
- 划分(分裂)算法
- K-Means算法(K-平均)
- K-MFDOIDS算法(K-中心)
- CLARANS算法
- 层次分析方法
- BIRCH算法(平衡迭代规约和聚类)
- CURE算法(点聚类)
- 基于密度的方法
- DBSCAN算法(基于高密度连接区域)
- DENCLUE算法(密度分布函数)
K—Means
简介
-
K-means算法是集简单和经典于一身的基于距离的聚类算法
-
采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。
-
该算法认为类簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
核心思想
-
通过迭代寻找k个类簇的一种划分方案,使得用这k个类簇的均值来代表相应各类样本时所得的总体误差最小。
-
k个聚类具有以下特点:
- 各聚类本身尽可能的紧凑
- 各聚类之间尽可能的分开
- 优点:容易实现
- 缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢
- 使用数据类型:数值型数据
-
算法步骤:
- 首先我们选择c个类/组,并随机初始化它们各自的中心点。中心点是与每个数据点向量长度相同的位置。这需要我们提前预知类的数量(即中心点的数量)。
- 计算每个数据点到中心点的距离,数据点距离哪个中心点最近就划分到哪一类中。
- 计算每一类中中心点作为新的中心点。
- 重复以上步骤,直到每一类中心在每次迭代后变化不大为止。也可以多次随机初始化中心点,然后选择运行结果最好的一个。
代码段
- 使用sklearn模块
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
from sklearn import datasets
iris = datasets.load_iris()
X = iris.data[:, :2] # #表示我们取特征空间中的4个维度
print(X.shape)
# 绘制数据分布图
plt.scatter(X[:, 0], X[:, 1], c="red", marker='o', label='see')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()
estimator = KMeans(n_clusters=3) # 构造聚类器
estimator.fit(X) # 聚类
label_pred = estimator.labels_ # 获取聚类标签
# 绘制k-means结果
x0 = X[label_pred == 0]
print(x0)
x1 = X[label_pred == 1]
x2 = X[label_pred == 2]
plt.scatter(x0[:, 0], x0[:, 1], c="red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c="green", marker='*', label='label1')
plt.scatter(x2[:, 0], x2[:, 1], c="blue", marker='+', label='label2')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()
- 手动计算并显示
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
iris = load_iris()
def dist(x,y):
# dist: 求样本间的余弦相似度
return sum(x*y)/(sum(x**2)*sum(y**2))**0.5
def K_means(data=iris.data[:,:2],k=3,ping=0,maxiter=100):
# k: 类别数
# maxiter: 最大迭代次数
n, m = data.shape # n:样本个数,m:属性个数
print(n,m)
centers = data[:k,:] #初始类中心
while ping < maxiter: #迭代步数
dis = np.zeros([n,k+1]) #距离矩阵
for i in range(n): #求各样本至各类中心的距离
for j in range(k):
dis[i,j] = dist(data[i,:],centers[j,:])
dis[i,k] = dis[i,:k].argmax()
centers_new = np.zeros([k,m])
for i in range(k):
# 求新类中心:各类样本均值作为新类中心
index = dis[:,k]==i
centers_new[i,:] = np.mean(data[index,:],axis=0)
if np.all(centers==centers_new):
# 判定类中心是否发生变化
break
centers = centers_new #更新类中心
ping += 1
print(centers)
print(ping)
x0 = []
x1 = []
x2 = []
index0 = dis[:,k]==0
x0 = data[index0,:]
index1 = dis[:,k]==1
x1 = data[index1,:]
index2 = dis[:,k]==2
x2 = data[index2,:]
plt.scatter(x0[:, 0], x0[:, 1], c="red", marker='o', label='label0')
plt.scatter(x1[:, 0], x1[:, 1], c="green", marker='*', label='label1')
plt.scatter(x2[:, 0], x2[:, 1], c="blue", marker='+', label='label2')
plt.xlabel('petal length')
plt.ylabel('petal width')
plt.legend(loc=2)
plt.show()
return dis
if __name__ == '__main__':
res = K_means()