【转】决策树C4.5算法

来源:互联网 发布:mac清理破解版 编辑:程序博客网 时间:2024/05/28 11:49
 
Java代码
  1. 数据挖掘中决策树C4.5预测算法实现(半成品,还要写规则后煎支及对非离散数据信息增益计算),下一篇博客讲原理  

Java代码
  1. package org.struct.decisiontree;   
  2.   
  3. import java.util.ArrayList;   
  4. import java.util.Arrays;   
  5. import java.util.List;   
  6. import java.util.TreeSet;   
  7.   
  8. /**  
  9.  * @author Leon.Chen  
  10.  */  
  11. public class DecisionTreeBaseC4p5 {   
  12.        
  13.     /**  
  14.      * root node  
  15.      */  
  16.     private DecisionTreeNode root;   
  17.   
  18.     /**  
  19.      * visableArray  
  20.      */  
  21.     private boolean[] visable;   
  22.   
  23.     private static final int NOT_FOUND = -1;   
  24.   
  25.     private static final int DATA_START_LINE = 1;   
  26.   
  27.     private Object[] trainingArray;   
  28.   
  29.     private String[] columnHeaderArray;   
  30.   
  31.     /**  
  32.      * forecast node index  
  33.      */  
  34.     private int nodeIndex;   
  35.   
  36.     /**  
  37.      * @param args  
  38.      */  
  39.     @SuppressWarnings("boxing")   
  40.     public static void main(String[] args) {   
  41.         Object[] array = new Object[] {   
  42.                 new String[] { "age",          "income",   "student""credit_rating""buys_computer" },   
  43.                 new String[] { "youth",        "high",     "no",      "fair",          "no"  },   
  44.                 new String[] { "youth",        "high",     "no",      "excellent",     "no"  },   
  45.                 new String[] { "middle_aged",  "high",     "no",      "fair",          "yes" },   
  46.                 new String[] { "senior",       "medium",   "no",      "fair",          "yes" },   
  47.                 new String[] { "senior",       "low",      "yes",     "fair",          "yes" },   
  48.                 new String[] { "senior",       "low",      "yes",     "excellent",     "no"  },   
  49.                 new String[] { "middle_aged",  "low",      "yes",     "excellent",     "yes" },   
  50.                 new String[] { "youth",        "medium",   "no",      "fair",          "no"  },   
  51.                 new String[] { "youth",        "low",      "yes",     "fair",          "yes" },   
  52.                 new String[] { "senior",       "medium",   "yes",     "fair",          "yes" },   
  53.                 new String[] { "youth",        "medium",   "yes",     "excellent",     "yes" },   
  54.                 new String[] { "middle_aged",  "medium",   "no",      "excellent",     "yes" },   
  55.                 new String[] { "middle_aged",  "high",     "yes",     "fair",          "yes" },   
  56.                 new String[] { "senior",       "medium",   "no",      "excellent",     "no"  },   
  57.         };   
  58.   
  59.         DecisionTreeBaseC4p5 tree = new DecisionTreeBaseC4p5();   
  60.         tree.create(array, 4);   
  61.         System.out.println("===============END PRINT TREE===============");   
  62.         System.out.println("===============DECISION RESULT===============");   
  63.         //tree.forecast(printData, tree.root);  
  64.     }   
  65.   
  66.     /**  
  67.      * @param printData  
  68.      * @param node  
  69.      */  
  70.     public void forecast(String[] printData, DecisionTreeNode node) {   
  71.         int index = getColumnHeaderIndexByName(node.nodeName);   
  72.         if (index == NOT_FOUND) {   
  73.             System.out.println(node.nodeName);   
  74.         }   
  75.         DecisionTreeNode[] childs = node.childNodesArray;   
  76.         for (int i = 0; i < childs.length; i++) {   
  77.             if (childs[i] != null) {   
  78.                 if (childs[i].parentArrtibute.equals(printData[index])) {   
  79.                     forecast(printData, childs[i]);   
  80.                 }   
  81.             }   
  82.         }   
  83.     }   
  84.   
  85.     /**  
  86.      * @param array  
  87.      * @param index  
  88.      */  
  89.     public void create(Object[] array, int index) {   
  90.         this.trainingArray = Arrays.copyOfRange(array, DATA_START_LINE,   
  91.                 array.length);   
  92.         init(array, index);   
  93.         createDecisionTree(this.trainingArray);   
  94.         printDecisionTree(root);   
  95.     }   
  96.   
  97.     /**  
  98.      * @param array  
  99.      * @return Object[]  
  100.      */  
  101.     @SuppressWarnings("boxing")   
  102.     public Object[] getMaxGain(Object[] array) {   
  103.         Object[] result = new Object[2];   
  104.         double gain = 0;   
  105.         int index = -1;   
  106.   
  107.         for (int i = 0; i < visable.length; i++) {   
  108.             if (!visable[i]) {   
  109.                 //TODO ID3 change to C4.5   
  110.                 double value = gainRatio(array, i, this.nodeIndex);   
  111.                 System.out.println(value);   
  112.                 if (gain < value) {   
  113.                     gain = value;   
  114.                     index = i;   
  115.                 }   
  116.             }   
  117.         }   
  118.         result[0] = gain;   
  119.         result[1] = index;   
  120.         // TODO throws can't forecast this model exception  
  121.         if (index != -1) {   
  122.             visable[index] = true;   
  123.         }   
  124.         return result;   
  125.     }   
  126.   
  127.     /**  
  128.      * @param array  
  129.      */  
  130.     public void createDecisionTree(Object[] array) {   
  131.         Object[] maxgain = getMaxGain(array);   
  132.         if (root == null) {   
  133.             root = new DecisionTreeNode();   
  134.             root.parentNode = null;   
  135.             root.parentArrtibute = null;   
  136.             root.arrtibutesArray = getArrtibutesArray(((Integer) maxgain[1])   
  137.                     .intValue());   
  138.             root.nodeName = getColumnHeaderNameByIndex(((Integer) maxgain[1])   
  139.                     .intValue());   
  140.             root.childNodesArray = new DecisionTreeNode[root.arrtibutesArray.length];   
  141.             insertDecisionTree(array, root);   
  142.         }   
  143.     }   
  144.   
  145.     /**  
  146.      * @param array  
  147.      * @param parentNode  
  148.      */  
  149.     public void insertDecisionTree(Object[] array, DecisionTreeNode parentNode) {   
  150.         String[] arrtibutes = parentNode.arrtibutesArray;   
  151.         for (int i = 0; i < arrtibutes.length; i++) {   
  152.             Object[] pickArray = pickUpAndCreateSubArray(array, arrtibutes[i],   
  153.                     getColumnHeaderIndexByName(parentNode.nodeName));   
  154.             Object[] info = getMaxGain(pickArray);   
  155.             double gain = ((Double) info[0]).doubleValue();   
  156.             if (gain != 0) {   
  157.                 int index = ((Integer) info[1]).intValue();   
  158.                 DecisionTreeNode currentNode = new DecisionTreeNode();   
  159.                 currentNode.parentNode = parentNode;   
  160.                 currentNode.parentArrtibute = arrtibutes[i];   
  161.                 currentNode.arrtibutesArray = getArrtibutesArray(index);   
  162.                 currentNode.nodeName = getColumnHeaderNameByIndex(index);   
  163.                 currentNode.childNodesArray = new DecisionTreeNode[currentNode.arrtibutesArray.length];   
  164.                 parentNode.childNodesArray[i] = currentNode;   
  165.                 insertDecisionTree(pickArray, currentNode);   
  166.             } else {   
  167.                 DecisionTreeNode leafNode = new DecisionTreeNode();   
  168.                 leafNode.parentNode = parentNode;   
  169.                 leafNode.parentArrtibute = arrtibutes[i];   
  170.                 leafNode.arrtibutesArray = new String[0];   
  171.                 leafNode.nodeName = getLeafNodeName(pickArray,this.nodeIndex);   
  172.                 leafNode.childNodesArray = new DecisionTreeNode[0];   
  173.                 parentNode.childNodesArray[i] = leafNode;   
  174.             }   
  175.         }   
  176.     }   
  177.   
  178.     /**  
  179.      * @param node  
  180.      */  
  181.     public void printDecisionTree(DecisionTreeNode node) {   
  182.         System.out.println(node.nodeName);   
  183.         DecisionTreeNode[] childs = node.childNodesArray;   
  184.         for (int i = 0; i < childs.length; i++) {   
  185.             if (childs[i] != null) {   
  186.                 System.out.println(childs[i].parentArrtibute);   
  187.                 printDecisionTree(childs[i]);   
  188.             }   
  189.         }   
  190.     }   
  191.   
  192.     /**  
  193.      * init data  
  194.      *   
  195.      * @param dataArray  
  196.      * @param index  
  197.      */  
  198.     public void init(Object[] dataArray, int index) {   
  199.         this.nodeIndex = index;   
  200.         // init data   
  201.         this.columnHeaderArray = (String[]) dataArray[0];   
  202.         visable = new boolean[((String[]) dataArray[0]).length];   
  203.         for (int i = 0; i < visable.length; i++) {   
  204.             if (i == index) {   
  205.                 visable[i] = true;   
  206.             } else {   
  207.                 visable[i] = false;   
  208.             }   
  209.         }   
  210.     }   
  211.   
  212.     /**  
  213.      * @param array  
  214.      * @param arrtibute  
  215.      * @param index  
  216.      * @return Object[]  
  217.      */  
  218.     public Object[] pickUpAndCreateSubArray(Object[] array, String arrtibute,   
  219.             int index) {   
  220.         List<String[]> list = new ArrayList<String[]>();   
  221.         for (int i = 0; i < array.length; i++) {   
  222.             String[] strs = (String[]) array[i];   
  223.             if (strs[index].equals(arrtibute)) {   
  224.                 list.add(strs);   
  225.             }   
  226.         }   
  227.         return list.toArray();   
  228.     }   
  229.   
  230.     /**  
  231.      * gain(A)  
  232.      *   
  233.      * @param array  
  234.      * @param index  
  235.      * @return double  
  236.      */  
  237.     public double gain(Object[] array, int index, int nodeIndex) {   
  238.         int[] counts = separateToSameValueArrays(array, nodeIndex);   
  239.         String[] arrtibutes = getArrtibutesArray(index);   
  240.         double infoD = infoD(array, counts);   
  241.         double infoaD = infoaD(array, index, nodeIndex, arrtibutes);   
  242.         return infoD - infoaD;   
  243.     }   
  244.   
  245.     /**  
  246.      * @param array  
  247.      * @param nodeIndex  
  248.      * @return  
  249.      */  
  250.     public int[] separateToSameValueArrays(Object[] array, int nodeIndex) {   
  251.         String[] arrti = getArrtibutesArray(nodeIndex);   
  252.         int[] counts = new int[arrti.length];   
  253.         for (int i = 0; i < counts.length; i++) {   
  254.             counts[i] = 0;   
  255.         }   
  256.         for (int i = 0; i < array.length; i++) {   
  257.             String[] strs = (String[]) array[i];   
  258.             for (int j = 0; j < arrti.length; j++) {   
  259.                 if (strs[nodeIndex].equals(arrti[j])) {   
  260.                     counts[j]++;   
  261.                 }   
  262.             }   
  263.         }   
  264.         return counts;   
  265.     }   
  266.        
  267.     /**  
  268.      * gainRatio = gain(A)/splitInfo(A)  
  269.      *   
  270.      * @param array  
  271.      * @param index  
  272.      * @param nodeIndex  
  273.      * @return  
  274.      */  
  275.     public double gainRatio(Object[] array,int index,int nodeIndex){   
  276.         double gain = gain(array,index,nodeIndex);   
  277.         int[] counts = separateToSameValueArrays(array, index);   
  278.         double splitInfo = splitInfoaD(array,counts);   
  279.         if(splitInfo != 0){   
  280.             return gain/splitInfo;   
  281.         }   
  282.         return 0;   
  283.     }   
  284.   
  285.     /**  
  286.      * infoD = -E(pi*log2 pi)  
  287.      *   
  288.      * @param array  
  289.      * @param counts  
  290.      * @return  
  291.      */  
  292.     public double infoD(Object[] array, int[] counts) {   
  293.         double infoD = 0;   
  294.         for (int i = 0; i < counts.length; i++) {   
  295.             infoD += DecisionTreeUtil.info(counts[i], array.length);   
  296.         }   
  297.         return infoD;   
  298.     }   
  299.   
  300.     /**  
  301.      * splitInfoaD = -E|Dj|/|D|*log2(|Dj|/|D|)  
  302.      *   
  303.      * @param array  
  304.      * @param counts  
  305.      * @return  
  306.      */  
  307.     public double splitInfoaD(Object[] array, int[] counts) {   
  308.         return infoD(array, counts);   
  309.     }   
  310.   
  311.     /**  
  312.      * infoaD = E(|Dj| / |D|) * info(Dj)  
  313.      *   
  314.      * @param array  
  315.      * @param index  
  316.      * @param arrtibutes  
  317.      * @return  
  318.      */  
  319.     public double infoaD(Object[] array, int index, int nodeIndex,   
  320.             String[] arrtibutes) {   
  321.         double sv_total = 0;   
  322.         for (int i = 0; i < arrtibutes.length; i++) {   
  323.             sv_total += infoDj(array, index, nodeIndex, arrtibutes[i],   
  324.                     array.length);   
  325.         }   
  326.         return sv_total;   
  327.     }   
  328.   
  329.     /**  
  330.      * ((|Dj| / |D|) * Info(Dj))  
  331.      *   
  332.      * @param array  
  333.      * @param index  
  334.      * @param arrtibute  
  335.      * @param allTotal  
  336.      * @return double  
  337.      */  
  338.     public double infoDj(Object[] array, int index, int nodeIndex,   
  339.             String arrtibute, int allTotal) {   
  340.         String[] arrtibutes = getArrtibutesArray(nodeIndex);   
  341.         int[] counts = new int[arrtibutes.length];   
  342.         for (int i = 0; i < counts.length; i++) {   
  343.             counts[i] = 0;   
  344.         }   
  345.   
  346.         for (int i = 0; i < array.length; i++) {   
  347.             String[] strs = (String[]) array[i];   
  348.             if (strs[index].equals(arrtibute)) {   
  349.                 for (int k = 0; k < arrtibutes.length; k++) {   
  350.                     if (strs[nodeIndex].equals(arrtibutes[k])) {   
  351.                         counts[k]++;   
  352.                     }   
  353.                 }   
  354.             }   
  355.         }   
  356.   
  357.         int total = 0;   
  358.         double infoDj = 0;   
  359.         for (int i = 0; i < counts.length; i++) {   
  360.             total += counts[i];   
  361.         }   
  362.         for (int i = 0; i < counts.length; i++) {   
  363.             infoDj += DecisionTreeUtil.info(counts[i], total);   
  364.         }   
  365.         return DecisionTreeUtil.getPi(total, allTotal) * infoDj;   
  366.     }   
  367.   
  368.     /**  
  369.      * @param index  
  370.      * @return String[]  
  371.      */  
  372.     @SuppressWarnings("unchecked")   
  373.     public String[] getArrtibutesArray(int index) {   
  374.         TreeSet<String> set = new TreeSet<String>(new SequenceComparator());   
  375.         for (int i = 0; i < trainingArray.length; i++) {   
  376.             String[] strs = (String[]) trainingArray[i];   
  377.             set.add(strs[index]);   
  378.         }   
  379.         String[] result = new String[set.size()];   
  380.         return set.toArray(result);   
  381.     }   
  382.   
  383.     /**  
  384.      * @param index  
  385.      * @return String  
  386.      */  
  387.     public String getColumnHeaderNameByIndex(int index) {   
  388.         for (int i = 0; i < columnHeaderArray.length; i++) {   
  389.             if (i == index) {   
  390.                 return columnHeaderArray[i];   
  391.             }   
  392.         }   
  393.         return null;   
  394.     }   
  395.   
  396.     /**  
  397.      * @param array  
  398.      * @return String  
  399.      */  
  400.     public String getLeafNodeName(Object[] array,int nodeIndex) {   
  401.         if (array != null && array.length > 0) {   
  402.             String[] strs = (String[]) array[0];   
  403.             return strs[nodeIndex];   
  404.         }   
  405.         return null;   
  406.     }   
  407.   
  408.     /**  
  409.      * @param name  
  410.      * @return int  
  411.      */  
  412.     public int getColumnHeaderIndexByName(String name) {   
  413.         for (int i = 0; i < columnHeaderArray.length; i++) {   
  414.             if (name.equals(columnHeaderArray[i])) {   
  415.                 return i;   
  416.             }   
  417.         }   
  418.         return NOT_FOUND;   
  419.     }   
  420. }  

Java代码
  1. package org.struct.decisiontree;   
  2.   
  3. /**  
  4.  * @author Leon.Chen  
  5.  */  
  6. public class DecisionTreeNode {   
  7.   
  8.     DecisionTreeNode parentNode;   
  9.   
  10.     String parentArrtibute;   
  11.   
  12.     String nodeName;   
  13.   
  14.     String[] arrtibutesArray;   
  15.   
  16.     DecisionTreeNode[] childNodesArray;   
  17.   
  18. }  

Java代码
  1. package org.struct.decisiontree;   
  2.   
  3. /**  
  4.  * @author Leon.Chen  
  5.  */  
  6. public class DecisionTreeUtil {   
  7.   
  8.     /**  
  9.      * entropy:Info(T)=(i=1...k)pi*log(2)pi  
  10.      *   
  11.      * @param x  
  12.      * @param total  
  13.      * @return double  
  14.      */  
  15.     public static double info(int x, int total) {   
  16.         if (x == 0) {   
  17.             return 0;   
  18.         }   
  19.         double x_pi = getPi(x, total);   
  20.         return -(x_pi * logYBase2(x_pi));   
  21.     }   
  22.   
  23.     /**  
  24.      * log2y  
  25.      *   
  26.      * @param y  
  27.      * @return double  
  28.      */  
  29.     public static double logYBase2(double y) {   
  30.         return Math.log(y) / Math.log(2);   
  31.     }   
  32.   
  33.     /**  
  34.      * pi=|C(i,d)|/|D|  
  35.      *   
  36.      * @param x  
  37.      * @param total  
  38.      * @return double  
  39.      */  
  40.     public static double getPi(int x, int total) {   
  41.         return x / (double) total;   
  42.     }   
  43.   
  44. }  

Java代码
  1. package org.struct.decisiontree;   
  2.   
  3. import java.util.Comparator;   
  4.   
  5. /**  
  6.  * @author Leon.Chen  
  7.  *   
  8.  */  
  9. @SuppressWarnings("unchecked")   
  10. public class SequenceComparator implements Comparator {   
  11.   
  12.     public int compare(Object o1, Object o2) throws ClassCastException {   
  13.         String str1 = (String) o1;   
  14.         String str2 = (String) o2;   
  15.         return str1.compareTo(str2);   
  16.     }   
  17. }  
原创粉丝点击