~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/classifiers/meta/RandomCommittee.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/*
 
18
 *    RandomCommittee.java
 
19
 *    Copyright (C) 2003 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.classifiers.meta;
 
24
 
 
25
import weka.classifiers.Classifier;
 
26
import weka.classifiers.RandomizableIteratedSingleClassifierEnhancer;
 
27
import weka.core.Instance;
 
28
import weka.core.Instances;
 
29
import weka.core.Randomizable;
 
30
import weka.core.Utils;
 
31
import weka.core.WeightedInstancesHandler;
 
32
 
 
33
import java.util.Random;
 
34
 
 
35
/**
 
36
 <!-- globalinfo-start -->
 
37
 * Class for building an ensemble of randomizable base classifiers. Each base classifiers is built using a different random number seed (but based one the same data). The final prediction is a straight average of the predictions generated by the individual base classifiers.
 
38
 * <p/>
 
39
 <!-- globalinfo-end -->
 
40
 *
 
41
 <!-- options-start -->
 
42
 * Valid options are: <p/>
 
43
 * 
 
44
 * <pre> -S &lt;num&gt;
 
45
 *  Random number seed.
 
46
 *  (default 1)</pre>
 
47
 * 
 
48
 * <pre> -I &lt;num&gt;
 
49
 *  Number of iterations.
 
50
 *  (default 10)</pre>
 
51
 * 
 
52
 * <pre> -D
 
53
 *  If set, classifier is run in debug mode and
 
54
 *  may output additional info to the console</pre>
 
55
 * 
 
56
 * <pre> -W
 
57
 *  Full name of base classifier.
 
58
 *  (default: weka.classifiers.trees.RandomTree)</pre>
 
59
 * 
 
60
 * <pre> 
 
61
 * Options specific to classifier weka.classifiers.trees.RandomTree:
 
62
 * </pre>
 
63
 * 
 
64
 * <pre> -K &lt;number of attributes&gt;
 
65
 *  Number of attributes to randomly investigate
 
66
 *  (&lt;1 = int(log(#attributes)+1)).</pre>
 
67
 * 
 
68
 * <pre> -M &lt;minimum number of instances&gt;
 
69
 *  Set minimum number of instances per leaf.</pre>
 
70
 * 
 
71
 * <pre> -D
 
72
 *  Turns debugging info on.</pre>
 
73
 * 
 
74
 * <pre> -S
 
75
 *  Seed for random number generator.
 
76
 *  (default 1)</pre>
 
77
 * 
 
78
 <!-- options-end -->
 
79
 *
 
80
 * Options after -- are passed to the designated classifier.<p>
 
81
 *
 
82
 * @author Eibe Frank (eibe@cs.waikato.ac.nz)
 
83
 * @version $Revision: 1.11 $
 
84
 */
 
85
public class RandomCommittee 
 
86
  extends RandomizableIteratedSingleClassifierEnhancer
 
87
  implements WeightedInstancesHandler {
 
88
    
 
89
  /** for serialization */
 
90
  static final long serialVersionUID = -9204394360557300092L;
 
91
  
 
92
  /**
 
93
   * Constructor.
 
94
   */
 
95
  public RandomCommittee() {
 
96
    
 
97
    m_Classifier = new weka.classifiers.trees.RandomTree();
 
98
  }
 
99
 
 
100
  /**
 
101
   * String describing default classifier.
 
102
   * 
 
103
   * @return the default classifier classname
 
104
   */
 
105
  protected String defaultClassifierString() {
 
106
    
 
107
    return "weka.classifiers.trees.RandomTree";
 
108
  }
 
109
 
 
110
  /**
 
111
   * Returns a string describing classifier
 
112
   * @return a description suitable for
 
113
   * displaying in the explorer/experimenter gui
 
114
   */
 
115
  public String globalInfo() {
 
116
 
 
117
    return "Class for building an ensemble of randomizable base classifiers. Each "
 
118
      + "base classifiers is built using a different random number seed (but based "
 
119
      + "one the same data). The final prediction is a straight average of the "
 
120
      + "predictions generated by the individual base classifiers.";
 
121
  }
 
122
 
 
123
  /**
 
124
   * Builds the committee of randomizable classifiers.
 
125
   *
 
126
   * @param data the training data to be used for generating the
 
127
   * bagged classifier.
 
128
   * @exception Exception if the classifier could not be built successfully
 
129
   */
 
130
  public void buildClassifier(Instances data) throws Exception {
 
131
 
 
132
    // can classifier handle the data?
 
133
    getCapabilities().testWithFail(data);
 
134
 
 
135
    // remove instances with missing class
 
136
    data = new Instances(data);
 
137
    data.deleteWithMissingClass();
 
138
    
 
139
    if (!(m_Classifier instanceof Randomizable)) {
 
140
      throw new IllegalArgumentException("Base learner must implement Randomizable!");
 
141
    }
 
142
 
 
143
    m_Classifiers = Classifier.makeCopies(m_Classifier, m_NumIterations);
 
144
 
 
145
    Random random = data.getRandomNumberGenerator(m_Seed);
 
146
    for (int j = 0; j < m_Classifiers.length; j++) {
 
147
 
 
148
      // Set the random number seed for the current classifier.
 
149
      ((Randomizable) m_Classifiers[j]).setSeed(random.nextInt());
 
150
      
 
151
      // Build the classifier.
 
152
      m_Classifiers[j].buildClassifier(data);
 
153
    }
 
154
  }
 
155
 
 
156
  /**
 
157
   * Calculates the class membership probabilities for the given test
 
158
   * instance.
 
159
   *
 
160
   * @param instance the instance to be classified
 
161
   * @return preedicted class probability distribution
 
162
   * @exception Exception if distribution can't be computed successfully 
 
163
   */
 
164
  public double[] distributionForInstance(Instance instance) throws Exception {
 
165
 
 
166
    double [] sums = new double [instance.numClasses()], newProbs; 
 
167
    
 
168
    for (int i = 0; i < m_NumIterations; i++) {
 
169
      if (instance.classAttribute().isNumeric() == true) {
 
170
        sums[0] += m_Classifiers[i].classifyInstance(instance);
 
171
      } else {
 
172
        newProbs = m_Classifiers[i].distributionForInstance(instance);
 
173
        for (int j = 0; j < newProbs.length; j++)
 
174
          sums[j] += newProbs[j];
 
175
      }
 
176
    }
 
177
    if (instance.classAttribute().isNumeric() == true) {
 
178
      sums[0] /= (double)m_NumIterations;
 
179
      return sums;
 
180
    } else if (Utils.eq(Utils.sum(sums), 0)) {
 
181
      return sums;
 
182
    } else {
 
183
      Utils.normalize(sums);
 
184
      return sums;
 
185
    }
 
186
  }
 
187
 
 
188
  /**
 
189
   * Returns description of the committee.
 
190
   *
 
191
   * @return description of the committee as a string
 
192
   */
 
193
  public String toString() {
 
194
    
 
195
    if (m_Classifiers == null) {
 
196
      return "RandomCommittee: No model built yet.";
 
197
    }
 
198
    StringBuffer text = new StringBuffer();
 
199
    text.append("All the base classifiers: \n\n");
 
200
    for (int i = 0; i < m_Classifiers.length; i++)
 
201
      text.append(m_Classifiers[i].toString() + "\n\n");
 
202
 
 
203
    return text.toString();
 
204
  }
 
205
 
 
206
  /**
 
207
   * Main method for testing this class.
 
208
   *
 
209
   * @param argv the options
 
210
   */
 
211
  public static void main(String [] argv) {
 
212
    runClassifier(new RandomCommittee(), argv);
 
213
  }
 
214
}