聚类2
上篇文章介绍了聚类算法中基本的k均值聚类算法,然而还有很多种其他的聚类算法
-
密度聚类(DBSCAN)
这种方法的聚类不是以方差最小为衡量标准,而是遵循一个原则,“兄弟的兄弟也是兄弟”,也就是加入A与B距离很近,B与C距离很近,就算A与C距离较远,ABC也是属于同一个簇。这里定义
核心对象:若 x j x_j xj的 ϵ − \epsilon - ϵ−邻域至少包含 M i n P t s MinPts MinPts个样本,即 ∣ N ϵ ( x j ) ∣ ≥ M i n P t s |N_{\epsilon}(x_j)|\geq MinPts ∣Nϵ(xj)∣≥MinPts,则 x j x_j xj是一个核心对象
算法步骤:
- 找出数据集中所有的核心对象构成集合 H H H
- 随机在 H H H选取一个核心对象 x j x_j xj,并加入队列 Q Q Q中,初始化簇集合 Γ = ∅ \Gamma=\emptyset Γ=∅
- 从队列 Q Q Q中取出队首元素$ q , 如 果 ,如果 ,如果q 是 核 心 对 象 , 首 先 将 是核心对象,首先将 是核心对象,首先将q 从 从 从H 中 去 除 , 其 次 将 中去除,其次将 中去除,其次将q 的 的 的\epsilon - 邻 域 里 的 数 据 邻域里的数据 邻域里的数据N_{\epsilon}(q) 加 入 加入 加入Q , 并 将 该 数 据 并 入 集 合 ,并将该数据并入集合 ,并将该数据并入集合\Gamma 中 , 当 然 中,当然 中,当然\Gamma$中的元素需互异
- 若队列 Q Q Q不空,则重复步骤3,若队列 Q Q Q空了,则将 Γ \Gamma Γ生成簇 C k C_k Ck,并重复步骤2,直至 H H H为空
- 最终没有归入任何簇的数据视为噪声样本
有点像从特定点开始的深度优先搜索
密度聚类对噪声点不敏感,并且可以形成不同的形状的簇
from numpy import * import matplotlib.pyplot as plt def loadDataSet(fileName): dataSet = [] fr = open(fileName) for line in fr.readlines(): curLine = line.strip().split('\t') fltLine = map(float,curLine) dataSet.append(list(fltLine)) return mat(dataSet) def dist(vecA,vecB): return sqrt(sum(power(vecA-vecB,2))) def DBSCAN(dataSet,k,epsilon,MinPts): H=[]; k=1; C=[] #H核心对象序列,C储存簇内的点 G = set([tuple(i) for i in dataSet.tolist()]) for data in dataSet: #步骤1 if len([i for i in dataSet if dist(data,i) < epsilon]) >= MinPts: H.append(tuple(data.tolist()[0]))#找出所有核心序列 步骤1 while len(H) > 0: Gold = G o = H[random.randint(0,len(H))] #步骤2 temp = set([]); temp.add(o) G = G - temp #1 同下的2,这个操作是为了避免在队列中加入之前已经遍历过的点 Q = []; Q.append(tuple(o)) #步骤2 while len(Q) > 0: q = Q[0] #步骤3 Nq = [i.tolist()[0] for i in dataSet if dist(i,q) < epsilon] if len(Nq) >= MinPts: #如果是核心对象 H.remove(q) #在核心序列取出该点 S = G & set([tuple(i) for i in Nq]) #S的点是没有遍历过的点 Q += list(S) G = G - S #2 Q.remove(q) #步骤3 k = k + 1 Ck = list(Gold-G) C.append(Ck) return C
-
层次聚类
层次聚类有”自底向上“的聚合策略和“自顶向下”的分拆策略。我们来看看自底向上的聚合策略。就是一开始每个样本属于一个簇,每次找出距离最近的簇并合并这两个簇,待最终的簇数量为k。这里什么是簇的距离呢?
定义两个簇的最短距离 d m i n ( C i , C j ) = m i n x ∈ C i , z ∈ C j d i s t ( x , z ) d_{min}(C_i,C_j)=min_{x\in C_i,z\in C_j}dist(x,z) dmin(Ci,Cj)=minx∈Ci,z∈Cjdist(x,z),即两个簇之间的最近的样本的距离
算法步骤:
- 每个样本归为各自一个簇 C j = C_j= Cj={ x j x_j xj}
- 计算簇距离矩阵 M M M, M ( i , j ) = d m i n ( C i , C j ) M(i,j)=d_{min}(C_i,C_j) M(i,j)=dmin(Ci,Cj),每个元素为第i个簇与第j个簇的最短距离
- 找出距离最近的两个簇 C a C_a Ca和 C b C_b Cb,合并两个簇 C a = C a ∪ C b C_a=C_a\cup C_b Ca=Ca∪Cb,并将位于b后的簇的编号-1
- 更新距离矩阵,即删除第b行和第b列,并重新计算其他簇到 C a C_a Ca的距离
- 重复步骤3,直至最终的簇的数量符合要求
最终会形成一种层次结构