ID3算法(决策树)

一,预备知识:

  1. 信息量:
  2. 单个类别的信息熵:
  3. 条件信息量:
  4. 单个类别的条件熵:
  5. 信息增益:
  6. 信息熵:
  7. 条件熵:表示分类的类,表示属性V的取值,m为属性V的取值个数,n为分类的个数)

二.算法流程:

实质:递归的先根建树,结束条件(当前子集类别一致),建树量化方法(信息增益)

三.示例代码:

package com.mechinelearn.id3;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

public class ID3 {
    private ArrayList<String> attribute = new ArrayList<String>(); // 存储属性的名称
    private ArrayList<ArrayList<String>> attributevalue = new ArrayList<ArrayList<String>>(); // 存储每个属性的取值
    private ArrayList<String[]> data = new ArrayList<String[]>();; // 原始数据
    int decatt; // 决策变量在属性集中的索引
    public static final String patternString = "@attribute(.*)[{](.*?)[}]";

    Document xmldoc;
    Element root;

    public ID3() {
        xmldoc = DocumentHelper.createDocument();
        root = xmldoc.addElement("root");
        root.addElement("DecisionTree").addAttribute("value", "null");
    }

    public static void main(String[] args) {
        ID3 inst = new ID3();
        inst.readARFF(new File("data.txt"));
        inst.setDec("play");
        LinkedList<Integer> ll = new LinkedList<Integer>();
        for (int i = 0; i < inst.attribute.size(); i++) {
            if (i != inst.decatt)
                ll.add(i);
        }
        ArrayList<Integer> al = new ArrayList<Integer>();
        for (int i = 0; i < inst.data.size(); i++) {
            al.add(i);
        }
        inst.buildDT("DecisionTree", "null", al, ll);
        inst.writeXML("dt.xml");
        return;
    }

    // 读取arff文件,给attribute、attributevalue、data赋值
    public void readARFF(File file) {
        try {
            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);
            String line;
            Pattern pattern = Pattern.compile(patternString);
            while ((line = br.readLine()) != null) {
                Matcher matcher = pattern.matcher(line);
                if (matcher.find()) {
                    attribute.add(matcher.group(1).trim());// 增加属性
                    String[] values = matcher.group(2).split(",");
                    ArrayList<String> al = new ArrayList<String>(values.length);
                    for (String value : values) {
                        al.add(value.trim());
                    }
                    attributevalue.add(al);// 每个属性对应的属性值
                } else if (line.startsWith("@data")) {
                    while ((line = br.readLine()) != null) {
                        if (line == "")
                            continue;
                        String[] row = line.split(",");
                        data.add(row);// 增加训练数据
                    }
                } else {
                    continue;
                }
            }
            br.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    // 设置决策变量
    public void setDec(String name) {
        int n = attribute.indexOf(name);
        if (n < 0 || n >= attribute.size()) {
            System.err.println("决策变量指定错误。");
            System.exit(2);
        }
        decatt = n;
    }

    // 计算每一个属性的属性值对应的的熵
    public double getEntropy(int[] arr) {
        double entropy = 0.0;
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            entropy -= arr[i] * Math.log(arr[i] + Double.MIN_VALUE)
                    / Math.log(2);
            sum += arr[i];
        }
        entropy += sum * Math.log(sum + Double.MIN_VALUE) / Math.log(2);
        entropy /= sum;
        return entropy;
    }

    // 给一个样本数组及样本的算术和,计算它的熵
    public double getEntropy(int[] arr, int sum) {
        double entropy = 0.0;
        for (int i = 0; i < arr.length; i++) {
            entropy -= arr[i] * Math.log(arr[i] + Double.MIN_VALUE)
                    / Math.log(2);
        }
        entropy += sum * Math.log(sum + Double.MIN_VALUE) / Math.log(2);
        entropy /= sum;
        return entropy;
    }

    //是否到达叶子节点
    public boolean infoPure(ArrayList<Integer> subset) {
        String value = data.get(subset.get(0))[decatt];
        for (int i = 1; i < subset.size(); i++) {
            String next = data.get(subset.get(i))[decatt];
            // equals表示对象内容相同,==表示两个对象指向的是同一片内存
            if (!value.equals(next))
                return false;
        }
        return true;
    }

    // 给定原始数据的子集(subset中存储行号),当以第index个属性为节点时计算它的信息熵
    public double calNodeEntropy(ArrayList<Integer> subset, int index) {
        int sum = subset.size();
        double entropy = 0.0;
        int[][] info = new int[attributevalue.get(index).size()][];//属性值个数为行
        for (int i = 0; i < info.length; i++)
            info[i] = new int[attributevalue.get(decatt).size()];//分类属性值个数为列
        int[] count = new int[attributevalue.get(index).size()];//每个属性值在整个样本中出现的概率
        for (int i = 0; i < sum; i++) {
            int n = subset.get(i);
            String nodevalue = data.get(n)[index];
            int nodeind = attributevalue.get(index).indexOf(nodevalue);
            count[nodeind]++;
            String decvalue = data.get(n)[decatt];
            int decind = attributevalue.get(decatt).indexOf(decvalue);
            info[nodeind][decind]++;
        }
        for (int i = 0; i < info.length; i++) {
            entropy += getEntropy(info[i]) * count[i] / sum;// 计算条件熵
        }
        return entropy;
    }

    // 构建决策树(递归建树)
    public void buildDT(String name, String value, ArrayList<Integer> subset,
            LinkedList<Integer> selatt) {
        Element ele = null;
        @SuppressWarnings("unchecked")
        List<Element> list = root.selectNodes("//" + name);
        Iterator<Element> iter = list.iterator();
        while (iter.hasNext()) {
            ele = iter.next();
            if (ele.attributeValue("value").equals(value))
                break;
        }
        if (infoPure(subset)) {// 深度优先建树是否结束
            ele.setText(data.get(subset.get(0))[decatt]);// 设置决策
            return;
        }
        int minIndex = -1;
        double minEntropy = Double.MAX_VALUE;
        for (int i = 0; i < selatt.size(); i++) {
            if (i == decatt)
                continue;
            double entropy = calNodeEntropy(subset, selatt.get(i));
            if (entropy < minEntropy) {
                minIndex = selatt.get(i);
                minEntropy = entropy;
            }
        }
        String nodeName = attribute.get(minIndex);
        selatt.remove(new Integer(minIndex));
        ArrayList<String> attvalues = attributevalue.get(minIndex);
        for (String val : attvalues) {
            ele.addElement(nodeName).addAttribute("value", val);
            ArrayList<Integer> al = new ArrayList<Integer>();
            for (int i = 0; i < subset.size(); i++) {
                if (data.get(subset.get(i))[minIndex].equals(val)) {
                    al.add(subset.get(i));
                }
            }
            buildDT(nodeName, val, al, selatt);// 递归建树
        }
    }

    // 把xml写入文件
    public void writeXML(String filename) {
        try {
            File file = new File(filename);
            if (!file.exists())
                file.createNewFile();
            FileWriter fw = new FileWriter(file);
            OutputFormat format = OutputFormat.createPrettyPrint(); // 美化格式
            XMLWriter output = new XMLWriter(fw, format);
            output.write(xmldoc);
            output.close();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}
时间: 2024-11-10 07:10:05

ID3算法(决策树)的相关文章

ID3算法 决策树 C++实现

人工智能课的实验. 数据结构:多叉树 这个实验我写了好久,开始的时候从数据的读入和表示入手,写到递归建树的部分时遇到了瓶颈,更新样例集和属性集的办法过于繁琐: 于是参考网上的代码后重新写,建立决策树类,把属性集.样例集作为数据成员加入类中,并设立访问数组,这样每次更新属性集.样例集时只是标记访问数组的对应元素即可,不必实际拷贝. 主函数: 1 #include "Decision_tree.h" 2 using namespace std; 3 int main() 4 { 5 int

决策树---ID3算法(介绍及Python实现)

决策树---ID3算法   决策树: 以天气数据库的训练数据为例. Outlook Temperature Humidity Windy PlayGolf? sunny 85 85 FALSE no sunny 80 90 TRUE no overcast 83 86 FALSE yes rainy 70 96 FALSE yes rainy 68 80 FALSE yes rainy 65 70 TRUE no overcast 64 65 TRUE yes sunny 72 95 FALSE

决策树-预测隐形眼镜类型 (ID3算法,C4.5算法,CART算法,GINI指数,剪枝,随机森林)

1. 1.问题的引入 2.一个实例 3.基本概念 4.ID3 5.C4.5 6.CART 7.随机森林 2. 我们应该设计什么的算法,使得计算机对贷款申请人员的申请信息自动进行分类,以决定能否贷款? 一个女孩的母亲要给这个女孩介绍男朋友,于是有了下面的对话: 女儿:多大年纪了? 母亲:26. 女儿:长的帅不帅? 母亲:挺帅的. 女儿:收入高不? 母亲:不算很高,中等情况. 女儿:是公务员不? 母亲:是,在税务局上班呢. 女儿:那好,我去见见. 决策过程: 这个女孩的决策过程就是典型的分类树决策.

决策树ID3算法的java实现(基本试用所有的ID3)

已知:流感训练数据集,预定义两个类别: 求:用ID3算法建立流感的属性描述决策树 流感训练数据集 No. 头痛 肌肉痛 体温 患流感 1 是(1) 是(1) 正常(0) 否(0) 2 是(1) 是(1) 高(1) 是(1) 3 是(1) 是(1) 很高(2) 是(1) 4 否(0) 是(1) 正常(0) 否(0) 5 否(0) 否(0) 高(1) 否(0) 6 否(0) 是(1) 很高(2) 是(1) 7 是(1) 否(0) 高(1) 是(1) 原理分析: 在决策树的每一个非叶子结点划分之前,先

决策树ID3算法[分类算法]

ID3分类算法的编码实现 1 <?php 2 /* 3 *决策树ID3算法(分类算法的实现) 4 */ 5 6 /* 7 *把.txt中的内容读到数组中保存 8 *$filename:文件名称 9 */ 10 11 //-------------------------------------------------------------------- 12 function gerFileContent($filename) 13 { 14 $array = array(NULL); 15

决策树的基本ID3算法

一  ID3算法的大致思想 基本的ID3算法是通过自顶向下构造决策树来进行学习的.我们首先思考的是树的构造从哪里开始,这就涉及到选择属性进行树的构造了,那么怎样选择属性呢?为了解决这个问题,我们使用统计测试来确定每一个实例属性单独分类训练样例的能力,把分类能力最好的属性作为树根节点的测试.然后为根节点属性的每个可能值产生一个分支,并把训练样例排列到适当的分支之下.然后重复整个过程,用每个分支节点关联的训练样例来选取在该点被测试的最佳属性.这形成了对合格决策树的贪婪搜索,也就是算法从不回溯重新考虑

决策树 -- ID3算法小结

ID3算法(Iterative Dichotomiser 3 迭代二叉树3代),是一个由Ross Quinlan发明的用于决策树的算法:简单理论是越是小型的决策树越优于大的决策树. 算法归纳: 1.使用所有没有使用的属性并计算与之相关的样本熵值: 2.选取其中熵值最小的属性 3.生成包含该属性的节点 4.使用新的分支表继续前面步骤 ID3算法以信息论为基础,以信息熵和信息增益为衡量标准,从而实现对数据的归纳分类:所以归根结底,是为了从一堆数据中生成决策树而采取的一种归纳方式: 具体介绍: 1.信

决策树ID3算法的java实现

决策树的分类过程和人的决策过程比较相似,就是先挑“权重”最大的那个考虑,然后再往下细分.比如你去看医生,症状是流鼻涕,咳嗽等,那么医生就会根据你的流鼻涕这个权重最大的症状先认为你是感冒,接着再根据你咳嗽等症状细分你是否为病毒性感冒等等.决策树的过程其实也是基于极大似然估计.那么我们用一个什么标准来衡量某个特征是权重最大的呢,这里有信息增益和基尼系数两个.ID3算法采用的是信息增益这个量. 根据<统计学习方法>中的描述,G(D,A)表示数据集D在特征A的划分下的信息增益.具体公式: G(D,A)

数据挖掘之决策树ID3算法(C#实现)

决策树是一种非常经典的分类器,它的作用原理有点类似于我们玩的猜谜游戏.比如猜一个动物: 问:这个动物是陆生动物吗? 答:是的. 问:这个动物有鳃吗? 答:没有. 这样的两个问题顺序就有些颠倒,因为一般来说陆生动物是没有鳃的(记得应该是这样的,如有错误欢迎指正).所以玩这种游戏,提问的顺序很重要,争取每次都能够获得尽可能多的信息量. AllElectronics顾客数据库标记类的训练元组 RID age income student credit_rating Class: buys_comput

[转载]简单易学的机器学习算法-决策树之ID3算的

一.决策树分类算法概述 决策树算法是从数据的属性(或者特征)出发,以属性作为基础,划分不同的类.例如对于如下数据集 (数据集) 其中,第一列和第二列为属性(特征),最后一列为类别标签,1表示是,0表示否.决策树算法的思想是基于属性对数据分类,对于以上的数据我们可以得到以下的决策树模型 (决策树模型) 先是根据第一个属性将一部份数据区分开,再根据第二个属性将剩余的区分开. 实现决策树的算法有很多种,有ID3.C4.5和CART等算法.下面我们介绍ID3算法. 二.ID3算法的概述 ID3算法是由Q