CART算法的简单实现(1)

     花了两天时间将cart算法中离散数据分类写完(后面还有连续数据的处理和决策树裁剪)。这次感觉比id3实现要更有成就感,毕竟一般以上的代码自己写的。不过看看写好的代码还是有些不堪回首啊。写代码还不熟练以后要多加锻炼!

cart算法介绍:

与id3相比cart主要在度量参数方面不同,cart用gini指标用作属性划分的标准。2010040817082713.gif,其中pi为D中元素属于Ci类的概率。

对于元素的二元分裂由另一公式判断:2010040817123290.gif

对于单列属性的二元分裂要选取GiniA(D)最小的一个来最为该属性列上的一个合理划分。而选择作为节点的属性列也要根据最小的gini指标判断。

大致的特点就是这样。

1             for (int i = 0; i < columns.size(); i++) {
2 tempgini=getColGini(columns.get(i), temppropersep);
3 if (gini > tempgini) {
4 gini = tempgini;
5 propersep=new CARTProperClassify(temppropersep);
6 minColIndex = i;
7 }
8 }
 
  
1 int totalcount = totalTargets.totalCount;
2 for ( int i = 0 ; i < totalList.size(); i ++ ) {
3 double p = 0.0 ;
4 int itemcount = totalList.get(i).counts;
5 p = ( double ) itemcount / totalcount;
6 p *= p;
7 gini += p;
8 }
9 gini = 1 - gini;

但是,算法实现的外有一个难点,就是在选择二元分裂时,对属性项的真子集选择。对于有n个属性值的属性,会有2^n种不同的组合方式。

因为算法水平还没那么高,这个我就直接借鉴别人的代码了。大致思想就是将每个属性用二进制位(n个属性就用n个二进制为来表示)来表示,1表示选择该属性,0表示不选择该属性。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
package BaseStructure.Tree;

import java.util.BitSet;
import java.util.HashSet;
import java.util.Set;

public class ProperSubsetCombination {

private static Integer[] array;
private static BitSet startBitSet; // 比特集合起始状态
private static BitSet endBitSet; // 比特集合终止状态,用来控制循环
private static Set < Set < Integer >> properSubset; // 真子集集合

/**
* 计算得到一个集合的非空真子集集合
*
*
@param n
* 真子集的大小
*
@param itemSet
* 一个频繁项集元素
*
@return 非空真子集集合
*/
public static Set < Set < Integer >> getProperSubset( int n, Set < Integer > itemSet) {
Integer[] array
= new Integer[itemSet.size()];
ProperSubsetCombination.array
= itemSet.toArray(array);
properSubset
= new HashSet < Set < Integer >> ();
startBitSet
= new BitSet();
endBitSet
= new BitSet();

// 初始化startBitSet,左侧占满1
for ( int i = 0 ; i < n; i ++ ) {
startBitSet.set(i,
true );
}

// 初始化endBit,右侧占满1
for ( int i = array.length - 1 ; i >= array.length - n; i -- ) {
endBitSet.set(i,
true );
}

// 根据起始startBitSet,将一个组合加入到真子集集合中
get(startBitSet);

while ( ! startBitSet.equals(endBitSet)) {
int zeroCount = 0 ; // 统计遇到10后,左边0的个数
int oneCount = 0 ; // 统计遇到10后,左边1的个数
int pos = 0 ; // 记录当前遇到10的索引位置

// 遍历startBitSet来确定10出现的位置
for ( int i = 0 ; i < array.length; i ++ ) {
if ( ! startBitSet.get(i)) {
zeroCount
++ ;
}
if (startBitSet.get(i) && ! startBitSet.get(i + 1 )) {
pos
= i;
oneCount
= i - zeroCount;
// 将10变为01
startBitSet.set(i, false );
startBitSet.set(i
+ 1 , true );
break ;
}
}
// 将遇到10后,左侧的1全部移动到最左侧
int counter = Math.min(zeroCount, oneCount);
int startIndex = 0 ;
int endIndex = 0 ;
if (pos > 1 && counter > 0 ) {
pos
-- ;
endIndex
= pos;
for ( int i = 0 ; i < counter; i ++ ) {
startBitSet.set(startIndex,
true );
startBitSet.set(endIndex,
false );
startIndex
= i + 1 ;
pos
-- ;
if (pos > 0 ) {
endIndex
= pos;
}
}
}
get(startBitSet);
}
return properSubset;
}

/**
* 根据一次移位操作得到的startBitSet,得到一个真子集
*
*
@param bitSet
*/
private static void get(BitSet bitSet) {
Set
< Integer > set = new HashSet < Integer > ();
for ( int i = 0 ; i < array.length; i ++ ) {
if (bitSet.get(i)) {
set.add(array[i]);
}
}
properSubset.add(set);
}
}

接下来就的工作就是完善算法的了。

转载于:https://www.cnblogs.com/valder/archive/2010/04/08/1707609.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值