数据挖掘之KMeans算法应用与简单理解

一、背景

煤矿地磅产生了一系列数据:

我想从这些数据中,取出最能反映当前车辆重量的数据(有很多数据是车辆上磅过程中产生的数据)。我于是想到了聚类算法KMeans,该算法思想比较简单。

二、算法步骤

1、从样本中随机取出k个值,作为初始中心

2、以k个中心划分这些数据,分为k个组

3、重新计算出每个组的中心,作为新中心

4、如果初始中心和新中心不相等,则把新中心作为初始中心,重复2,3。反之,结束

注意:

1、我没有用严格的算法定义,怕不好理解

2、KMeans善于处理球形数据,因此随机取k个质心,每个质心吸引离它最近的数据

3、由于质心的取值是不科学的,所以需要不断地计算调整,直到质心名副其实

三、算法分析及特点

1、从算法步骤当中可以看出有两个问题,需要解决:

首先,如何计算每个组(簇)的质心?

其次,如何把值划分到不同的组?

2、解决上面两个问题,因场景和要求不同而有不同的小算法,由于我的数据是一维的,而不是点,所以可以简单处理:

a、以每个组的平均值作为质心

b、根据值离质心的距离(相减),选择距离最近的组加入

3、此算法有两个缺点:

1)某个组(簇)划分不充分,还可以再划分为更小的组。(容易陷入局部最优)

2)需要用户指定k,聚类结果对初始质心的选择较为敏感(初始选择不同,聚类结果可能不同)

4、优点:简单易理解和上手

四、实现

    public class KMeans
    {
        /*
        * 聚类函数主体。
        * 针对一维 decimal 数组。指定聚类数目 k。
        * 将数据聚成 k 类。
        */
        public static decimal[][] cluster(decimal[] p, int k)
        {
            // 存放聚类旧的聚类中心
            decimal[] c = new decimal[k];
            // 存放新计算的聚类中心
            decimal[] nc = new decimal[k];
            // 存放放回结果
            decimal[][] g;
            // 初始化聚类中心
            // 经典方法是随机选取 k 个
            // 本例中采用前 k 个作为聚类中心
            // 聚类中心的选取不影响最终结果
            for (int i = 0; i < k; i++)
                c[i] = p[i];
            // 循环聚类,更新聚类中心
            // 到聚类中心不变为止
            while (true)
            {
                // 根据聚类中心将元素分类
                g = group(p, c);
                // 计算分类后的聚类中心
                for (int i = 0; i < g.Length; i++)
                {
                    nc[i] = center(g[i]);
                }
                // 如果聚类中心不同
                if (!equal(nc, c))
                {
                    c = nc;
                    nc = new decimal[k];
                }
                else
                    break;
            }
            return g;
        }
        /*
         * 聚类中心函数
         * 简单的一维聚类返回其算数平均值
         * 可扩展
         */
        public static decimal center(decimal[] p)
        {
            if (p.Length == 0) return 0;
            return sum(p) / p.Length;
        }
        /*
         * 给定 decimal 型数组 p 和聚类中心 c。
         * 根据 c 将 p 中元素聚类。返回二维数组。
         * 存放各组元素。
         */
        public static decimal[][] group(decimal[] p, decimal[] c)
        {
            // 中间变量,用来分组标记
            int[] gi = new int[p.Length];
            // 考察每一个元素 pi 同聚类中心 cj 的距离
            // pi 与 cj 的距离最小则归为 j 类
            for (int i = 0; i < p.Length; i++)
            {
                // 存放距离
                decimal[] d = new decimal[c.Length];
                // 计算到每个聚类中心的距离
                for (int j = 0; j < c.Length; j++)
                {
                    d[j] = distance(p[i], c[j]);
                }
                // 找出最小距离
                int ci = min(d);
                // 标记属于哪一组
                gi[i] = ci;
            }
            // 存放分组结果
            decimal[][] g = new decimal[c.Length][];
            // 遍历每个聚类中心,分组
            for (int i = 0; i < c.Length; i++)
            {
                // 中间变量,记录聚类后每一组的大小
                int s = 0;
                // 计算每一组的长度
                for (int j = 0; j < gi.Length; j++)
                    if (gi[j] == i)
                        s++;
                // 存储每一组的成员
                g[i] = new decimal[s];
                s = 0;
                // 根据分组标记将各元素归位
                for (int j = 0; j < gi.Length; j++)
                    if (gi[j] == i)
                    {
                        g[i][s] = p[j];
                        s++;
                    }
            }
            // 返回分组结果
            return g;
        }

        /*
         * 计算两个点之间的距离, 这里采用最简单得一维欧氏距离, 可扩展。
         */
        public static decimal distance(decimal x, decimal y)
        {
            return Math.Abs(x - y);
        }

        /*
         * 返回给定 decimal 数组各元素之和。
         */
        public static decimal sum(decimal[] p)
        {
            decimal sum = 0.0M;
            for (int i = 0; i < p.Length; i++)
                sum += p[i];
            return sum;
        }

        /*
         * 给定 decimal 类型数组,返回最小值得下标。
         */
        public static int min(decimal[] p)
        {
            int i = 0;
            decimal m = p[0];
            for (int j = 1; j < p.Length; j++)
            {
                if (p[j] < m)
                {
                    i = j;
                    m = p[j];
                }
            }
            return i;
        }

        /*
         * 判断两个 decimal 数组是否相等。 长度一样且对应位置值相同返回真。
         */
        public static bool equal(decimal[] a, decimal[] b)
        {
            if (a.Length != b.Length)
                return false;
            else
            {
                for (int i = 0; i < a.Length; i++)
                {
                    if (a[i] != b[i])
                        return false;
                }
            }
            return true;
        }
    }

客户端调用:

 1        static void Main(string[] args)
 2         {
 3             var path = string.Empty;
 4             int k = 0;
 5             try
 6             {
 7                 path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "blanceTest.txt");//数据文件路径
 8                 k = 4;
 9             }
10             catch (Exception)
11             {
12                 Console.Write("参数错误");
13                 return;
14             }
15
16             decimal[] p = { 1, 2, 3, 5, 6, 7, 9, 10, 11, 20, 21, 22, 23, 27, 40, 41, 42, 43, 61, 62, 63, 100, 150, 200, 1000 };
17
18             List<decimal> pList = new List<decimal>();
19
20             var lines = File.ReadAllLines(path);
21
22             foreach (var line in lines)
23             {
24                 var data = System.Text.RegularExpressions.Regex.Replace(line, @" +", " ");
25                 var datas = data.Split(‘ ‘);
26
27                 pList.AddRange(datas.Where(d => d != "").Select(d => Convert.ToDecimal(d)));
28             }
29
30             p = pList.ToArray();
31
32             k = 5;
33             decimal[][] g;
34             g = KMeans.cluster(p, k);
35             for (int i = 0; i < g.Length; i++)
36             {
37                 for (int j = 0; j < g[i].Length; j++)
38                 {
39                     Console.WriteLine(g[i][j]);
40                 }
41                 Console.WriteLine("----------------------");
42             }
43             Console.ReadKey();
44
45         }

注意:

1、如果数据文件为空或不存在,则用初始化的p数组,作为测试数据

2、文件中的数据,见开篇截图

参考文章:

一维数组的 K-Means 聚类算法理解

深入理解K-Means聚类算法

原文地址:https://www.cnblogs.com/wangqiang3311/p/11230975.html

时间: 2024-10-30 09:51:35

数据挖掘之KMeans算法应用与简单理解的相关文章

[数据挖掘] - 聚类算法:K-means算法理解及SparkCore实现

聚类算法是机器学习中的一大重要算法,也是我们掌握机器学习的必须算法,下面对聚类算法中的K-means算法做一个简单的描述: 一.概述 K-means算法属于聚类算法中的直接聚类算法.给定一个对象(或记录)的集合,将这些对象划分为多个组或者“聚簇”,从而使同组内的对象间比较相似而不同组对象间差异比较大:换言之,聚类算法就是将相似的对象放到同一个聚簇中,而将不相似的对象放到不同的聚簇中.由于在聚类过程中不使用到类别标签,所以相似性的概念要基于对象的属性进行定义.应用不同则相似性规则和聚类算法一般不太

K-Means 算法(转载)

K-Means 算法 在数据挖掘中, k-Means 算法是一种 cluster analysis 的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 问题 K-Means算法主要解决的问题如下图所示.我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Means算法(Wikipedia链接) K-Means 要解决的问题 算法概要 这个算法其实很简单,如下图所示: K-Means 算法

(转)深入浅出K-Means算法

原文地址:http://www.csdn.net/article/2012-07-03/2807073-k-means 摘要:在数据挖掘中,K-Means算法是一种 cluster analysis 的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 在数据挖掘中,K-Means算法是一种cluster analysis的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 问题 K-Means算法主要解决的问题如下图所示.我们可以看到,在图的

机器学习之K-means算法

前言            以下内容是个人学习之后的感悟,转载请注明出处~ 简介 在之前发表的线性回归.逻辑回归.神经网络.SVM支持向量机等算法都是监督学习算法,需要样本进行训练,且 样本的类别是知道的.接下来要介绍的是非监督学习算法,其样本的类别是未知的.非监督学习算法中,比较有代表性 的就是聚类算法.而聚类算法中,又有 分割方法:K-means 分层次方法:ROCK . Chemeleon 基于密度的方法:DBSCAN 基于网格的方法:STING . WaveCluster 以上只是部分算

关于K-Means算法

在数据挖掘中,K-Means算法是一种cluster analysis的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 问题 K-Means算法主要解决的问题如下图所示.我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Means算法(Wikipedia链接) K-Means要解决的问题 算法概要 这个算法其实很简单,如下图所示: 从上图中,我们可以看到,A,B,C,D,E是五个在图

Kmeans算法详解及MATLAB实现

首先要来了解的一个概念就是聚类,简单地说就是把相似的东西分到一组,同 Classification (分类)不同,对于一个 classifier ,通常需要你告诉它"这个东西被分为某某类"这样一些例子,理想情况下,一个 classifier 会从它得到的训练集中进行"学习",从而具备对未知数据进行分类的能力,这种提供训练数据的过程通常叫做 supervised learning (监督学习),而在聚类的时候,我们并不关心某一类是什么,我们需要实现的目标只是把相似的东

【机器学习笔记之一】深入浅出学习K-Means算法

摘要:在数据挖掘中,K-Means算法是一种 cluster analysis 的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 在数据挖掘中,K-Means算法是一种cluster analysis的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法. 问题 K-Means算法主要解决的问题如下图所示.我们可以看到,在图的左边有一些点,我们用肉眼可以看出来有四个点群,但是我们怎么通过计算机程序找出这几个点群来呢?于是就出现了我们的K-Mea

数据挖掘算法之k-means算法

系列文章:数据挖掘算法之决策树算法 [QQ群: 189191838,对算法和C++感兴趣可以进来]       k-means算法可以说是数据挖掘中十大经典算法之一了,属于无监督的学习.该算法由此衍生出了很多类k-means算法,比如k中心点等等,在数据挖掘领域,很多地方都会用到该算法,他能够把相似的一类很好的聚在一起.一类指的是,他们之间的相似度较高,计算相似度的常用度量有欧氏距离.余弦定理等.本算法采用的是欧式距离度量.这个对理解k-means算法不会造成任何实质性的影响. 为了更好的说明k

数据挖掘-聚类分析(Python实现K-Means算法)

概念: 聚类分析(cluster analysis ):是一组将研究对象分为相对同质的群组(clusters)的统计分析技术.聚类分析也叫分类分析,或者数值分类.聚类的输入是一组未被标记的样本,聚类根据数据自身的距离或者相似度将其划分成若干个组,划分的原则是组内距离最小化而组间(外部)距离最大化.聚类和分类的不同在于:聚类所要求划分的类是未知的. 聚类度量的方法:分距离和相似度来度量. ? ? 聚类研究分析的方法: 1.层次的方法(hierarchical  method) 2.划分方法(par