Canopy算法是一种快速的预聚类算法
,主要用于大规模数据集的初步处理
,它可以显著减少
更复杂或更精确的聚类算法(如K-means)的计算成本。
Canopy算法通过使用两个阈值
T1 和 T2 来创建数据点的“遮盖”或“保护伞”,其中T1 > T2。
Canopy算法的主要步骤:
- 初始化:
将所有数据点放入一个列表中。
- 选择阈值:定义
两个阈值
T1 和 T2,T1用于创建canopy
,而 T2 用于决定数据点是否应被排除在未来的canopy之外。
- 创建Canopy:
- 随机选择一个
未处理的数据点
作为Canopy的中心。
- 对于列表中的
每个其他
数据点:
- 如果
它与中心的距离小于
T1,则将其添加
到Canopy中。 - 如果
它与中心的距离小于
T2 ,则从列表中移除
此点,防止其成为另一个Canopy的中心。
公式:
Canopy算法并不涉及复杂的数学公式,而是依赖于距离度量
。假设我们有数据点 p
和中心点 c
,以及它们之间的某种距离度量 d(p, c)
。
距离度量公式:
这里的d(p, c)
代表点p
与点c
之间的欧氏距离
其中
和
分别是
p
和c
在第i
维上的坐标值。-
n
是数据点的维度数
。
-
p
:一个数据点。
-
c
:一个中心点。
-
i
:维度索引,从1到n
。 -
n
:数据点的总维度数。
:数据点
p
在第i
维的坐标。:中心点
c
在第i
维的坐标。:平方运算符。
:平方根运算符。
:求和符号,表示对所有
i
从1到n
的项求和。
阈值判断:
在算法中,对于每个数据点p
,如果 d(p, c) < T1
,则 p
属于 c
的Canopy。如果 d(p, c) < T2
,则 p
将被从列表中移除。
Canopy算法的优势:
- 快速:使用简单的距离度量和阈值,
可以快速处理大量数据。
- 减少计算:通过预先筛选数据点,
减少需要进行更复杂聚类算法的数据量。
Canopy算法的局限性:
-
精确度
:由于使用了近似
的距离度量和阈值,结果可能不如更精确的算法准确。 -
参数选择
:T1 和 T2 的选择可能影响最终结果的质量。
例子
通过例子来进一步理解Canopy算法的工作原理。我们将使用一组简单的二维数据点,并手动执行算法的每一步。
示例数据点:
假设我们有以下六个二维数据点:
A: (1.0, 1.5)
B: (1.5, 2.0)
C: (0.5, 0.7)
D: (6.0, 7.5)
E: (5.5, 7.0)
F: (5.5, 4.5)
设置阈值:
设T1 = 1.0
和 T2 = 0.5
。
手动执行Canopy算法:
第一步:创建第一个Canopy
- 随机选择一个点作为中心,假设我们选择点
A
。 - 计算点
A
与其他所有点的距离。 - 将距离小于
T1
的所有点添加到Canopy中。同时,将距离小于
T2的点标记为不可再次作为中心点
。
T1 = 1.0
和 T2 = 0.5
-
A -> B
: 0.5 (加入Canopy, 标记B) -
A -> C
: 0.82 (加入Canopy) -
A -> D
: 8.54 (不加入) -
A -> E
: 8.06 (不加入) -
A -> F
: 4.03 (不加入)
第二步:更新数据点列表
- 已经加入Canopy A的点:
A
,B
,C
。 - 移除不可再次作为中心点的点:
B
。
第三步:重复以上步骤直到所有点都被处理
- 假设下一个随机选择的点是
D
。 - 计算点
D
与其他所有点的距离。 - 将距离小于
T1
的所有点添加到Canopy中。同时,将距离小于T2
的点标记为不可再次作为中心点。
T1 = 1.0
和 T2 = 0.5
-
D -> E
: 0.5 (加入Canopy, 标记E) -
D -> F
: 3.0 (不加入Canopy)
结果
最终,我们得到了两个Canopy:
- Canopy 1:
{A, B, C}
- Canopy 2:
{D, E, F}
- Canopy 3:
{F}
Python代码示例
以下是上述示例的Python代码实现:
import numpy as np
# 欧几里得距离函数
def euclidean_distance(p1, p2):
return np.linalg.norm(np.array(p1) - np.array(p2))
# Canopy聚类函数
def canopy_clustering(points, T1, T2):
canopies = []
covered_points = set() # 用于存储已经被某个Canopy覆盖的点
while points:
center = points[0]
canopy = [center]
points.remove(center)
for i, point in enumerate(points[:]):
dist = euclidean_distance(center, point)
if dist < T1:
if point not in covered_points:
canopy.append(point)
covered_points.add(point)
points.remove(point)
elif dist < T2:
covered_points.add(point)
canopies.append(canopy)
return canopies
# 定义数据点
data_points = [(1.0, 1.5), (1.5, 2.0), (0.5, 0.7), (6.0, 7.5), (5.5, 7.0), (5.5, 4.5)]
# 设置阈值
T1 = 1.0
T2 = 0.5
# 执行Canopy算法
result = canopy_clustering(data_points, T1, T2)
print("Canopies:", result)
'''
Canopies: [
[(1.0, 1.5), (1.5, 2.0), (0.5, 0.7)],
[(6.0, 7.5), (5.5, 7.0)],
[(5.5, 4.5)]
]
'''
这段代码将输出两个Canopy,每个包含一组数据点,与我们的手动计算结果相匹配。这有助于直观地理解Canopy算法是如何工作的。