编程点滴 | 您所在的位置:网站首页 › randomint › 编程点滴 |
决策树算法实现:RandomForest是由RandomTree组成的,而RandomTree的基础就是决策树,weka中决策树实现的核心代码如下: protected void buildTree(Instances data, double[] classProbs, Instances header, double minNum, boolean debug, int[] attIndicesWindow, Random random, int depth, boolean allow) throws Exception {.......................................................................................................................... m_SplitPoint = splits[m_Attribute]; m_Prop = props[m_Attribute]; Instances[] subsets = splitData(data); m_Successors = new RandomTree[distribution.length]; for (int i = 0; i < distribution.length; i++) { m_Successors[i] = new RandomTree(); m_Successors[i].setKValue(m_KValue); m_Successors[i].setMaxDepth(getMaxDepth()); m_Successors[i].buildTree(subsets[i], distribution[i], header, m_MinNum, m_Debug, attIndicesWindow, random, depth + 1, allow);.......................................................................................................................... }..........................................................................................................................}其中subsets就是分裂后每个节点的样本,把这个数据递归传入buildTree中进行下次分裂。在转换成C代码时,我首先想到的是用vector来保存这些样本,但是因为是递归函数,占用内存过大了(java中的垃圾回收机制起到了作用?反正weka占用的内存要少很多)。一种很自然的改进产生了,即每次只是传入样本的id,因为样本总量是一定的,所以总的样本只保留了一份,大大节省了内存。然而这样每次还是需要传入一个数组,感觉还是有冗余啊,看了LH的代码后才发现原来内存可以这么省...比如我有十个样本,id为[0,1,2,3,4,5,6,7,8,9]分裂的时候属于左节点的样本为[0,2,4,6,8]分裂的时候属于右节点的样本为[1,3,5,7,9]这样我每次传入的是其中一个数组,需要复制五个字节(假设这里用的是char型数组)LH的做法是:将[0,1,2,3,4,5,6,7,8,9]看成是一个链表,用两个字节记录下左右节点的初始id,用-1表示链表结束,这样每次只需传入链表的起始位置一个字节即可 ![]() ![]() 例如,当你获得0这个链表起点时,不但知道该节点包含了样本0,还知道该节点包含的下一个样本id在数组的第0个位置,当遍历到2时,又知道下个节点在位置2,即4 |
CopyRight 2018-2019 实验室设备网 版权所有 |