1. 程式人生 > >Canopy算法計算聚類的簇數

Canopy算法計算聚類的簇數

border ans ati double number evel clu 得到 依據

Kmeans算是是聚類中的經典算法。步驟例如以下:
選擇K個點作為初始質心
repeat
將每一個點指派到近期的質心,形成K個簇
又一次計算每一個簇的質心
until 簇不發生變化或達到最大叠代次數

算法中的K須要人為的指定。確定K的做法有非常多,比方多次進行試探。計算誤差。得出最好的K。這樣須要比較長的時間。我們能夠依據Canopy算法來粗略確定K值(能夠覺得相等)。看一下Canopy算法的過程:

技術分享

(1)設樣本集合為S。確定兩個閾值t1和t2,且t1>t2。


(2)任取一個樣本點p。作為一個Canopy,記為C,從S中移除p。


(3)計算S中全部點到p的距離dist


(4)若dist<t1。則將對應點歸到C,作為弱關聯。
(5)若dist<t2。則將對應點移出S,作為強關聯。
(6)反復(2)~(5),直至S為空。

Canopy 個數全然能夠作為這個K值,一定程度上降低了選擇K的盲目性。

以下通過Canopy算法對一些點進行計算Canopy的個數。假設只計算K值,則T1沒有不論什麽作用,之用指定T2就可以。這裏使用全部點的平均距離的一半來作為T2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package cn.edu.ustc.dm.cluster;

import java.util.ArrayList;
import java.util.List;

import cn.edu.ustc.dm.bean.Point;

/**
* Canopy算法 借助canopy算法計算相應的Kmeans中的K值大小
* 當中對於計算K值來說。canopy算法中的T1沒有意義,僅僅用設定T2(T1>T2) 我們這裏將T2設置為平均距離
*
* @author YD
*
*/
public class Canopy {
private List<Point> points = new ArrayList<Point>(); // 進行聚類的點
private List<List<Point>> clusters = new ArrayList<List<Point>>(); // 存儲簇
private double T2 = -1; // 閾值

public Canopy(List<Point> points) {
for (Point point : points)
// 進行深拷貝
this.points.add(point);
}

/**
* 進行聚類,依照Canopy算法進行計算,將全部點進行聚類
*/
public void cluster() {
T2 = getAverageDistance(points);
while (points.size() != 0) {
List<Point> cluster = new ArrayList<Point>();
Point basePoint = points.get(0); // 基準點
cluster.add(basePoint);
points.remove(0);
int index = 0;
while (index < points.size()) {
Point anotherPoint = points.get(index);
double distance = Math.sqrt((basePoint.x - anotherPoint.x)
* (basePoint.x - anotherPoint.x)
+ (basePoint.y - anotherPoint.y)
* (basePoint.y - anotherPoint.y));
if (distance <= T2) {
cluster.add(anotherPoint);
points.remove(index);
} else {
index++;
}
}
clusters.add(cluster);
}
}

/**
* 得到Cluster的數目
*
* @return 數目
*/
public int getClusterNumber() {
return clusters.size();
}

/**
* 獲取Cluster相應的中心點(各點相加求平均)
*
* @return
*/
public List<Point> getClusterCenterPoints() {
List<Point> centerPoints = new ArrayList<Point>();
for (List<Point> cluster : clusters) {
centerPoints.add(getCenterPoint(cluster));
}
return centerPoints;
}

/**
* 得到的中心點(各點相加求平均)
*
* @return 返回中心點
*/
private double getAverageDistance(List<Point> points) {
double sum = 0;
int pointSize = points.size();
for (int i = 0; i < pointSize; i++) {
for (int j = 0; j < pointSize; j++) {
if (i == j)
continue;
Point pointA = points.get(i);
Point pointB = points.get(j);
sum += Math.sqrt((pointA.x - pointB.x) * (pointA.x - pointB.x)
+ (pointA.y - pointB.y) * (pointA.y - pointB.y));
}
}
int distanceNumber = pointSize * (pointSize + 1) / 2;
double T2 = sum / distanceNumber / 2; // 平均距離的一半
return T2;
}

/**
* 得到的中心點(各點相加求平均)
*
* @return 返回中心點
*/
private Point getCenterPoint(List<Point> points) {
double sumX = 0;
double sumY = 0;
for (Point point : points) {
sumX += point.x;
sumY += point.y;
}
int clusterSize = points.size();
Point centerPoint = new Point(sumX / clusterSize, sumY / clusterSize);
return centerPoint;
}

/**
* 獲取閾值T2
*
* @return 閾值T2
*/
public double getThreshold() {
return T2;
}

/**
* 測試9個點。進行操作
* @param args
*/
public static void main(String[] args) {
List<Point> points = new ArrayList<Point>();
points.add(new Point(0, 0));
points.add(new Point(0, 1));
points.add(new Point(1, 0));

points.add(new Point(5, 5));
points.add(new Point(5, 6));
points.add(new Point(6, 5));

points.add(new Point(10, 2));
points.add(new Point(10, 3));
points.add(new Point(11, 3));

Canopy canopy = new Canopy(points);
canopy.cluster();

//獲取canopy數目
int clusterNumber = canopy.getClusterNumber();
System.out.println(clusterNumber);

//獲取canopy中T2的值
System.out.println(canopy.getThreshold());
}
}

以上代碼是對9個點使用Canopy算法進行計算,獲取Canopy數目,也即K。


很多其它文章請前往小胖軒.

Canopy算法計算聚類的簇數