决策树分类器-Java实现

本文介绍了使用Java实现决策树分类器的方法,基于信息熵最小原则选择特征。内容包括决策树的基本思想,信息熵的计算公式,以及如何构建和序列化决策树结构。通过训练集数据递归创建决策树,并对外提供classify()方法进行样本点分类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

决策树模型,其基本思想类似于if else的结构,即满足什么条件则将它判定为某一类,而这里的决策树的深度就类似于if else的深度。
决策树的问题焦点在于,对于一个拥有多维数据特征的数据点,如何选择合适的分类依据。例如一只鸡(两条腿,有翅膀,没有脚蹼。。。),一只鸭(两条腿,有翅膀,有脚蹼。。),等等,现在来了一只奇怪的生物(两条腿,有翅膀,没有脚蹼。。),如果先根据腿或翅膀来判断的话,根本无法判断它属于哪一种生物,而如果根据脚蹼来判断的话,立刻就能分辨出来。从这个例子中,想表达的就是决策树如果去抉择一种最合适的特征来得到不同的判决类。
本文是基于数据集信息熵最小的原则,来确定这种树的生长规则的。信息熵的背景,不多说,简而言之,越有序的系统熵越小,越无序的系统熵越大。其计算公式如下:
H(x) = E[I(xi)] = E[ log(2,1/p(xi)) ] = -∑p(xi)log(2,p(xi)) (i=1,2,..n)
其中p(xi)为xi样本在x总体中的取值概率(或统计学中的频率)。
在给出具体实现代码之前,我先给出此处用到的树结构。

/**
 * Created by Song on 2017/1/4.
 * 树节点,可序列化存储
 */
public class Node implements Serializable{
   
    public Object element;
    public Map<Object,Node> child;
}

之所以这样设计,是基于此处具体的应用环境。e在此应用环境中,element为String类型的特征名称,而Map中的每个键值对,键名代表着判决条件(连接两个节点的线的标称),值代表着下一个节点。
下面再给出,Java中对象序列化存储的部分代码(在测试时,我注释掉了),用于在通过训练集得到决策树结构之后,将该树保存在文件中,而不需要,每次都重新训练得到决策树结构。

Node root = handler.createTree(dataSet,featurelabels,labelStr);
  //树结构存储
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("E:\\dectree.txt")));
        oos.writeObject(root);
        oos.flush();
        oos.close();
//树结构读取
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:\\dectree.txt")));
        Node tree = (Node) ois.readObject();

下面是决策树分类器的具体实现代码:

/**
 * Created by Song on 2017/1/3.
 * 决策树
 */
public class DectreeHandler {
   
    /**
     * 计算数据集的香农熵
     * @param dataSet 数据集(最后一列为分类信息)
     * @return 香农熵
     */
    private static double calcShannonEnt(Matrix dataSet){
        int m = dataSet.getRowDimension();
        int n = dataSet.getColumnDimension();
        double currentLabel = 0;
        double shannonEnt = 0;
        double rate = 0;
        HashMap<Double,Integer> labelCounts = new HashMap<Double, Integer>();
        //统计各类出现次数
        for(int i=0;i<m;i++){
            currentLabel = dataSet.get(i,n-1);
            if(!labelCounts.containsKey(currentLabel))
                labelCounts.put(currentLabel,0);
            labelCounts.put(currentLabel,labelCounts.get(currentLabel)+1);
        }
        //计算整体香农熵
        for(double key:labelCounts.keySet()){
            rate =labelCounts.get(key)/(float)m;
            shannonEnt -= rate*Math.log(rate)/Math.log(2);
        }
        return shannonEnt;
    }

    /**
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值