将连续值离散化的问题,在数据挖掘和机器学习的任务中并不鲜见,当然离散化的方法也有很多。
本文将要介绍的是一种基于数据标签(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):
为了描述的方便,我们给出如下一些标记:
基于上述标记,则我们的模型空间为如下集合:
同时对模型做如下假定:
- 分段数“I”服从 1~n的均匀分布
- 给定分段数“I”后,不同的分段结果之间的概率相等
- 给定 I 和 ni,每个类标签值的分布在各个分段内的概率是均等的。
- 每个分段内的类值分布概率是独立的
根据上述假设,则模型先验概率P(M)可展开如下:
根据假定1,得到:
根据假定2,得到:
根据假定3,4,得到:
则,P(M)的最终形态为:
P(D|M):
即给定模型M,数据D的“似然”,不难得到:
则P(M|D)最终表达为:
最大化P(M|D)等价于最小化如下公式:
最终我们只需要求解一个如上目标的最小化问题即可,具体的求解方法,本文不做详细展开。
具体实现可参考代码: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