下图为主要介绍的几个聚类方法:
1、 k均值(K-means)
▲在指定n个类别后,最小化类别中样本到类别均值样本的距离,公式如下:

其中,Ci为划分,ui为每个划分的均值向量,k=n。K-均值是相当于一个小、 全等、 对角协方差矩阵的期望最大化算法。
▲该方法有以下缺点:
- 有个前提:集群是凸和各向同性的。对长条形、流行以及不规则形的集群响应不好。
- 惯性不是归一化的度量:仅仅知道值越低越好。但是在高维空间中,欧几里得距离会有所变化。因此在使用k均值方法前,可以利用PCA算法对数据降维,不仅可缓解这一问题,而且还可以加快计算。
▲k均值的算法如下:(参考周志华老师的《机器学习》:203)
***********************************************************
输入:样本集D={x1,x2,x3,…,xm}
聚类簇数:k
过程:
从D中随机选择k个样本{u1,u2,u3,…,uk}
repeat
令Ci={}(1<=i<=k)
计算每个样本到{u1,u2,u3,…,uk}的距离,将距离最近的加入对应的集合中
计算对应集合的均值向量
更新随机选择的k个样本
until 当前均值样本向量均未更新
输出:划分
***********************************************************
▲理论上k-均值总会收敛(可能收敛于一个局部最小值),这依赖于初始化的质心。因此k-均值算法常常会以不同初始化的质心计算几次。在sklearn中可设置init=kmeans++解决这一问题。
▲n_jobs参数可以实现并行处理。通常需要计算机有多的处理器,当n_jobs=-1时,表示使用全部的处理器,-2时减少一个,以此类推。处理器使用的越多内存消耗越大。
▲下面的例子为:k均值算法在不同数据集上的表现,其中前三个为输入数据不符合前提假设,最后一个为每个集群大小不应的情况。如下图:

相关代码如下:
-
# -*- coding: utf-8 -*-
-
"""
-
Created on Wed Feb 8 14:15:41 2017
-
-
@author: ZQ
-
"""
-
import numpy as np
-
import matplotlib.pyplot as plt
-
-
from sklearn.cluster import KMeans
-
from sklearn.datasets import make_blobs
-
-
plt.figure(figsize=(12,12))
-
-
n_samples = 1500
-
random_state = 170
-
X,y = make_blobs(n_samples=n_samples,random_state=random_state)
-
-
#第一幅图,不正确的聚类参数
-
y_pred = KMeans(n_clusters=2,random_state=random_state).fit_predict(X)
-
plt.subplot(221)
-
plt.scatter(X[:,0],X[:,1],c=y_pred)
-
plt.title("Incorrect Number of Blobs")
-
-
#各向异性数据
-
transformation = [[0.60834549,-0.63667341],[-0.40887718,0.85253229]]
-
X_aniso = np.dot(X,transformation)
-
y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X_aniso)
-
plt.subplot(222)
-
plt.scatter(X_aniso[:,0],X_aniso[:,1],c=y_pred)
-
plt.title("Anisotropicly Distributed Blobs")
-
-
#不同方差
-
X_varied,y_varied = make_blobs(n_samples=n_samples,
-
cluster_std=[1.0,2.5,0.5],
-
random_state=random_state)
-
y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X_varied)
-
-
plt.subplot(223)
-
plt.scatter(X_varied[:,0],X_varied[:,1],c=y_pred)
-
plt.title("Unequal Variance")
-
#不同大小的聚类,选取标签为0的500个。。。。
-
X_filtered = np.vstack((X[y==0][:500],X[y==1][:100],X[y==2][:10]))
-
y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X_filtered)
-
plt.subplot(224)
-
plt.scatter(X_filtered[:,0],X_filtered[:,1],c=y_pred)
-
plt.title("Unevenly Sized Blobs")
-
plt.show()
1.1、Mini Batch K-Means
▲MiniBatchKMeans为k均值算法的变种,可减少收敛时间,但是其结果与标准的k均值算法较差。每次迭代中选取的数据集为原始数据集的子集。
▲该算法主要分为两步:
- 在原始数据集中选取b个样本作为小批量,并将其分配到最近的质心(质心的选取不太清楚,有两种可能,1随机在样本集中选取,2在小批量中选取。不清楚)
- 更新质心
▲虽然说MiniBatchKmeans不如标准的K均值算法,但是其差异很小,如下例子:相关代码可查询http://scikit-learn.org/stable/auto_examples/cluster/plot_mini_batch_kmeans.html
2、 层次聚类(Hierarchical clustering)
▲该聚类算法试图在不同层次对数据集进行划分,从而形成树形的聚类结构。划分方法可采用自上而下和自下而上的方法。

▲AgglomerativeClustering采用自下而上的方法。首先将每个样本作为一个类,然后按照距离度量的方法将其合并到需要的聚类数。根据距离度量方法可分为:Ward方差和最小(距离最小)、complete聚类中最大或最小距离、average平均距离。
▲下面的例子说明了这三个方法的优缺点,该聚类方法具有一定的富集性,选择其中的average较好。如下图:http://scikit-learn.org/stable/auto_examples/cluster/plot_digits_linkage.html

3、DBSCAN
▲该算法通过样本的紧密程度来确定样本的分布,该算法可适用于集群在任何形状的情况下。DBSCAN算法中一个重要的概念为核心样本(具有较高的紧密度)。该算法有两个参数min_samples和eps,高min_samples或者低eps代表着在形成聚类时,需要较高的紧密度。
▲该算法简单的描述:先任意选择数据集中的一个核心对象为“种子”,在由此出发确定相应的聚类簇,在根据给定的领域参数(min_samples,eps)找出所有核心对象,在以任意一个核心对象出发,找出由其密度可达的样本生产聚类簇,直到所有核心对象均被访问为止。(更多参考周志华老师《机器学习》P212)
▲下图为一个例子:使用DBSCAN算法,大圈为找到了核心样本,带颜色的小点位非核心样本,黑色的为异常值。

-
相关代码:
-
# -*- coding: utf-8 -*-
-
"""
-
Created on Sun Feb 12 10:49:05 2017
-
-
@author: ZQ
-
"""
-
-
import numpy as np
-
import matplotlib.pyplot as plt
-
-
from sklearn.cluster import DBSCAN
-
from sklearn import metrics
-
from sklearn.datasets.samples_generator import make_blobs
-
from sklearn.preprocessing import StandardScaler
-
-
#生产数据
-
centers = [[1,1],[-1,-1],[1,-1]]
-
X,labels_true = make_blobs(n_samples=750,
-
centers=centers,
-
cluster_std=0.4,
-
random_state=0)
-
#对数据进行标准化
-
X = StandardScaler().fit_transform(X)
-
-
#计算
-
db = DBSCAN(eps=0.3,min_samples=10).fit(X)
-
core_samples_mask = np.zeros_like(db.labels_,dtype=bool)
-
core_samples_mask[db.core_sample_indices_] = True
-
labels = db.labels_
-
-
n_clusters_ = len(set(labels))-(1 if -1 in labels else 0)
-
-
unique_labels = set(labels)
-
colors = plt.cm.Spectral(np.linspace(0,1,len(unique_labels)))
-
for k,col in zip(unique_labels,colors):
-
if k == -1:
-
col = 'k'
-
class_member_mask = (labels == k)
-
xy = X[class_member_mask & core_samples_mask]
-
plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
-
markeredgecolor='k', markersize=14)
-
-
xy = X[class_member_mask & ~core_samples_mask]
-
plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
-
markeredgecolor='k', markersize=6)
-
-
plt.title('Estimated number of clusters: %d' % n_clusters_)
-
plt.show()
补充:用聚类进行图像分割

-
相关代码:
-
# -*- coding: utf-8 -*-
-
"""
-
Created on Sat Feb 11 11:37:03 2017
-
-
@author: ZQ
-
"""
-
-
import time
-
import scipy as sp
-
import numpy as np
-
import matplotlib.pyplot as plt
-
-
from sklearn.feature_extraction import image
-
from sklearn.cluster import spectral_clustering
-
from sklearn.utils.testing import SkipTest
-
from sklearn.utils.fixes import sp_version
-
-
if sp_version < (0,12):
-
raise SkipTest("Skipping because SciPy version earlier than 0.12.0 and "
-
"thus does not include the scipy.misc.face() image.")
-
face = sp.misc.face(gray=True)
-
-
#减小集合
-
face = sp.misc.imresize(face,0.10)/255
-
-
graph = image.img_to_graph(face)
-
-
#参数beta越小,分割越独立
-
beta = 5
-
eps = 1e-6
-
graph.data = np.exp(-beta*graph.data/graph.data.std())+eps
-
-
N_REGIONS = 25
-
for assign_labels in ('kmeans','discretize'):
-
t0 = time.time()
-
labels = spectral_clustering(graph,n_clusters=N_REGIONS,
-
assign_labels=assign_labels,random_state=1)
-
t1 = time.time()
-
labels = labels.reshape(face.shape)
-
-
plt.figure(figsize=(5,5))
-
plt.imshow(face,cmap=plt.cm.gray)
-
for l in range(N_REGIONS):
-
plt.contour(labels==l,contours=1,
-
colors = [plt.cm.spectral(l/float(N_REGIONS))])
-
plt.xticks(())
-
plt.yticks(())
-
title = 'Spectral clustering: %s, %.2fs' % (assign_labels,(t1-t0))
-
print(title)
-
plt.title(title)
-
plt.show()
-