k-means算法是一种简单的迭代型聚类算法,采用距离作为相似性指标,从而发现给定数据集中的K个类,且每个类的中心是根据类中所有值的均值得到,每个类用聚类中心来描述。对于给定的一个包含n个d维数据点的数据集X以及要分得的类别K,选取欧式距离作为相似度指标,聚类目标是使得各类的聚类平方和最小,即最小化:
结合最小二乘法和拉格朗日原理,聚类中心为对应类别中各数据点的平均值,同时为了使得算法收敛,在迭代过程中,应使最终的聚类中心尽可能的不变。
聚类过程
首先任取k个样本点作为k个簇的初始中心
对每一个样本点,计算它们与k个中心的距离,把它归入距离最小的中心所在的簇
等到所有的样本点归类完毕,重新计算k个簇的中心
重复以上过程直至样本点归入的簇不再变动或变动范围极小
可视化演示:
在每次完成聚类之后,生成图片并保存。
最后生成一个k-means.html,其中使用JavaScript逐秒绘制过程图
聚类过程:
不同的颜色代表一个类,黑点代表聚簇点
第一次迭代(随机选点,还未聚类)
进行迭代,更新聚类点
最后一次迭代(按点已经完成聚类)
由于数据太多,可以在k-means.html中查看变化过程
结果演示:
输出聚簇点
可视化演示
代码:使用了github.com/muesli/kmeans库,我对它的注释进行了翻译,对程序进行了部分修改,方便可视化演示
package main
import ("io"
"os"
"log"
"fmt"
"bufio"
"io/ioutil"
"strings"
"strconv"
"github.com/leeli73/go-kmeans-html-plotter/clusters"
"github.com/leeli73/go-kmeans-html-plotter/kmeans")//读取数据
func InitData() clusters.Observations{
fi, err := os.Open("data/iris.dat")if err !=nil {
log.Fatalln(err)returnnil
}
defer fi.Close()vard clusters.Observations
br :=bufio.NewReader(fi)for{
a, _, c :=br.ReadLine()if c ==io.EOF {break}
temp := string(a)if temp[0] != '@'{
data := strings.Split(temp,",")
num1,_ := strconv.ParseFloat(data[0], 64)
num2,_ := strconv.ParseFloat(data[1], 64)
num3,_ := strconv.ParseFloat(data[2], 64)
num4,_ := strconv.ParseFloat(data[3], 64)
d=append(d,clusters.Coordinates{
num1,
num2,
num3,
num4,
})
}
}returnd
}
func main() {
d :=InitData()//定义一个k-means
km, _ := kmeans.New(0.01, kmeans.SimplePlotter{})//进行聚类运算
clusters,files, _ := km.Partition(d, 4)//生成演示html
strfiles := "\"" + files[0] + "\","
for i:=1;i
strfiles= strfiles + "\"" + files[i] + "\","}
strfiles= strfiles + "\"" + files[len(files)-1] + "\""clusterout := []string{}for i, c :=range clusters {
log.Printf("Cluster: %d %+v", i, c.Center)
str := fmt.Sprintf("Cluster: %d %+v", i, c.Center)
clusterout=append(clusterout,str)
}
clustersstr := "\"" + clusterout[0] + "\","
for i:=1;i
clustersstr= clustersstr + "\"" + clusterout[i] + "\","}
clustersstr= clustersstr + "\"" +clusterout[len(clusterout)-1] + "\""
var Data,err = ioutil.ReadFile("data/web.html")if err !=nil{
log.Fatal(err)
}
html := string(Data)
html= strings.Replace(html,"{{images}}",strfiles,-1)
html= strings.Replace(html,"{{clusters}}",clustersstr,-1)
ioutil.WriteFile("k-means.html",[]byte(html), 0644)
}
k-means.html
Bootstrap 4 Website Example