——“聚类:经典的无监督学习方法”
(1) 聚类的基本概念
(2) 聚类的基本方法
基于距离的划分方法
给定一个 n n 个对象的集合,划分方法构建数据的 k k 个划分。大部分的划分方法是基于距离的,首先给定要构建的分区数 k k 构建一个初始划分。通过不断迭代,使得同一簇中的对象尽可能接近,不同簇中的对象尽可能远离。最终达到稳定状态。典型的这类方法有: k k -均值和 k k -中心点的启发式算法,能够逼近局部最优。
基于层次的方法
层次方法分为凝聚和分裂。凝聚:自底向上,开始将每个对象作为单独的一个组,然后逐渐合并相近的组,直到所有的组合并为一个组(或者满足某个终止条件)。分裂:自顶向下,开始将所有对象置于一个簇中,每次相继迭代,划分更小的簇,最终每个对象单独在一个簇中。
基于密度的方法
考虑“邻域”中的密度(对象或数据点的数目),超过某个阈值,就继续增长给定的簇。基于密度的聚类方法,可以用来过滤噪声和离群点,能够发现任意形状的簇。
基于网格的方法
把对象空间化为有限个单元形成一个网格结构。聚类操作在网格上进行。处理速度快,因为其处理时间独立于数据对象的个数,仅依赖于量化空间每一维的单元数。
总结:
(1) 算法的主要思想和原理
算法的目标
假设数据集 D D 包含 n n 个欧式空间中的对象。算法将 n n 个对象分配到 k k 个簇 C1,...,Ck C 1 , . . . , C k 中,使得对于 1≤i,j≤k,Ci⊂D且Ci∩Cj=∅ 1 ≤ i , j ≤ k , C i ⊂ D 且 C i ∩ C j = ∅ 。用一个目标函数评估划分的质量,使得簇内对象相似,簇间对象相异。
评价(目标)函数
k k -means取簇 Ci C i 中对象的均值为中心点 ci c i 代表该簇,对象 p p 与其簇的代表 ci c i 之差为 dist(p,ci) d i s t ( p , c i ) 度量,其中 dist(x,y) d i s t ( x , y ) 表示两个点之间的欧式距离。算法划分 k k 个簇的质量可用数据集中所有对象与所属簇中心的距离之和度量定义为:
算法策略
要想求出全局最优解,需要穷举出所有可能的划分,比较目标函数。即使在2维空间内,穷举法也是个N-P难问题。如果簇数为 k k 维度为 d d ,则穷举法对 n n 个对象求出最佳的 k k 个划分的时间复杂度为 O(ndk+1logn) O ( n d k + 1 log n ) 。这个开销是很大的,为了克服这个问题,通常采用贪心算法的策略。
(2) 算法的主要过程
(3) 算法的评价
(1) 算法的主要思想和原理
(2) 算法的主要过程
(3) 算法的评价
一种类似于生物的门科种属分类的层次划分聚类。
(1) 算法的原理的思想(以凝聚法为例)
(2) 算法采取的距离度量
基于层次的聚类算法一个核心的问题是度量两个簇之间的距离,目前有4个广泛使用的簇间距离度量方法。
假设两个对象 p p 和 p′ p ′ 之间的距离为 |p−p′| | p − p ′ | , mi m i 是簇 Ci C i 的均值, ni n i 为簇 Ci C i 中对象的数目。则两个簇 Ci C i 和 Cj C j 之间的距离度量有以下几种:
几点说明:
1. DBSCAN算法基本原理和思想
(1) 基本概念
(2) 密度可达和密度相连
(3) 簇的发现
2. DBSCAN算法主要过程
3. DBSCAN算法复杂度分析
(1) 评估聚类趋势
计算霍普金斯统计量
(2) 确定簇数
肘方法
还可以通过交叉验证的方法确定数据集中正确的簇数。
(3) 评估聚类质量
BCubed精度和召回率(外在方法)
设 D=o1,...,on D = o 1 , . . . , o n 是对象的集合, C C 是 D D 中的一个聚类。设 L(oi) L ( o i ) 是基准确定的 oi o i 的类别, C(oi) C ( o i ) 是 C C 中的簇标号。对于两个对象 oi o i 和 oj o j 在聚类 C C 中的关系的正确性由下式给出:
轮廓系数(内在方法)
对于含有 n n 个对象的数据集 D D ,假设能被划分为 k k 个簇 C1,...,Ck C 1 , . . . , C k 。对于 D D 中的每个对象 o o :
——“挑几个算法偶尔码码”
(1) 实现过程
(2) 主要代码
# -*- coding: utf-8 -*-
__author__ = "Yunfan Yang"
import numpy as np
import matplotlib.pyplot as plt
import random
def generate_data():
"""生成数据"""
# 产生3个2维高斯分布
mean0 = [0,1] # 第1个二维高斯均值、协方差矩阵
cov0 = [[0.8,0],[0,0.6]]
np.random.seed(0) # 设置随机种子为0
norm0 = np.random.multivariate_normal(mean0,cov0, 100)
mean1 = [3,5] # 第2个二维高斯均值、协方差矩阵
cov1 = [[0.6,0],[0,0.8]]
np.random.seed(1) # 设置随机种子为1
norm1 = np.random.multivariate_normal(mean1,cov1, 100)
mean2 = [4,1] # 第3个二维高斯均值、协方差矩阵
cov2 = [[0.6,0],[0,0.6]]
np.random.seed(2) # 设置随机种子为2
norm2 = np.random.multivariate_normal(mean2,cov2, 100)
norm_data = list(norm0) + list(norm1) + list(norm2)
DataSet = []
for i in range(len(norm_data)):
temp_tuple = (round(norm_data[i][0], 4), round(norm_data[i][1],4))
DataSet.append(temp_tuple)
return DataSet
def dist(A, B):
"""计算两点之间的欧几里得距离"""
Ojld = np.sqrt(np.square(A[0]-B[0]) + np.square(A[1]-B[1]))
Ojld = round(Ojld, 2)
return Ojld
def clustering(DataSet):
"""进行聚类"""
k_means = [(0, 0), (0, 0), (0, 0)]
# random.seed(2)
tk = random.sample(DataSet, 3) # 从数据集中随机抽取三个点作为初始簇中心
k_new_means = tk[:]
while k_new_means != k_means: # 判断终止条件:簇中心不再发生改变
CopyDataSet = {} # 这里将数据集转化为字典形式,便于后续的删除数据点操作,批量删除列表元素太麻烦了。。
for i in range(len(DataSet)):
CopyDataSet[i] = DataSet[i]
k=0
Clusters = {}
while(k < 3):
distance_list = {}
for key,value in CopyDataSet.items():
temp_dist = dist(k_new_means[k], value) # 计算第一个簇中心与数据集中所有点的距离
distance_list[key]=temp_dist
sort_distance1 = sorted(distance_list.items(),reverse=False,key=lambda x:x[1]) # 按照距离从小到大排列
sub_cluster = [] # 创建子簇
for i in range(100): # 贪心法取前100个距离返回下标作为第一个簇的数据点下标
index = sort_distance1[i][0]
temp_tuple = CopyDataSet[index]
sub_cluster.append(temp_tuple)
CopyDataSet.pop(index) # 从数据集的副本中剔除已形成簇的数据点
Clusters[k] = sub_cluster
k+=1
k_means = k_new_means[:]
for k, cluster in Clusters.items(): # 计算新一轮的簇中心
x_sum = 0
y_sum = 0
for data_dot in cluster:
x_sum += data_dot[0]
y_sum += data_dot[1]
k_mean = (round((x_sum / 100),4), round(y_sum / 100,4))
k_new_means[k] = k_mean
return Clusters
def data_visual(DataSet,Clusters):
"""绘制原始数据点和簇"""
x = []
y = []
for value in DataSet:
x.append(value[0])
y.append(value[1])
# plt.style.use('ggplot')
fig1 = plt.figure()
ax1 = fig1.add_subplot(111)
# for spine in ['left', 'bottom']:
# ax1.spines[spine].set_position('zero') # 将坐标轴移动至原点
ax1.spines['right'].set_visible(False) # 右边框不可见
ax1.spines['top'].set_color('none') # 上边框不可见
ax1.plot(x,y, 'o', c='blue', alpha=0.5, markersize=5)
ax1.axis('equal')
ax1.grid(True, color='black', linewidth=0.2, linestyle='-.')
color_list = ['r','g','b']
fig2 = plt.figure()
ax2 = fig2.add_subplot(111)
for k,cluster in Clusters.items(): # 绘出每个簇的数据点
x_k = []
y_k = []
for data_dot in cluster:
x_k.append(data_dot[0])
y_k.append(data_dot[1])
ax2.plot(x_k,y_k,'o',c=color_list[k], alpha=0.7,markersize=5)
ax2.spines['right'].set_visible(False) # 右边框不可见
ax2.spines['top'].set_color('none') # 上边框不可见
ax2.axis('equal')
ax2.grid(True, color='black', linewidth=0.2, linestyle='-.')
plt.show()
if __name__ == "__main__":
DataSet = generate_data() # 产生3个二维随机高斯分布的原始数据集
Clusters = clustering(DataSet) # 对原始数据集进行聚类
data_visual(DataSet,Clusters) # 绘图
(3) 运行结果
(1) 问题简述
(2) R代码
#### 输入原始距离数据
x<- c(0, 662, 877, 225, 412, 996,
662, 0, 295, 468, 268, 400,
877, 295, 0, 754, 564, 138,
255, 468, 754, 0, 219, 869,
412, 268, 564, 219, 0, 669,
996, 400, 138, 869, 669, 0)
y<-x/(max(x)-min(x)) # 数据归一化
names<-c("BA","FI","MI","NA","RM","TO")
r<-matrix(y, nrow=6, ncol=6, dimnames=list(names, names)) # 将数据转化为矩阵
#### 聚类分析
#### 函数dist()将普通矩阵转化为聚类分析用的距离结构
d<-dist(r); hc<-hclust(d); dend<-as.dendrogram(hc)
#用四种不同的距离方法生成系统聚类
hc1<-hclust(d, "single"); hc2<-hclust(d, "complete") #最短距离法和最长距离法
hc3<-hclust(d, "median"); hc4<-hclust(d, "average") #中间距离法和平均距离法
#绘制出以上四种方法的树形结构图,并以2x2的形式画在一张图上.图像距离边界的距离
opar <- par(mfrow = c(2, 2))
#hang是表明谱系图中各类所在的位置 当hang取负值时,谱系图中的类从底部画起 生成谱系图
plot(hc1,hang=-1); plot(hc2,hang=-1)
plot(hc3,hang=-1); plot(hc4,hang=-1)
par(opar)