source: src/main/java/weka/experiment/PairedCorrectedTTester.java @ 23

Last change on this file since 23 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 11.0 KB
Line 
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 *    PairedCorrectedTTester.java
19 *    Copyright (C) 2003 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23
24package weka.experiment;
25
26import weka.core.Attribute;
27import weka.core.FastVector;
28import weka.core.Instance;
29import weka.core.Instances;
30import weka.core.Option;
31import weka.core.RevisionUtils;
32import weka.core.Utils;
33import weka.core.TechnicalInformation;
34import weka.core.TechnicalInformation.Type;
35import weka.core.TechnicalInformation.Field;
36import weka.core.TechnicalInformationHandler;
37
38import java.io.BufferedReader;
39import java.io.FileReader;
40import java.util.Enumeration;
41
42/**
43 * Behaves the same as PairedTTester, only it uses the corrected
44 * resampled t-test statistic.<p/>
45 *
46 * For more information see:<p/>
47 *
48 <!-- technical-plaintext-start -->
49 * Claude Nadeau, Yoshua Bengio (2001). Inference for the Generalization Error. Machine Learning..
50 <!-- technical-plaintext-end -->
51 *
52 * <p/>
53 *
54 <!-- technical-bibtex-start -->
55 * BibTeX:
56 * <pre>
57 * &#64;article{Nadeau2001,
58 *    author = {Claude Nadeau and Yoshua Bengio},
59 *    journal = {Machine Learning},
60 *    title = {Inference for the Generalization Error},
61 *    year = {2001},
62 *    PDF = {http://www.iro.umontreal.ca/\~lisa/bib/pub_subject/comparative/pointeurs/nadeau_MLJ1597.pdf}
63 * }
64 * </pre>
65 * <p/>
66 <!-- technical-bibtex-end -->
67 *
68 <!-- options-start -->
69 * Valid options are: <p/>
70 *
71 * <pre> -D &lt;index,index2-index4,...&gt;
72 *  Specify list of columns that specify a unique
73 *  dataset.
74 *  First and last are valid indexes. (default none)</pre>
75 *
76 * <pre> -R &lt;index&gt;
77 *  Set the index of the column containing the run number</pre>
78 *
79 * <pre> -F &lt;index&gt;
80 *  Set the index of the column containing the fold number</pre>
81 *
82 * <pre> -G &lt;index1,index2-index4,...&gt;
83 *  Specify list of columns that specify a unique
84 *  'result generator' (eg: classifier name and options).
85 *  First and last are valid indexes. (default none)</pre>
86 *
87 * <pre> -S &lt;significance level&gt;
88 *  Set the significance level for comparisons (default 0.05)</pre>
89 *
90 * <pre> -V
91 *  Show standard deviations</pre>
92 *
93 * <pre> -L
94 *  Produce table comparisons in Latex table format</pre>
95 *
96 * <pre> -csv
97 *  Produce table comparisons in CSV table format</pre>
98 *
99 * <pre> -html
100 *  Produce table comparisons in HTML table format</pre>
101 *
102 * <pre> -significance
103 *  Produce table comparisons with only the significance values</pre>
104 *
105 * <pre> -gnuplot
106 *  Produce table comparisons output suitable for GNUPlot</pre>
107 *
108 <!-- options-end -->
109 *
110 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
111 * @version $Revision: 1.13 $
112 */
113public class PairedCorrectedTTester 
114  extends PairedTTester
115  implements TechnicalInformationHandler {
116 
117  /** for serialization */
118  static final long serialVersionUID = -3105268939845653323L;
119
120  /**
121   * Returns an instance of a TechnicalInformation object, containing
122   * detailed information about the technical background of this class,
123   * e.g., paper reference or book this class is based on.
124   *
125   * @return the technical information about this class
126   */
127  public TechnicalInformation getTechnicalInformation() {
128    TechnicalInformation        result;
129   
130    result = new TechnicalInformation(Type.ARTICLE);
131    result.setValue(Field.AUTHOR, "Claude Nadeau and Yoshua Bengio");
132    result.setValue(Field.YEAR, "2001");
133    result.setValue(Field.TITLE, "Inference for the Generalization Error");
134    result.setValue(Field.JOURNAL, "Machine Learning");
135    result.setValue(Field.PDF, "http://www.iro.umontreal.ca/~lisa/bib/pub_subject/comparative/pointeurs/nadeau_MLJ1597.pdf");
136
137    return result;
138  }
139
140  /**
141   * Computes a paired t-test comparison for a specified dataset between
142   * two resultsets.
143   *
144   * @param datasetSpecifier the dataset specifier
145   * @param resultset1Index the index of the first resultset
146   * @param resultset2Index the index of the second resultset
147   * @param comparisonColumn the column containing values to compare
148   * @return the results of the paired comparison
149   * @throws Exception if an error occurs
150   */
151  public PairedStats calculateStatistics(Instance datasetSpecifier,
152                                         int resultset1Index,
153                                         int resultset2Index,
154                                         int comparisonColumn) throws Exception {
155
156    if (m_Instances.attribute(comparisonColumn).type()
157        != Attribute.NUMERIC) {
158      throw new Exception("Comparison column " + (comparisonColumn + 1)
159                          + " ("
160                          + m_Instances.attribute(comparisonColumn).name()
161                          + ") is not numeric");
162    }
163    if (!m_ResultsetsValid) {
164      prepareData();
165    }
166
167    Resultset resultset1 = (Resultset) m_Resultsets.elementAt(resultset1Index);
168    Resultset resultset2 = (Resultset) m_Resultsets.elementAt(resultset2Index);
169    FastVector dataset1 = resultset1.dataset(datasetSpecifier);
170    FastVector dataset2 = resultset2.dataset(datasetSpecifier);
171    String datasetName = templateString(datasetSpecifier);
172    if (dataset1 == null) {
173      throw new Exception("No results for dataset=" + datasetName
174                         + " for resultset=" + resultset1.templateString());
175    } else if (dataset2 == null) {
176      throw new Exception("No results for dataset=" + datasetName
177                         + " for resultset=" + resultset2.templateString());
178    } else if (dataset1.size() != dataset2.size()) {
179      throw new Exception("Results for dataset=" + datasetName
180                          + " differ in size for resultset="
181                          + resultset1.templateString()
182                          + " and resultset="
183                          + resultset2.templateString()
184                          );
185    }
186
187    // calculate the test/train ratio
188    double testTrainRatio = 0.0;
189    int trainSizeIndex = -1;
190    int testSizeIndex = -1;
191    // find the columns with the train/test sizes
192    for (int i=0; i<m_Instances.numAttributes(); i++) {
193      if (m_Instances.attribute(i).name().toLowerCase().equals("number_of_training_instances")) {
194        trainSizeIndex = i;
195      } else if (m_Instances.attribute(i).name().toLowerCase().equals("number_of_testing_instances")) {
196        testSizeIndex = i;
197      }
198    }
199    if (trainSizeIndex >= 0 && testSizeIndex >= 0) {
200      double totalTrainSize = 0.0;
201      double totalTestSize = 0.0;
202      for (int k = 0; k < dataset1.size(); k ++) {
203        Instance current = (Instance) dataset1.elementAt(k);
204        totalTrainSize += current.value(trainSizeIndex);
205        totalTestSize += current.value(testSizeIndex);
206      }
207      testTrainRatio = totalTestSize / totalTrainSize;
208    }
209    PairedStats pairedStats =
210      new PairedStatsCorrected(m_SignificanceLevel, testTrainRatio);
211
212    for (int k = 0; k < dataset1.size(); k ++) {
213      Instance current1 = (Instance) dataset1.elementAt(k);
214      Instance current2 = (Instance) dataset2.elementAt(k);
215      if (current1.isMissing(comparisonColumn)) {
216        System.err.println("Instance has missing value in comparison "
217                           + "column!\n" + current1);
218        continue;
219      }
220      if (current2.isMissing(comparisonColumn)) {
221        System.err.println("Instance has missing value in comparison "
222                           + "column!\n" + current2);
223        continue;
224      }
225      if (current1.value(m_RunColumn) != current2.value(m_RunColumn)) {
226        System.err.println("Run numbers do not match!\n"
227                            + current1 + current2);
228      }
229      if (m_FoldColumn != -1) {
230        if (current1.value(m_FoldColumn) != current2.value(m_FoldColumn)) {
231          System.err.println("Fold numbers do not match!\n"
232                             + current1 + current2);
233        }
234      }
235
236      double value1 = current1.value(comparisonColumn);
237      double value2 = current2.value(comparisonColumn);
238      pairedStats.add(value1, value2);
239    }
240    pairedStats.calculateDerived();
241    return pairedStats;
242  }
243
244  /**
245   * Test the class from the command line.
246   *
247   * @param args contains options for the instance ttests
248   */
249  public static void main(String args[]) {
250   
251    try {
252      PairedCorrectedTTester tt = new PairedCorrectedTTester();
253      String datasetName = Utils.getOption('t', args);
254      String compareColStr = Utils.getOption('c', args);
255      String baseColStr = Utils.getOption('b', args);
256      boolean summaryOnly = Utils.getFlag('s', args);
257      boolean rankingOnly = Utils.getFlag('r', args);
258      try {
259        if ((datasetName.length() == 0)
260            || (compareColStr.length() == 0)) {
261          throw new Exception("-t and -c options are required");
262        }
263        tt.setOptions(args);
264        Utils.checkForRemainingOptions(args);
265      } catch (Exception ex) {
266        String result = "";
267        Enumeration enu = tt.listOptions();
268        while (enu.hasMoreElements()) {
269          Option option = (Option) enu.nextElement();
270          result += option.synopsis() + '\n'
271            + option.description() + '\n';
272        }
273        throw new Exception(
274              "Usage:\n\n"
275              + "-t <file>\n"
276              + "\tSet the dataset containing data to evaluate\n"
277              + "-b <index>\n"
278              + "\tSet the resultset to base comparisons against (optional)\n"
279              + "-c <index>\n"
280              + "\tSet the column to perform a comparison on\n"
281              + "-s\n"
282              + "\tSummarize wins over all resultset pairs\n\n"
283              + "-r\n"
284              + "\tGenerate a resultset ranking\n\n"
285              + result);
286      }
287      Instances data = new Instances(new BufferedReader(
288                                  new FileReader(datasetName)));
289      tt.setInstances(data);
290      //      tt.prepareData();
291      int compareCol = Integer.parseInt(compareColStr) - 1;
292      System.out.println(tt.header(compareCol));
293      if (rankingOnly) {
294        System.out.println(tt.multiResultsetRanking(compareCol));
295      } else if (summaryOnly) {
296        System.out.println(tt.multiResultsetSummary(compareCol));
297      } else {
298        System.out.println(tt.resultsetKey());
299        if (baseColStr.length() == 0) {
300          for (int i = 0; i < tt.getNumResultsets(); i++) {
301            System.out.println(tt.multiResultsetFull(i, compareCol));
302          }
303        } else {
304          int baseCol = Integer.parseInt(baseColStr) - 1;
305          System.out.println(tt.multiResultsetFull(baseCol, compareCol));
306        }
307      }
308    } catch(Exception e) {
309      e.printStackTrace();
310      System.err.println(e.getMessage());
311    }
312  }
313
314  /**
315   * returns the name of the tester
316   *
317   * @return the display name
318   */
319  public String getDisplayName() {
320    return "Paired T-Tester (corrected)";
321  }
322
323  /**
324   * returns a string that is displayed as tooltip on the "perform test"
325   * button in the experimenter
326   *
327   * @return the string for the tool tip
328   */
329  public String getToolTipText() {
330    return "Performs test using corrected resampled t-test statistic (Nadeau and Bengio)";
331  }
332 
333  /**
334   * Returns the revision string.
335   *
336   * @return            the revision
337   */
338  public String getRevision() {
339    return RevisionUtils.extract("$Revision: 1.13 $");
340  }
341}
Note: See TracBrowser for help on using the repository browser.