基本概念:(Density-Based Spatial Clustering of Applications with Noise)
核心对象:若某个点的密度达到算法设定的阈值则其为核心点(即r领域内点的数量不小于minPts)
领域的距离阈值:设定的半径r
直接密度可达:若某点p在点q的r领域内,且q是核心点则p-q直接密度可达
密度可达:若有一个点的序列q0,q1,…,qk,对任意qi-qi-1是直接密度可达的,则称从q0到qk密度可达,这实际上是直接密度可达的传播
工作流程:
参数D:输入数据集
参数:指定半径
MinPts:密度阈值
1.标记所有对象为unvisited
2.Do
3.随机选择一个unvisited对象p
4.标记p为visited
5.If p的领域至少有MinPts个对象
6. 创建一个新簇C,并把p添加到C
7. 令N为p的领域中的对象集合
8. For N中每个点p
9. If p是unvisited
10. 标记p为visited
11. if p的领域至少有MinPts个对象,把这些对象添加到N
12. 如果p还不是任何簇的成员,把p添加到C
13. End for
14. 输出C
15.Else标记p为噪声
16.Until没有标记为unvisited的对象
参数选择:
半径,可以根据K距离来设定:找突变点
K距离:给定数据集P={p(i);i=0,1,…n},计算点P(i)到集合D的子集S中所有点之间的距离,距离按照从小到大的顺序排序,d(k)就被称为k距离
MinPts:k-距离中k的值,一般取小一些,多次尝试
优势:
不需要指定簇的个数
可以发现任意形状的簇
擅长找到离群点(检测任务)
两个参数就够了
劣势:
高维数据有些困难(可以做降维)
参数难以选择(参数对结果的影响非常大)
Sklearn中效率很慢(数据削减策略)
聚类案例实战
In[1]: import pandas as pd
beer = pd.read_csv('data.txt', sep=' ')
# 原本的数据很密集,sep参数可以让它们分开
beer
In[2]: X = beer[['calories', 'sodium', 'alcohol', 'cost']]
# 取出所有特征列,聚类是无监督算法,没有标签
用K-means方法来做(K-means clustering)
In[3]: from sklearn.cluster import KMeans
km = KMeans(n_clusters=3).fit(X)
km2 = KMeans(n_clusters=2).fit(X)
# n_clusters参数是指定分成多少个簇
In[4]: km.labels_
# 分好类的标签
In[5]: beer['cluster'] = km.labels_
beer['cluster2'] = km2.labels_
# 增加两列标签列
beer.sort_values(