机器学习经典算法1:k-means 聚类算法

这里的k为聚类数,其解决以1种属性值(例如距离值)进行的多点分类问题。
例如我们要实现对坐标系中多个点进行聚类分组。思路如下:
1,输入条件1:坐标系中的N个固定点集合(已知每个点的x、y坐标值)
2,输入条件2:坐标系中任意k个聚类核心点的位置(通常会依据经验定位初始的聚类核心点位置)
3,执行过程1:遍历所有固定点计算每个点与k各聚类核心点的距离,并将各点归类到与其距离最近的核心点分类中(采用欧氏距离)。
4,执行过程2:依次遍历k个聚类,调整各聚类中核心点的位置到聚类中心(求聚类中所有点平均值的方式)
5,执行过程3:再次执行过程1,直到聚类核心点的位置不再发生变化。

Js算法如下:

        /**
         * 按给定的分组点生成分组
         * @param points 所有点
         * @param zonePoints 当前分组点
         */
        function kMeans(points, zonePoints) {
            for (var i = 0; i < points.length; i++) {
                var p = points[i];
                var minDistance = -1, minTp = null;
                for (var j = 0; j < zonePoints.length; j++) {
                    var tp = zonePoints[j];
                    var distance = Math.sqrt(Math.pow(p.x - tp.x, 2) + Math.pow(p.y - tp.y, 2));
                    if (minDistance === -1 || minDistance > distance) {//计算每个点到各区域核心点的最短距离
                        minDistance = distance;
                        minTp = tp;
                    }
                }
                p.tpId = minTp.id;
                $("#p" + p.id).css('background-color', minTp.color);//设置点颜色
                printLog('p[' + p.id + ']{x:' + p.x + ',y:' + p.y + '}所属类别:' + (p.tpId === undefined ? '未设定' : p.tpId));
            }
        }

        /**
         * 计算每个分组的核心点,并修改分组点坐标
         * @param points 所有点
         * @param zonePoints 当前分组点
         */
        function calcCenter(points, zonePoints) {
            var bestRegionCoreSize = 0;
            for (var j = 0; j < zonePoints.length; j++) {
                var tp = zonePoints[j];
                //1,找到分组的所有点
                var pSumX = 0, pSumY = 0, pSize = 0;
                for (var i = 0; i < points.length; i++) {
                    var p = points[i];
                    if (tp.id === p.tpId) {
                        // tpGroup.push(p);
                        pSumX += p.x;
                        pSumY += p.y;
                        pSize++;
                    }
                }
                //2,求组核心点
                if (pSize > 0) {
                    var pCenterX = pSumX / pSize;
                    var pCenterY = pSumY / pSize;
                    if (tp.x === pCenterX && tp.y === pCenterY) {
                        bestRegionCoreSize++;
                        printLog('找到一个最佳聚类核心,坐标是:{x:'+pCenterX+',y:'+pCenterY+'}');
                    } else {
                        tp.x = pCenterX;
                        tp.y = pCenterY;
                        $("#tp" + tp.id).css({'left': pCenterX + 'px', 'top': pCenterY + 'px'});

                    }
                }
            }
            if (bestRegionCoreSize === zonePoints.length) {
                alert("已找到所有聚类的最佳核心点,所有点的聚类已完成");
                return true;
            } else {
                return false;
            }
        }

演示demo下载地址:https://gitee.com/inq/k-means.git

ScreenFlow.gif

你可能感兴趣的:(机器学习经典算法1:k-means 聚类算法)