关于连续值离散化[MODL]

将连续值离散化的问题,在数据挖掘和机器学习的任务中并不鲜见,当然离散化的方法也有很多。

本文将要介绍的是一种基于数据标签(label)来对连续数据值做离散化分割的监督学习方法。

 

问题:

考虑有如下数据:

   1,0

   2,0

   3,0

   4,0

   5,0

   6,1

   7,1

   8,1

   9,1

   10,1

第一列是连续值数据,而第二列是数据的类别标签(label)

我们希望对数据进行划分,使得划分的结果符合数据的类标签的分布。

即,预期前5个值为一段,后5个值为另一段。

 

这个问题可能有点太naive,明眼人只要看一眼即可准确地将数据按照需要的方式划分。

可是,我们需要机器像人一样聪明,能做出同样的判断,而且能将这种能力推广到更大更复杂的数据集。

 

那机器到底是怎么样进行思考的呢?或者是基于什么准则来实现上述数据分段?

这就是我们今天要重点介绍的内容,一种基于贝叶斯后验优化的连续值离散化方法

 

我们将上述数据记为D,将要求解的模型记为M。我们的目标是找到在给定数据D时,后验概率最大的那个M,即最大化P(M|D)。

 

根据贝叶斯公式得到:P(M|D) = P(D|M)P(M) / P(D),而既然D已经给定了,那P(D)不管是多少都是个定值,因此只需要使P(D|M)P(M)最大即可。

 

 

P(M):

为了描述的方便,我们给出如下一些标记:

 关于连续值离散化[MODL]_第1张图片

 

基于上述标记,则我们的模型空间为如下集合:

同时对模型做如下假定:

  1. 分段数“I”服从 1~n的均匀分布
  2. 给定分段数“I”后,不同的分段结果之间的概率相等
  3. 给定 I 和 ni,每个类标签值的分布在各个分段内的概率是均等的。
  4. 每个分段内的类值分布概率是独立的

 根据上述假设,则模型先验概率P(M)可展开如下:

根据假定1,得到:

根据假定2,得到:

关于连续值离散化[MODL]_第2张图片

根据假定3,4,得到:

关于连续值离散化[MODL]_第3张图片

 

则,P(M)的最终形态为:

关于连续值离散化[MODL]_第4张图片

 

 

P(D|M):

 

即给定模型M,数据D的“似然”,不难得到:

 

关于连续值离散化[MODL]_第5张图片

 

 

则P(M|D)最终表达为:

关于连续值离散化[MODL]_第6张图片

最大化P(M|D)等价于最小化如下公式:

 

关于连续值离散化[MODL]_第7张图片

 

 

最终我们只需要求解一个如上目标的最小化问题即可,具体的求解方法,本文不做详细展开。

 

具体实现可参考代码:https://code.csdn.net/u011531384/libdm/blob/master/modl.c

 

代码接口原型如下:

/* **********************************
 *  in   double [] v, the continous data vector
 *  in   int [] a,    the label vector assiated with v
 *  in   int n,       the size of data
 *  out int nd,       the size of split points
 *  return            the split points vector
 * **********************************/
double * modl(double v[], int a[], int n, int* nd);

 

测试代码如下:

#include <stdlib.h>
#include "modl.h"


int main(){
    double v[15] = {1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0};
    int    a[15] = {0,  0,  0,  0,  0,  1,  1,  1,  1,  1   ,0   ,0   ,0   ,0   ,0};
    int    nd = 0,i=0;
    double * rule = NULL;
    rule = modl(v,a,15,&nd);
    if (rule && nd > 0){
        printf("split points:%d\n",nd);
        for (i = 0; i< nd; i++){
            printf("%.3f\n", rule[i]);
        }
    }
    else{
        printf("no split rule generated\n");
    }
    return 0;
}

 

 

结果如预期输出:

split points:2

5.5

10.5

 

 

 

 

 

你可能感兴趣的:(c,算法,数据挖掘,机器学习,离散化)