JS写一遍K-means

数据可视化用的highcharts.

运行结果:

upload successful

在html头部加上highcharts的cdn

1
2
3
4
<script type="text/javascript" src="http://cdn.hcharts.cn/jquery/jquery-1.8.3.min.js">
</script>
<script type="text/javascript" src="http://cdn.hcharts.cn/highcharts/highcharts.js">
</script>

数据如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
{
name: 'Female',
color: 'rgba(223,83,83,.5)',
data: [[161.2, 51.6],[167.5, 59.0],[159.5, 49.2],
[157.0, 63.0],[155.8, 53.6]...]
},
{
name: 'Male',
color: 'rgba(119,152,191,.5)',
data: [[174.0, 65.6],[175.3, 71.8],[193.5, 80.7],
[186.5, 72.6],[187.2, 78.8]...]
}
]

共有507个样本的身高与体重数据,标签分为男女。

====代码====

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
var Dot_1, Dot_2, temp_group_1, temp_group_2 = new Array;
var temp_data
var dataTotel = hasntlabel_data.length;
var TempDot = [0, 0];
random_dot();
initgroup();
k_means()
//主要代码
function init() { //初始化
group_1 = [];
group_2 = [];
console.log("init") for (var i = 0; i < dataTotel; i++) {
distance(Dot_1,hasntlabel_data[i])>distance(Dot_2,hasntlabel_data[i])?
group_2.push(hasntlabel_data[i]):group_1.push(hasntlabel_data[i]);
}
}
function random_dot() { //随机定两个点
Dot_1=[Math.random()*7,Math.random()*7]Dot_2=[Math.random()*7,Math.random()*7]
}
function k_means() {
console.log(group_1.length + ',' + group_2.length);
if (!group_1.length || !group_2.length) {
random_dot();
init();
k_means()
}
data_1_x_sum = 0;
data_1_y_sum = 0;
data_2_x_sum = 0;
data_2_y_sum = 0;
for (var i = 0; i < group_1.length; i++) {
data_1_x_sum += group_1[i][0];
data_1_y_sum += group_1[i][1];
}
for (i = 0; i < group_2.length; i++) {
data_2_x_sum += group_2[i][0];
data_2_y_sum += group_2[i][1];
}
TempDot[0] = Dot_1;
TempDot[1] = Dot_2;
Dot_1 = [(data_1_x_sum / group_1.length), (data_1_y_sum / group_1.length)];
Dot_2 = [(data_2_x_sum / group_2.length), (data_2_y_sum / group_2.length)];
if(Dot_1[0]==TempDot[0][0]&&Dot_1[1]==TempDot[0][1]
&&Dot_2[0]==TempDot[1][0]&&Dot_2[1]==TempDot[1][1]){
return true;
}
group_1 = [];
group_2 = [];
for (var i = 0; i < dataTotel; i++) {
distance(Dot_1,hasntlabel_data[i])>distance(Dot_2,hasntlabel_data[i])
?group_2.push(hasntlabel_data[i]):group_1.push(hasntlabel_data[i]);
}
k_means()
}

function distance(e, f) {
return Math.sqrt(Math.pow((f[0] - e[0]), 2) + Math.pow((f[1] - e[1]), 2));
}


当多次运行代码时,可以看到不同的结果

upload successful

对于K-means来说初始点对于结果的影响大,

且收敛太慢,算法复杂度高O(nkt),结果不一定是全局最优,只能保证局部最优。

之后会学习与使用K-means++之类的增强的算法来进行聚类分析。