聚类算法---kmeans以及DBSCAN算法

一、聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法,同时也是数据挖掘的一个重要算法。
聚类(Cluster)分析是由若干模式(Pattern)组成的,通常,模式是一个度量(Measurement)的向量,或者是 多维空间中的一个点。
聚类分析以相似性为基础,在一个聚类中的模式之间比不在同一聚类中的模式之间具有更多的相似性。
 

二、聚类算法分类
1.基于划分
给定一个有N个元组或者纪录的数据集,分裂法将构造K个分组,每一个分组就代表一个聚类,K<N。
特点:计算量大。很适合发现中小规模的数据库中小规模的数据库中的球状簇。
算法:K-MEANS算法、K-MEDOIDS算法、CLARANS算法

2.基于层次
对给定的数据集进行层次似的分解,直到某种条件满足为止。具体又可分为“自底向上”和“自顶向下”两种方案。
特点:较小的计算开销。然而这种技术不能更正错误的决定。
算法:BIRCH算法、CURE算法、CHAMELEON算法

3.基于密度
只要一个区域中的点的密度大过某个阈值,就把它加到与之相近的聚类中去。
特点:能克服基于距离的算法只能发现“类圆形”的聚类的缺点。
算法:DBSCAN算法、OPTICS算法、DENCLUE算法

4.基于网格
将数据空间划分成为有限个单元(cell)的网格结构,所有的处理都是以单个的单元为对象的。
特点:处理速度很快,通常这是与目标数据库中记录的个数无关的,只与把数据空间分为多少个单元有关。
算法:STING算法、CLIQUE算法、WAVE-CLUSTER算法
---------------------

三、度量指标

 


算法步骤及代码实现

1. K-Means(K均值)聚类

算法步骤:
(1) 首先我们选择一些类/组,并随机初始化它们各自的中心点。中心点是与每个数据点向量长度相同的位置。这需要我们提前预知类的数量(即中心点的数量)。
(2) 计算每个数据点到中心点的距离,数据点距离哪个中心点最近就划分到哪一类中。
(3) 计算每一类中中心点作为新的中心点。
(4) 重复以上步骤,直到每一类中心在每次迭代后变化不大为止。也可以多次随机初始化中心点,然后选择运行结果最好的一个。
下图演示了K-Means进行分类的过程:
---------------------

优点:
速度快,计算简便
缺点:
我们必须提前知道数据有多少类/组。
K-Medians是K-Means的一种变体,是用数据集的中位数而不是均值来计算数据的中心点。
K-Medians的优势是使用中位数来计算中心点不受异常值的影响;缺点是计算中位数时需要对数据集中的数据进行排序,速度相对于K-Means较慢。
---------------------

肘部法则
如果问题中没有指定k的值,可以通过肘部法则这一技术来估计聚类数量。肘部法则会把不同k值的成本函数值画出来。随着kk值的增大,平均畸变程度会减小;每个类包含的样本数会减少,于是样本离其重心会更近。但是,随着k值继续增大,平均畸变程度的改善效果会不断减低。k值增大过程中,畸变程度的改善效果下降幅度最大的位置对应的k值就是肘部。为了让读者看的更加明白,下面让我们通过一张图用肘部法则来确定最佳的kk值。下图数据明显可分成两类:


  1 import random
  2 from sklearn import datasets
  3 import numpy as np
  4 import matplotlib.pyplot as plt
  5 from mpl_toolkits.mplot3d import Axes3D
  6 %matplotlib inline
  7 
  8 
  9 # 正规化数据集 X
 10 def normalize(X, axis=-1, p=2):
 11     lp_norm = np.atleast_1d(np.linalg.norm(X, p, axis))
 12     lp_norm[lp_norm == 0] = 1
 13     return X / np.expand_dims(lp_norm, axis)
 14 
 15 
 16 # 计算一个样本与数据集中所有样本的欧氏距离的平方
 17 def euclidean_distance(one_sample, X):
 18     one_sample = one_sample.reshape(1, -1)
 19     X = X.reshape(X.shape[0], -1)
 20     distances = np.power(np.tile(one_sample, (X.shape[0], 1)) - X, 2).sum(axis=1)
 21     return distances
 22 
 23 
 24 
 25 class Kmeans():
 26     """Kmeans聚类算法.
 27 
 28     Parameters:
 29     -----------
 30     k: int
 31         聚类的数目.
 32     max_iterations: int
 33         最大迭代次数. 
 34     varepsilon: float
 35         判断是否收敛, 如果上一次的所有k个聚类中心与本次的所有k个聚类中心的差都小于varepsilon, 
 36         则说明算法已经收敛
 37     """
 38     def __init__(self, k=2, max_iterations=500, varepsilon=0.0001):
 39         self.k = k
 40         self.max_iterations = max_iterations
 41         self.varepsilon = varepsilon
 42 
 43     # 从所有样本中随机选取self.k样本作为初始的聚类中心
 44     def init_random_centroids(self, X):
 45         n_samples, n_features = np.shape(X)
 46         centroids = np.zeros((self.k, n_features))
 47         for i in range(self.k):
 48             centroid = X[np.random.choice(range(n_samples))]
 49             centroids[i] = centroid
 50         return centroids
 51 
 52     # 返回距离该样本最近的一个中心索引[0, self.k)
 53     def _closest_centroid(self, sample, centroids):
 54         distances = euclidean_distance(sample, centroids)
 55         closest_i = np.argmin(distances)
 56         return closest_i
 57 
 58     # 将所有样本进行归类,归类规则就是将该样本归类到与其最近的中心
 59     def create_clusters(self, centroids, X):
 60         n_samples = np.shape(X)[0]
 61         clusters = [[] for _ in range(self.k)]
 62         for sample_i, sample in enumerate(X):
 63             centroid_i = self._closest_centroid(sample, centroids)
 64             clusters[centroid_i].append(sample_i)
 65         return clusters
 66 
 67     # 对中心进行更新
 68     def update_centroids(self, clusters, X):
 69         n_features = np.shape(X)[1]
 70         centroids = np.zeros((self.k, n_features))
 71         for i, cluster in enumerate(clusters):
 72             centroid = np.mean(X[cluster], axis=0)
 73             centroids[i] = centroid
 74         return centroids
 75 
 76     # 将所有样本进行归类,其所在的类别的索引就是其类别标签
 77     def get_cluster_labels(self, clusters, X):
 78         y_pred = np.zeros(np.shape(X)[0])
 79         for cluster_i, cluster in enumerate(clusters):
 80             for sample_i in cluster:
 81                 y_pred[sample_i] = cluster_i
 82         return y_pred
 83 
 84     # 对整个数据集X进行Kmeans聚类,返回其聚类的标签
 85     def predict(self, X):
 86         # 从所有样本中随机选取self.k样本作为初始的聚类中心
 87         centroids = self.init_random_centroids(X)
 88 
 89         # 迭代,直到算法收敛(上一次的聚类中心和这一次的聚类中心几乎重合)或者达到最大迭代次数
 90         for _ in range(self.max_iterations):
 91             # 将所有进行归类,归类规则就是将该样本归类到与其最近的中心
 92             clusters = self.create_clusters(centroids, X)
 93             former_centroids = centroids
 94 
 95             # 计算新的聚类中心
 96             centroids = self.update_centroids(clusters, X)
 97 
 98             # 如果聚类中心几乎没有变化,说明算法已经收敛,退出迭代
 99             diff = centroids - former_centroids
100             if diff.any() < self.varepsilon:
101                 break
102 
103         return self.get_cluster_labels(clusters, X)
104 
105 
106 def main():
107     # Load the dataset
108     X, y = datasets.make_blobs(n_samples=10000, 
109                                n_features=3, 
110                                centers=[[3,3, 3], [0,0,0], [1,1,1], [2,2,2]], 
111                                cluster_std=[0.2, 0.1, 0.2, 0.2], 
112                                random_state =9)
113 
114     # 用Kmeans算法进行聚类
115     clf = Kmeans(k=4)
116     y_pred = clf.predict(X)
117 
118 
119     # 可视化聚类效果
120     fig = plt.figure(figsize=(12, 8))
121     ax = Axes3D(fig, rect=[0, 0, 1, 1], elev=30, azim=20)
122     plt.scatter(X[y==0][:, 0], X[y==0][:, 1], X[y==0][:, 2])
123     plt.scatter(X[y==1][:, 0], X[y==1][:, 1], X[y==1][:, 2])
124     plt.scatter(X[y==2][:, 0], X[y==2][:, 1], X[y==2][:, 2])
125     plt.scatter(X[y==3][:, 0], X[y==3][:, 1], X[y==3][:, 2])
126     plt.show()
127 
128 
129 if __name__ == "__main__":
130     main()

 


2.DBSCAN也是基于密度的聚类算法,与均值漂移聚类类似

具体步骤:
1. 首先确定半径r和minPoints(数目). 从一个没有被访问过的任意数据点开始,以这个点为中心,r为半径的圆内包含的点的数量是否大于或等于minPoints,如果大于或等于minPoints则改点被标记为central point,反之则会被标记为noise point。
2. 重复1的步骤,如果一个noise point存在于某个central point为半径的圆内,则这个点被标记为边缘点,反之仍为noise point。重复步骤1,知道所有的点都被访问过。

在DBSCAN算法中将数据点分为一下三类: 
核心点:在半径Eps内含有超过MinPts数目的点 
边界点:在半径Eps内点的数量小于MinPts,但是落在核心点的邻域内 
噪音点:既不是核心点也不是边界点的点 


优点:不需要知道簇的数量
缺点:需要确定距离r和minPoints

 1 import numpy as np
 2 
 3 from sklearn.cluster import DBSCAN
 4 from sklearn import metrics
 5 from sklearn.datasets.samples_generator import make_blobs
 6 from sklearn.preprocessing import StandardScaler
 7 
 8 
 9 ##############################################################################
10 # Generate sample data
11 centers = [[1, 1], [-1, -1], [1, -1]]
12 X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4,
13                             random_state=0)
14 
15 X = StandardScaler().fit_transform(X)
16 
17 ##############################################################################
18 # Compute DBSCAN
19 db = DBSCAN(eps=0.3, min_samples=10).fit(X)
20 core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
21 core_samples_mask[db.core_sample_indices_] = True
22 labels = db.labels_
23 
24 # Number of clusters in labels, ignoring noise if present.
25 n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
26 
27 print('Estimated number of clusters: %d' % n_clusters_)
28 print("Homogeneity: %0.3f" % metrics.homogeneity_score(labels_true, labels))
29 print("Completeness: %0.3f" % metrics.completeness_score(labels_true, labels))
30 print("V-measure: %0.3f" % metrics.v_measure_score(labels_true, labels))
31 print("Adjusted Rand Index: %0.3f"
32       % metrics.adjusted_rand_score(labels_true, labels))
33 print("Adjusted Mutual Information: %0.3f"
34       % metrics.adjusted_mutual_info_score(labels_true, labels))
35 print("Silhouette Coefficient: %0.3f"
36       % metrics.silhouette_score(X, labels))
37 
38 ##############################################################################
39 # Plot result
40 import matplotlib.pyplot as plt
41 
42 # Black removed and is used for noise instead.
43 unique_labels = set(labels)
44 colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
45 for k, col in zip(unique_labels, colors):
46     if k == -1:
47         # Black used for noise.
48         col = 'k'
49 
50     class_member_mask = (labels == k)
51 
52     xy = X[class_member_mask & core_samples_mask]
53     plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
54              markeredgecolor='k', markersize=14)
55 
56     xy = X[class_member_mask & ~core_samples_mask]
57     plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
58              markeredgecolor='k', markersize=6)
59 
60 plt.title('Estimated number of clusters: %d' % n_clusters_)
61 plt.show()

            黑色的点代表离群点或者叫噪声点

 


 3.层次聚类

层次聚类算法分为两类:自上而下和自下而上。凝聚层级聚类(HAC)是自下而上的一种聚类算法。HAC首先将每个数据点视为一个单一的簇,然后计算所有簇之间的距离来合并簇,知道所有的簇聚合成为一个簇为止。 

度量方法:

算法步骤:

1. 首先我们将每个数据点视为一个单一的簇,然后选择一个测量两个簇之间距离的度量标准。例如我们使用average linkage作为标准,它将两个簇之间的距离定义为第一个簇中的数据点与第二个簇中的数据点之间的平均距离。
2. 在每次迭代中,我们将两个具有最小average linkage的簇合并成为一个簇。
3. 重复步骤2知道所有的数据点合并成一个簇,然后选择我们需要多少个簇。
层次聚类优点:(1)不需要知道有多少个簇
(2)对于距离度量标准的选择并不敏感
缺点:效率低
---------------------

 1 import numpy as np
 2 import pandas as pd
 3 from sklearn.cluster import AgglomerativeClustering
 4 import matplotlib.pyplot as plt
 5 import numpy as np
 6 from scipy import ndimage
 7 from matplotlib import pyplot as plt
 8 from sklearn import manifold, datasets
 9 
10 
11 # In[2]:
12 #1797个样本,每个样本包括8*8像素的图像和一个[0, 9]整数的标签
13 digits = datasets.load_digits(n_class=10)#手写字体数据集,
14 X = digits.data
15 y = digits.target
16 n_samples, n_features = X.shape
17 print(digits.keys())
18 print X[:5,:]
19 print n_samples,n_features
20 
21 
22 # In[3]:
23 
24 # Visualize the clustering
25 def plot_clustering(X_red, X, labels, title=None):
26     x_min, x_max = np.min(X_red, axis=0), np.max(X_red, axis=0)
27     X_red = (X_red - x_min) / (x_max - x_min)
28 
29     plt.figure(figsize=(6, 4))
30     for i in range(X_red.shape[0]):
31         plt.text(X_red[i, 0], X_red[i, 1], str(y[i]),
32                  color=plt.cm.spectral(labels[i] / 10.),
33                  fontdict={'weight': 'bold', 'size': 9})
34 
35     plt.xticks([])
36     plt.yticks([])
37     if title is not None:
38         plt.title(title, size=17)
39     plt.axis('off')
40     plt.tight_layout()
41 
42 
43 # In[ ]:
44 
45 # 2D embedding of the digits dataset
46 print("Computing embedding")
47 X_red = manifold.SpectralEmbedding(n_components=2).fit_transform(X)
48 print("Done.")
49 
50 from sklearn.cluster import AgglomerativeClustering
51 
52 for linkage in ('ward', 'average', 'complete'):
53     clustering = AgglomerativeClustering(linkage=linkage, n_clusters=10)
54     clustering.fit(X_red)
55     plot_clustering(X_red, X, clustering.labels_, "%s linkage" % linkage)
56 
57 
58 plt.show()

 

 

 上图显示层次聚类采用不同距离度量方法的效果,complete在此数据集上效果较差。

 

 

转载于:https://www.cnblogs.com/daliner/p/9887640.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值