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

« back to all changes in this revision

Viewing changes to weka/classifiers/BVDecompose.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
 *    BVDecompose.java
 
19
 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.classifiers;
 
24
 
 
25
import weka.core.Attribute;
 
26
import weka.core.Instance;
 
27
import weka.core.Instances;
 
28
import weka.core.Option;
 
29
import weka.core.OptionHandler;
 
30
import weka.core.TechnicalInformation;
 
31
import weka.core.TechnicalInformation.Type;
 
32
import weka.core.TechnicalInformation.Field;
 
33
import weka.core.TechnicalInformationHandler;
 
34
import weka.core.Utils;
 
35
 
 
36
import java.io.BufferedReader;
 
37
import java.io.FileReader;
 
38
import java.io.Reader;
 
39
import java.util.Enumeration;
 
40
import java.util.Random;
 
41
import java.util.Vector;
 
42
 
 
43
/**
 
44
 <!-- globalinfo-start -->
 
45
 * Class for performing a Bias-Variance decomposition on any classifier using the method specified in:<br/>
 
46
 * <br/>
 
47
 * Ron Kohavi, David H. Wolpert: Bias Plus Variance Decomposition for Zero-One Loss Functions. In: Machine Learning: Proceedings of the Thirteenth International Conference, 275-283, 1996.
 
48
 * <p/>
 
49
 <!-- globalinfo-end -->
 
50
 * 
 
51
 <!-- technical-bibtex-start -->
 
52
 * BibTeX:
 
53
 * <pre>
 
54
 * &#64;inproceedings{Kohavi1996,
 
55
 *    author = {Ron Kohavi and David H. Wolpert},
 
56
 *    booktitle = {Machine Learning: Proceedings of the Thirteenth International Conference},
 
57
 *    editor = {Lorenza Saitta},
 
58
 *    pages = {275-283},
 
59
 *    publisher = {Morgan Kaufmann},
 
60
 *    title = {Bias Plus Variance Decomposition for Zero-One Loss Functions},
 
61
 *    year = {1996},
 
62
 *    PS = {http://robotics.stanford.edu/\~ronnyk/biasVar.ps}
 
63
 * }
 
64
 * </pre>
 
65
 * <p/>
 
66
 <!-- technical-bibtex-end -->
 
67
 *
 
68
 <!-- options-start -->
 
69
 * Valid options are: <p/>
 
70
 * 
 
71
 * <pre> -c &lt;class index&gt;
 
72
 *  The index of the class attribute.
 
73
 *  (default last)</pre>
 
74
 * 
 
75
 * <pre> -t &lt;name of arff file&gt;
 
76
 *  The name of the arff file used for the decomposition.</pre>
 
77
 * 
 
78
 * <pre> -T &lt;training pool size&gt;
 
79
 *  The number of instances placed in the training pool.
 
80
 *  The remainder will be used for testing. (default 100)</pre>
 
81
 * 
 
82
 * <pre> -s &lt;seed&gt;
 
83
 *  The random number seed used.</pre>
 
84
 * 
 
85
 * <pre> -x &lt;num&gt;
 
86
 *  The number of training repetitions used.
 
87
 *  (default 50)</pre>
 
88
 * 
 
89
 * <pre> -D
 
90
 *  Turn on debugging output.</pre>
 
91
 * 
 
92
 * <pre> -W &lt;classifier class name&gt;
 
93
 *  Full class name of the learner used in the decomposition.
 
94
 *  eg: weka.classifiers.bayes.NaiveBayes</pre>
 
95
 * 
 
96
 * <pre> 
 
97
 * Options specific to learner weka.classifiers.rules.ZeroR:
 
98
 * </pre>
 
99
 * 
 
100
 * <pre> -D
 
101
 *  If set, classifier is run in debug mode and
 
102
 *  may output additional info to the console</pre>
 
103
 * 
 
104
 <!-- options-end -->
 
105
 *
 
106
 * Options after -- are passed to the designated sub-learner. <p>
 
107
 *
 
108
 * @author Len Trigg (trigg@cs.waikato.ac.nz)
 
109
 * @version $Revision: 1.14 $
 
110
 */
 
111
public class BVDecompose
 
112
  implements OptionHandler, TechnicalInformationHandler {
 
113
 
 
114
  /** Debugging mode, gives extra output if true */
 
115
  protected boolean m_Debug;
 
116
 
 
117
  /** An instantiated base classifier used for getting and testing options. */
 
118
  protected Classifier m_Classifier = new weka.classifiers.rules.ZeroR();
 
119
 
 
120
  /** The options to be passed to the base classifier. */
 
121
  protected String [] m_ClassifierOptions;
 
122
 
 
123
  /** The number of train iterations */
 
124
  protected int m_TrainIterations = 50;
 
125
 
 
126
  /** The name of the data file used for the decomposition */
 
127
  protected String m_DataFileName;
 
128
 
 
129
  /** The index of the class attribute */
 
130
  protected int m_ClassIndex = -1;
 
131
 
 
132
  /** The random number seed */
 
133
  protected int m_Seed = 1;
 
134
 
 
135
  /** The calculated bias (squared) */
 
136
  protected double m_Bias;
 
137
 
 
138
  /** The calculated variance */
 
139
  protected double m_Variance;
 
140
 
 
141
  /** The calculated sigma (squared) */
 
142
  protected double m_Sigma;
 
143
 
 
144
  /** The error rate */
 
145
  protected double m_Error;
 
146
 
 
147
  /** The number of instances used in the training pool */
 
148
  protected int m_TrainPoolSize = 100;
 
149
  
 
150
  /**
 
151
   * Returns a string describing this object
 
152
   * @return a description of the classifier suitable for
 
153
   * displaying in the explorer/experimenter gui
 
154
   */
 
155
  public String globalInfo() {
 
156
 
 
157
    return 
 
158
        "Class for performing a Bias-Variance decomposition on any classifier "
 
159
      + "using the method specified in:\n\n"
 
160
      + getTechnicalInformation().toString();
 
161
  }
 
162
 
 
163
  /**
 
164
   * Returns an instance of a TechnicalInformation object, containing 
 
165
   * detailed information about the technical background of this class,
 
166
   * e.g., paper reference or book this class is based on.
 
167
   * 
 
168
   * @return the technical information about this class
 
169
   */
 
170
  public TechnicalInformation getTechnicalInformation() {
 
171
    TechnicalInformation        result;
 
172
    
 
173
    result = new TechnicalInformation(Type.INPROCEEDINGS);
 
174
    result.setValue(Field.AUTHOR, "Ron Kohavi and David H. Wolpert");
 
175
    result.setValue(Field.YEAR, "1996");
 
176
    result.setValue(Field.TITLE, "Bias Plus Variance Decomposition for Zero-One Loss Functions");
 
177
    result.setValue(Field.BOOKTITLE, "Machine Learning: Proceedings of the Thirteenth International Conference");
 
178
    result.setValue(Field.PUBLISHER, "Morgan Kaufmann");
 
179
    result.setValue(Field.EDITOR, "Lorenza Saitta");
 
180
    result.setValue(Field.PAGES, "275-283");
 
181
    result.setValue(Field.PS, "http://robotics.stanford.edu/~ronnyk/biasVar.ps");
 
182
 
 
183
    return result;
 
184
  }
 
185
 
 
186
  /**
 
187
   * Returns an enumeration describing the available options.
 
188
   *
 
189
   * @return an enumeration of all the available options.
 
190
   */
 
191
  public Enumeration listOptions() {
 
192
 
 
193
    Vector newVector = new Vector(7);
 
194
 
 
195
    newVector.addElement(new Option(
 
196
              "\tThe index of the class attribute.\n"+
 
197
              "\t(default last)",
 
198
              "c", 1, "-c <class index>"));
 
199
    newVector.addElement(new Option(
 
200
              "\tThe name of the arff file used for the decomposition.",
 
201
              "t", 1, "-t <name of arff file>"));
 
202
    newVector.addElement(new Option(
 
203
              "\tThe number of instances placed in the training pool.\n"
 
204
              + "\tThe remainder will be used for testing. (default 100)",
 
205
              "T", 1, "-T <training pool size>"));
 
206
    newVector.addElement(new Option(
 
207
              "\tThe random number seed used.",
 
208
              "s", 1, "-s <seed>"));
 
209
    newVector.addElement(new Option(
 
210
              "\tThe number of training repetitions used.\n"
 
211
              +"\t(default 50)",
 
212
              "x", 1, "-x <num>"));
 
213
    newVector.addElement(new Option(
 
214
              "\tTurn on debugging output.",
 
215
              "D", 0, "-D"));
 
216
    newVector.addElement(new Option(
 
217
              "\tFull class name of the learner used in the decomposition.\n"
 
218
              +"\teg: weka.classifiers.bayes.NaiveBayes",
 
219
              "W", 1, "-W <classifier class name>"));
 
220
 
 
221
    if ((m_Classifier != null) &&
 
222
        (m_Classifier instanceof OptionHandler)) {
 
223
      newVector.addElement(new Option(
 
224
                                      "",
 
225
                                      "", 0, "\nOptions specific to learner "
 
226
                                      + m_Classifier.getClass().getName()
 
227
                                      + ":"));
 
228
      Enumeration enu = ((OptionHandler)m_Classifier).listOptions();
 
229
      while (enu.hasMoreElements()) {
 
230
        newVector.addElement(enu.nextElement());
 
231
      }
 
232
    }
 
233
    return newVector.elements();
 
234
  }
 
235
 
 
236
  /**
 
237
   * Parses a given list of options. <p/>
 
238
   *
 
239
   <!-- options-start -->
 
240
   * Valid options are: <p/>
 
241
   * 
 
242
   * <pre> -c &lt;class index&gt;
 
243
   *  The index of the class attribute.
 
244
   *  (default last)</pre>
 
245
   * 
 
246
   * <pre> -t &lt;name of arff file&gt;
 
247
   *  The name of the arff file used for the decomposition.</pre>
 
248
   * 
 
249
   * <pre> -T &lt;training pool size&gt;
 
250
   *  The number of instances placed in the training pool.
 
251
   *  The remainder will be used for testing. (default 100)</pre>
 
252
   * 
 
253
   * <pre> -s &lt;seed&gt;
 
254
   *  The random number seed used.</pre>
 
255
   * 
 
256
   * <pre> -x &lt;num&gt;
 
257
   *  The number of training repetitions used.
 
258
   *  (default 50)</pre>
 
259
   * 
 
260
   * <pre> -D
 
261
   *  Turn on debugging output.</pre>
 
262
   * 
 
263
   * <pre> -W &lt;classifier class name&gt;
 
264
   *  Full class name of the learner used in the decomposition.
 
265
   *  eg: weka.classifiers.bayes.NaiveBayes</pre>
 
266
   * 
 
267
   * <pre> 
 
268
   * Options specific to learner weka.classifiers.rules.ZeroR:
 
269
   * </pre>
 
270
   * 
 
271
   * <pre> -D
 
272
   *  If set, classifier is run in debug mode and
 
273
   *  may output additional info to the console</pre>
 
274
   * 
 
275
   <!-- options-end -->
 
276
   *
 
277
   * Options after -- are passed to the designated sub-learner. <p>
 
278
   *
 
279
   * @param options the list of options as an array of strings
 
280
   * @throws Exception if an option is not supported
 
281
   */
 
282
  public void setOptions(String[] options) throws Exception {
 
283
 
 
284
    setDebug(Utils.getFlag('D', options));
 
285
        
 
286
    String classIndex = Utils.getOption('c', options);
 
287
    if (classIndex.length() != 0) {
 
288
      if (classIndex.toLowerCase().equals("last")) {
 
289
        setClassIndex(0);
 
290
      } else if (classIndex.toLowerCase().equals("first")) {
 
291
        setClassIndex(1);
 
292
      } else {
 
293
        setClassIndex(Integer.parseInt(classIndex));
 
294
      }
 
295
    } else {
 
296
      setClassIndex(0);
 
297
    }
 
298
 
 
299
    String trainIterations = Utils.getOption('x', options);
 
300
    if (trainIterations.length() != 0) {
 
301
      setTrainIterations(Integer.parseInt(trainIterations));
 
302
    } else {
 
303
      setTrainIterations(50);
 
304
    }
 
305
 
 
306
    String trainPoolSize = Utils.getOption('T', options);
 
307
    if (trainPoolSize.length() != 0) {
 
308
      setTrainPoolSize(Integer.parseInt(trainPoolSize));
 
309
    } else {
 
310
      setTrainPoolSize(100);
 
311
    }
 
312
 
 
313
    String seedString = Utils.getOption('s', options);
 
314
    if (seedString.length() != 0) {
 
315
      setSeed(Integer.parseInt(seedString));
 
316
    } else {
 
317
      setSeed(1);
 
318
    }
 
319
 
 
320
    String dataFile = Utils.getOption('t', options);
 
321
    if (dataFile.length() == 0) {
 
322
      throw new Exception("An arff file must be specified"
 
323
                          + " with the -t option.");
 
324
    }
 
325
    setDataFileName(dataFile);
 
326
 
 
327
    String classifierName = Utils.getOption('W', options);
 
328
    if (classifierName.length() == 0) {
 
329
      throw new Exception("A learner must be specified with the -W option.");
 
330
    }
 
331
    setClassifier(Classifier.forName(classifierName,
 
332
                                     Utils.partitionOptions(options)));
 
333
  }
 
334
 
 
335
  /**
 
336
   * Gets the current settings of the CheckClassifier.
 
337
   *
 
338
   * @return an array of strings suitable for passing to setOptions
 
339
   */
 
340
  public String [] getOptions() {
 
341
 
 
342
    String [] classifierOptions = new String [0];
 
343
    if ((m_Classifier != null) && 
 
344
        (m_Classifier instanceof OptionHandler)) {
 
345
      classifierOptions = ((OptionHandler)m_Classifier).getOptions();
 
346
    }
 
347
    String [] options = new String [classifierOptions.length + 14];
 
348
    int current = 0;
 
349
    if (getDebug()) {
 
350
      options[current++] = "-D";
 
351
    }
 
352
    options[current++] = "-c"; options[current++] = "" + getClassIndex();
 
353
    options[current++] = "-x"; options[current++] = "" + getTrainIterations();
 
354
    options[current++] = "-T"; options[current++] = "" + getTrainPoolSize();
 
355
    options[current++] = "-s"; options[current++] = "" + getSeed();
 
356
    if (getDataFileName() != null) {
 
357
      options[current++] = "-t"; options[current++] = "" + getDataFileName();
 
358
    }
 
359
    if (getClassifier() != null) {
 
360
      options[current++] = "-W";
 
361
      options[current++] = getClassifier().getClass().getName();
 
362
    }
 
363
    options[current++] = "--";
 
364
    System.arraycopy(classifierOptions, 0, options, current, 
 
365
                     classifierOptions.length);
 
366
    current += classifierOptions.length;
 
367
    while (current < options.length) {
 
368
      options[current++] = "";
 
369
    }
 
370
    return options;
 
371
  }
 
372
  
 
373
  /**
 
374
   * Get the number of instances in the training pool.
 
375
   *
 
376
   * @return number of instances in the training pool.
 
377
   */
 
378
  public int getTrainPoolSize() {
 
379
    
 
380
    return m_TrainPoolSize;
 
381
  }
 
382
  
 
383
  /**
 
384
   * Set the number of instances in the training pool.
 
385
   *
 
386
   * @param numTrain number of instances in the training pool.
 
387
   */
 
388
  public void setTrainPoolSize(int numTrain) {
 
389
    
 
390
    m_TrainPoolSize = numTrain;
 
391
  }
 
392
  
 
393
  /**
 
394
   * Set the classifiers being analysed
 
395
   *
 
396
   * @param newClassifier the Classifier to use.
 
397
   */
 
398
  public void setClassifier(Classifier newClassifier) {
 
399
 
 
400
    m_Classifier = newClassifier;
 
401
  }
 
402
 
 
403
  /**
 
404
   * Gets the name of the classifier being analysed
 
405
   *
 
406
   * @return the classifier being analysed.
 
407
   */
 
408
  public Classifier getClassifier() {
 
409
 
 
410
    return m_Classifier;
 
411
  }
 
412
 
 
413
  /**
 
414
   * Sets debugging mode
 
415
   *
 
416
   * @param debug true if debug output should be printed
 
417
   */
 
418
  public void setDebug(boolean debug) {
 
419
 
 
420
    m_Debug = debug;
 
421
  }
 
422
 
 
423
  /**
 
424
   * Gets whether debugging is turned on
 
425
   *
 
426
   * @return true if debugging output is on
 
427
   */
 
428
  public boolean getDebug() {
 
429
 
 
430
    return m_Debug;
 
431
  }
 
432
 
 
433
  /**
 
434
   * Sets the random number seed
 
435
   * 
 
436
   * @param seed the random number seed
 
437
   */
 
438
  public void setSeed(int seed) {
 
439
 
 
440
    m_Seed = seed;
 
441
  }
 
442
 
 
443
  /**
 
444
   * Gets the random number seed
 
445
   *
 
446
   * @return the random number seed
 
447
   */
 
448
  public int getSeed() {
 
449
 
 
450
    return m_Seed;
 
451
  }
 
452
 
 
453
  /**
 
454
   * Sets the maximum number of boost iterations
 
455
   * 
 
456
   * @param trainIterations the number of boost iterations
 
457
   */
 
458
  public void setTrainIterations(int trainIterations) {
 
459
 
 
460
    m_TrainIterations = trainIterations;
 
461
  }
 
462
 
 
463
  /**
 
464
   * Gets the maximum number of boost iterations
 
465
   *
 
466
   * @return the maximum number of boost iterations
 
467
   */
 
468
  public int getTrainIterations() {
 
469
 
 
470
    return m_TrainIterations;
 
471
  }
 
472
 
 
473
  /**
 
474
   * Sets the name of the data file used for the decomposition
 
475
   * 
 
476
   * @param dataFileName the data file to use
 
477
   */
 
478
  public void setDataFileName(String dataFileName) {
 
479
 
 
480
    m_DataFileName = dataFileName;
 
481
  }
 
482
 
 
483
  /**
 
484
   * Get the name of the data file used for the decomposition
 
485
   *
 
486
   * @return the name of the data file
 
487
   */
 
488
  public String getDataFileName() {
 
489
 
 
490
    return m_DataFileName;
 
491
  }
 
492
 
 
493
  /**
 
494
   * Get the index (starting from 1) of the attribute used as the class.
 
495
   *
 
496
   * @return the index of the class attribute
 
497
   */
 
498
  public int getClassIndex() {
 
499
 
 
500
    return m_ClassIndex + 1;
 
501
  }
 
502
 
 
503
  /**
 
504
   * Sets index of attribute to discretize on
 
505
   *
 
506
   * @param classIndex the index (starting from 1) of the class attribute
 
507
   */
 
508
  public void setClassIndex(int classIndex) {
 
509
 
 
510
    m_ClassIndex = classIndex - 1;
 
511
  }
 
512
 
 
513
  /**
 
514
   * Get the calculated bias squared
 
515
   *
 
516
   * @return the bias squared
 
517
   */
 
518
  public double getBias() {
 
519
 
 
520
    return m_Bias;
 
521
  } 
 
522
 
 
523
  /**
 
524
   * Get the calculated variance
 
525
   *
 
526
   * @return the variance
 
527
   */
 
528
  public double getVariance() {
 
529
 
 
530
    return m_Variance;
 
531
  }
 
532
 
 
533
  /**
 
534
   * Get the calculated sigma squared
 
535
   *
 
536
   * @return the sigma squared
 
537
   */
 
538
  public double getSigma() {
 
539
 
 
540
    return m_Sigma;
 
541
  }
 
542
 
 
543
  /**
 
544
   * Get the calculated error rate
 
545
   *
 
546
   * @return the error rate
 
547
   */
 
548
  public double getError() {
 
549
 
 
550
    return m_Error;
 
551
  }
 
552
 
 
553
  /**
 
554
   * Carry out the bias-variance decomposition
 
555
   *
 
556
   * @throws Exception if the decomposition couldn't be carried out
 
557
   */
 
558
  public void decompose() throws Exception {
 
559
 
 
560
    Reader dataReader = new BufferedReader(new FileReader(m_DataFileName));
 
561
    Instances data = new Instances(dataReader);
 
562
 
 
563
    if (m_ClassIndex < 0) {
 
564
      data.setClassIndex(data.numAttributes() - 1);
 
565
    } else {
 
566
      data.setClassIndex(m_ClassIndex);
 
567
    }
 
568
    if (data.classAttribute().type() != Attribute.NOMINAL) {
 
569
      throw new Exception("Class attribute must be nominal");
 
570
    }
 
571
    int numClasses = data.numClasses();
 
572
 
 
573
    data.deleteWithMissingClass();
 
574
    if (data.checkForStringAttributes()) {
 
575
      throw new Exception("Can't handle string attributes!");
 
576
    }
 
577
 
 
578
    if (data.numInstances() < 2 * m_TrainPoolSize) {
 
579
      throw new Exception("The dataset must contain at least "
 
580
                          + (2 * m_TrainPoolSize) + " instances");
 
581
    }
 
582
    Random random = new Random(m_Seed);
 
583
    data.randomize(random);
 
584
    Instances trainPool = new Instances(data, 0, m_TrainPoolSize);
 
585
    Instances test = new Instances(data, m_TrainPoolSize, 
 
586
                                   data.numInstances() - m_TrainPoolSize);
 
587
    int numTest = test.numInstances();
 
588
    double [][] instanceProbs = new double [numTest][numClasses];
 
589
 
 
590
    m_Error = 0;
 
591
    for (int i = 0; i < m_TrainIterations; i++) {
 
592
      if (m_Debug) {
 
593
        System.err.println("Iteration " + (i + 1));
 
594
      }
 
595
      trainPool.randomize(random);
 
596
      Instances train = new Instances(trainPool, 0, m_TrainPoolSize / 2);
 
597
 
 
598
      Classifier current = Classifier.makeCopy(m_Classifier);
 
599
      current.buildClassifier(train);
 
600
 
 
601
      //// Evaluate the classifier on test, updating BVD stats
 
602
      for (int j = 0; j < numTest; j++) {
 
603
        int pred = (int)current.classifyInstance(test.instance(j));
 
604
        if (pred != test.instance(j).classValue()) {
 
605
          m_Error++;
 
606
        }
 
607
        instanceProbs[j][pred]++;
 
608
      }
 
609
    }
 
610
    m_Error /= (m_TrainIterations * numTest);
 
611
 
 
612
    // Average the BV over each instance in test.
 
613
    m_Bias = 0;
 
614
    m_Variance = 0;
 
615
    m_Sigma = 0;
 
616
    for (int i = 0; i < numTest; i++) {
 
617
      Instance current = test.instance(i);
 
618
      double [] predProbs = instanceProbs[i];
 
619
      double pActual, pPred;
 
620
      double bsum = 0, vsum = 0, ssum = 0;
 
621
      for (int j = 0; j < numClasses; j++) {
 
622
        pActual = (current.classValue() == j) ? 1 : 0; // Or via 1NN from test data?
 
623
        pPred = predProbs[j] / m_TrainIterations;
 
624
        bsum += (pActual - pPred) * (pActual - pPred) 
 
625
        - pPred * (1 - pPred) / (m_TrainIterations - 1);
 
626
        vsum += pPred * pPred;
 
627
        ssum += pActual * pActual;
 
628
      }
 
629
      m_Bias += bsum;
 
630
      m_Variance += (1 - vsum);
 
631
      m_Sigma += (1 - ssum);
 
632
    }
 
633
    m_Bias /= (2 * numTest);
 
634
    m_Variance /= (2 * numTest);
 
635
    m_Sigma /= (2 * numTest);
 
636
 
 
637
    if (m_Debug) {
 
638
      System.err.println("Decomposition finished");
 
639
    }
 
640
  }
 
641
 
 
642
 
 
643
  /**
 
644
   * Returns description of the bias-variance decomposition results.
 
645
   *
 
646
   * @return the bias-variance decomposition results as a string
 
647
   */
 
648
  public String toString() {
 
649
 
 
650
    String result = "\nBias-Variance Decomposition\n";
 
651
 
 
652
    if (getClassifier() == null) {
 
653
      return "Invalid setup";
 
654
    }
 
655
 
 
656
    result += "\nClassifier   : " + getClassifier().getClass().getName();
 
657
    if (getClassifier() instanceof OptionHandler) {
 
658
      result += Utils.joinOptions(((OptionHandler)m_Classifier).getOptions());
 
659
    }
 
660
    result += "\nData File    : " + getDataFileName();
 
661
    result += "\nClass Index  : ";
 
662
    if (getClassIndex() == 0) {
 
663
      result += "last";
 
664
    } else {
 
665
      result += getClassIndex();
 
666
    }
 
667
    result += "\nTraining Pool: " + getTrainPoolSize();
 
668
    result += "\nIterations   : " + getTrainIterations();
 
669
    result += "\nSeed         : " + getSeed();
 
670
    result += "\nError        : " + Utils.doubleToString(getError(), 6, 4);
 
671
    result += "\nSigma^2      : " + Utils.doubleToString(getSigma(), 6, 4);
 
672
    result += "\nBias^2       : " + Utils.doubleToString(getBias(), 6, 4);
 
673
    result += "\nVariance     : " + Utils.doubleToString(getVariance(), 6, 4);
 
674
 
 
675
    return result + "\n";
 
676
  }
 
677
  
 
678
 
 
679
  /**
 
680
   * Test method for this class
 
681
   *
 
682
   * @param args the command line arguments
 
683
   */
 
684
  public static void main(String [] args) {
 
685
 
 
686
    try {
 
687
      BVDecompose bvd = new BVDecompose();
 
688
 
 
689
      try {
 
690
        bvd.setOptions(args);
 
691
        Utils.checkForRemainingOptions(args);
 
692
      } catch (Exception ex) {
 
693
        String result = ex.getMessage() + "\nBVDecompose Options:\n\n";
 
694
        Enumeration enu = bvd.listOptions();
 
695
        while (enu.hasMoreElements()) {
 
696
          Option option = (Option) enu.nextElement();
 
697
          result += option.synopsis() + "\n" + option.description() + "\n";
 
698
        }
 
699
        throw new Exception(result);
 
700
      }
 
701
 
 
702
      bvd.decompose();
 
703
      System.out.println(bvd.toString());
 
704
    } catch (Exception ex) {
 
705
      System.err.println(ex.getMessage());
 
706
    }
 
707
  }
 
708
}