鸢尾花数据集是非常经典的数据集,常被用来数据挖掘初学者进行数据探索,本文基于鸢尾花数据集分别进行K-均值聚类、层次聚类、DBSCAN(密度聚类),比较这三类算法的区别。
一、K-均值聚类
关于K-均值聚类算法的详细介绍可见《多元统计分析——聚类分析——K-均值聚类(K-中值、K-众数)》。
二、层次聚类
关于层次聚类算法的详细介绍可见《多元统计分析——聚类分析——层次聚类》。
三、DBSCAN(密度聚类)
关于DBSCAN(密度聚类)聚类算法的详细介绍可见《多元统计分析——聚类分析——DBSCAN(基于密度的聚类)》。
本文主要目的是结合数据集探索三者的区别,接下来我们直接上案例。
四、案例:鸢尾花数据集
1、导入数据
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
from sklearn import datasets
from sklearn.decomposition import PCA, FactorAnalysis
iris = datasets.load_iris()
print(iris.data.shape)
输出:
(150, 4)
2、原始数据集PCA降维及可视化
iris_pca = PCA(n_components=2)
iris_pca_score = iris_pca.fit_transform(iris.data)
print(iris_pca.explained_variance_ratio_ )
输出:
[0.92461872 0.05306648]
降成二维能够解释将近98%的方差。我们进一步可视化,查看原始标签下的数据分布:
for cluster, marker in zip(range(3), ['x', 'o', '+']):
x_axis = iris_pca_score[:, 0][iris.target == cluster] #降维之后第一维数据
y_axis = iris_pca_score[:, 1][iris.target == cluster] #降维之后第二维数据
plt.scatter(x_axis, y_axis, marker=marker)
plt.show()
输出:
3、KMeans、DBSCAN、层次聚类效果比较
为了区别不同数据分布(比如噪声)对聚类效果的差异,聚类之前我们不进行降维,我们降维的目的是为了方便绘制图形。
#K-均值
from sklearn.cluster import KMeans
from sklearn.cluster import dbscan
import pandas as pd
import scipy.cluster.hierarchy as sch #层次聚类
import matplotlib.pyplot as plt
fig=plt.figure(figsize=[16, 3])
#原始标签
ax=fig.add_subplot(1,4,1)
for cluster, marker in zip(range(3), ['x', 'o', '+']):
x_axis = iris_pca_score[:, 0][iris.target == cluster] #降维之后第一维数据
y_axis = iris_pca_score[:, 1][iris.target == cluster] #降维之后第二维数据
plt.scatter(x_axis, y_axis, marker=marker)
plt.title('cluster by target')
#KMeans聚类
ax=fig.add_subplot(1,4,2)
iris_kmeans = KMeans(n_clusters=3, n_init=15)
iris_kmeans.fit(iris.data)
for cluster, marker in zip(range(3), ['x', 'o', '+']):
x_axis = iris_pca_score[:, 0][iris_kmeans.labels_ == cluster]
y_axis = iris_pca_score[:, 1][iris_kmeans.labels_ == cluster]
plt.scatter(x_axis, y_axis, marker=marker)
plt.title('cluster by KMeans')
#DBSCAN
ax=fig.add_subplot(1,4,3)
core_samples,cluster_ids = dbscan(iris.data, eps = 0.4, min_samples=4) # eps为邻域半径,min_samples为最少点数目
cluster_ids
for cluster, marker in zip(range(-1,3,1), ['x', 'o', '+','*']):
x_axis = iris_pca_score[:, 0][cluster_ids == cluster]
y_axis = iris_pca_score[:, 1][cluster_ids == cluster]
plt.scatter(x_axis, y_axis, marker=marker)
plt.title('cluster by DBSCAN')
#层次聚类
ax=fig.add_subplot(1,4,4)
Z = sch.linkage(iris.data, method ='ward',metric='euclidean') #euclidean代表欧式距离。
label = sch.cut_tree(Z,n_clusters=3)
A=pd.DataFrame(iris.data,columns=iris.feature_names)
A['label']=label
for cluster, marker in zip(range(3), ['x', 'o', '+']):
x_axis = iris_pca_score[:, 0][A['label'] == cluster]
y_axis = iris_pca_score[:, 1][A['label'] == cluster]
plt.scatter(x_axis, y_axis, marker=marker)
plt.title('cluster by hierarchy')
输出:
4、聚类结果分析
从上面三种聚类效果图可以看出,k-means聚类和层次聚类分析结果大致相同,但是两者与DBSCAN的结果(较多的噪声点)不一样。
层次聚类适用于小样本的聚类,相对于k-means时间复杂度较高,计算较慢。
k-means对于大型数据集也是简单高效、时间复杂度、空间复杂度低。 最重要是数据集大时结果容易局部最优;需要预先设定K值,对最先的K个点选取很敏感;对噪声和离群值非常敏感;只用于numerical类型数据;不能解决非凸数据。
DBSCAN对噪声不敏感;能发现任意形状的聚类。 但是聚类的结果与参数有很大的关系;DBSCAN用固定参数识别聚类,但当聚类的稀疏程度不同时,相同的判定标准可能会破坏聚类的自然结构,即较稀的聚类会被划分为多个类或密度较大且离得较近的类会被合并成一个聚类。