C45ModelSelection.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 5k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    C45ModelSelection.java
  18.  *    Copyright (C) 1999 Eibe Frank
  19.  *
  20.  */
  21. package weka.classifiers.trees.j48;
  22. import java.util.*;
  23. import weka.core.*;
  24. /**
  25.  * Class for selecting a C4.5-type split for a given dataset.
  26.  *
  27.  * @author Eibe Frank (eibe@cs.waikato.ac.nz)
  28.  * @version $Revision: 1.7 $y
  29.  */
  30. public class C45ModelSelection extends ModelSelection {
  31.   /** Minimum number of objects in interval. */
  32.   private int m_minNoObj;               
  33.   /** All the training data */
  34.   private Instances m_allData; // 
  35.   /**
  36.    * Initializes the split selection method with the given parameters.
  37.    *
  38.    * @param minNoObj minimum number of instances that have to occur in at least two
  39.    * subsets induced by split
  40.    * @param allData FULL training dataset (necessary for
  41.    * selection of split points).
  42.    */
  43.   public C45ModelSelection(int minNoObj, Instances allData) {
  44.     m_minNoObj = minNoObj;
  45.     m_allData = allData;
  46.   }
  47.   /**
  48.    * Sets reference to training data to null.
  49.    */
  50.   public void cleanup() {
  51.     m_allData = null;
  52.   }
  53.   /**
  54.    * Selects C4.5-type split for the given dataset.
  55.    */
  56.   public final ClassifierSplitModel selectModel(Instances data){
  57.     double minResult;
  58.     double currentResult;
  59.     C45Split [] currentModel;
  60.     C45Split bestModel = null;
  61.     NoSplit noSplitModel = null;
  62.     double averageInfoGain = 0;
  63.     int validModels = 0;
  64.     boolean multiVal = true;
  65.     Distribution checkDistribution;
  66.     Attribute attribute;
  67.     double sumOfWeights;
  68.     int i;
  69.     
  70.     try{
  71.       // Check if all Instances belong to one class or if not
  72.       // enough Instances to split.
  73.       checkDistribution = new Distribution(data);
  74.       noSplitModel = new NoSplit(checkDistribution);
  75.       if (Utils.sm(checkDistribution.total(),2*m_minNoObj) ||
  76.   Utils.eq(checkDistribution.total(),
  77.    checkDistribution.perClass(checkDistribution.maxClass())))
  78. return noSplitModel;
  79.       // Check if all attributes are nominal and have a 
  80.       // lot of values.
  81.       if (m_allData != null) {
  82. Enumeration enum = data.enumerateAttributes();
  83. while (enum.hasMoreElements()) {
  84.   attribute = (Attribute) enum.nextElement();
  85.   if ((attribute.isNumeric()) ||
  86.       (Utils.sm((double)attribute.numValues(),
  87. (0.3*(double)m_allData.numInstances())))){
  88.     multiVal = false;
  89.     break;
  90.   }
  91. }
  92.       } 
  93.       currentModel = new C45Split[data.numAttributes()];
  94.       sumOfWeights = data.sumOfWeights();
  95.       // For each attribute.
  96.       for (i = 0; i < data.numAttributes(); i++){
  97. // Apart from class attribute.
  98. if (i != (data).classIndex()){
  99.   
  100.   // Get models for current attribute.
  101.   currentModel[i] = new C45Split(i,m_minNoObj,sumOfWeights);
  102.   currentModel[i].buildClassifier(data);
  103.   
  104.   // Check if useful split for current attribute
  105.   // exists and check for enumerated attributes with 
  106.   // a lot of values.
  107.   if (currentModel[i].checkModel())
  108.     if (m_allData != null) {
  109.       if ((data.attribute(i).isNumeric()) ||
  110.   (multiVal || Utils.sm((double)data.attribute(i).numValues(),
  111. (0.3*(double)m_allData.numInstances())))){
  112. averageInfoGain = averageInfoGain+currentModel[i].infoGain();
  113. validModels++;
  114.       } 
  115.     } else {
  116.       averageInfoGain = averageInfoGain+currentModel[i].infoGain();
  117.       validModels++;
  118.     }
  119. }else
  120.   currentModel[i] = null;
  121.       }
  122.       
  123.       // Check if any useful split was found.
  124.       if (validModels == 0)
  125. return noSplitModel;
  126.       averageInfoGain = averageInfoGain/(double)validModels;
  127.       // Find "best" attribute to split on.
  128.       minResult = 0;
  129.       for (i=0;i<data.numAttributes();i++){
  130. if ((i != (data).classIndex()) &&
  131.     (currentModel[i].checkModel()))
  132.   
  133.   // Use 1E-3 here to get a closer approximation to the original
  134.   // implementation.
  135.   if ((currentModel[i].infoGain() >= (averageInfoGain-1E-3)) &&
  136.       Utils.gr(currentModel[i].gainRatio(),minResult)){ 
  137.     bestModel = currentModel[i];
  138.     minResult = currentModel[i].gainRatio();
  139.   } 
  140.       }
  141.       // Check if useful split was found.
  142.       if (Utils.eq(minResult,0))
  143. return noSplitModel;
  144.       
  145.       // Add all Instances with unknown values for the corresponding
  146.       // attribute to the distribution for the model, so that
  147.       // the complete distribution is stored with the model. 
  148.       bestModel.distribution().
  149.   addInstWithUnknown(data,bestModel.attIndex());
  150.       
  151.       // Set the split point analogue to C45 if attribute numeric.
  152.       if (m_allData != null)
  153. bestModel.setSplitPoint(m_allData);
  154.       return bestModel;
  155.     }catch(Exception e){
  156.       e.printStackTrace();
  157.     }
  158.     return null;
  159.   }
  160.   /**
  161.    * Selects C4.5-type split for the given dataset.
  162.    */
  163.   public final ClassifierSplitModel selectModel(Instances train, Instances test) {
  164.     return selectModel(train);
  165.   }
  166. }