zoukankan      html  css  js  c++  java
  • [Go]使用Golang对鸢尾花数据集进行k-means聚类

    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)
            return nil
        }
        defer fi.Close()
    
        var d 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,
                })
            }
        }
        return d
    }
    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<len(files) - 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<len(clusterout)-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
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <title>Bootstrap 4 Website Example</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/css/bootstrap.min.css">
        <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
        <script src="https://cdn.staticfile.org/popper.js/1.12.5/umd/popper.min.js"></script>
        <script src="https://cdn.staticfile.org/twitter-bootstrap/4.1.0/js/bootstrap.min.js"></script>
    </head>
    
    <body>
    
        <div class="container" style="margin-top:30px">
            <div class="row">
                <div class="col-sm-6">
                    <h2>聚类点</h2>
                    <div style="height: 500px">
                        <textarea style=" 100%; height: 100%" id="clusters"></textarea>
                    </div>
                </div>
                <div class="col-sm-6">
                    <h2>k-means聚类过程</h2>
                    <div style="height: 500px">
                        <canvas id="show" style=" 100%;height: 100%"></canvas>
                    </div>
                </div>
            </div>
        </div>
    
    </body>
    <script>
        Images = [{{images}}]
        Clusters = [{{clusters}}]
        window.onload = function () {
            var CANVAS = document.getElementById('show');
            context = CANVAS.getContext('2d');
            var ratio = getPixelRatio(context)
            var img = new Image();
            SetClusters()
            img.onload = function () {
                context.drawImage(img, 0, 0, 300 * ratio,150 * ratio);
            }
            var count = 0
            var interval = setInterval(function(){
                if(count < Images.length)
                {
                    img.src = Images[count]
                }
                else
                {
                    clearInterval(interval);
                    return
                }
                count = count + 1
            },1000)
        }
        function getPixelRatio(context) {
            var backingStore = context.backingStorePixelRatio ||
                context.webkitBackingStorePixelRatio ||
                context.mozBackingStorePixelRatio ||
                context.msBackingStorePixelRatio ||
                context.oBackingStorePixelRatio ||
                context.backingStorePixelRatio || 1;
    
            return (window.devicePixelRatio || 1) / backingStore;
        }
        function SetClusters(){
            for(var i=0;i<Clusters.length;i++)
            {
                document.getElementById("clusters").value = document.getElementById("clusters").value + Clusters[i] + '
    '
            }
        }
    </script>
    
    </html>

    项目地址:https://github.com/leeli73/go-kmeans-html-plotter.git

    kmeans项目地址:https://github.com/muesli/kmeans.git

     

  • 相关阅读:
    matplotlib-形状
    matplotlib-区域填充
    C++文件操作
    画数学公式
    文字
    画注释
    Doubango简介-sip
    boost的asio接收单路大数据量udp包的方法
    Boost.Asio基本原理(CSDN也有Markdown了,好开森)
    boot asio 非阻塞同步编程---非阻塞的accept和receive。
  • 原文地址:https://www.cnblogs.com/lee-li/p/11016730.html
Copyright © 2011-2022 走看看