/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* RaceSearch.java
* Copyright (C) 2000 Mark Hall
*
*/
package weka.attributeSelection;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.Option;
import weka.core.OptionHandler;
import weka.core.SelectedTag;
import weka.core.Statistics;
import weka.core.Tag;
import weka.core.TechnicalInformation;
import weka.core.TechnicalInformation.Type;
import weka.core.TechnicalInformation.Field;
import weka.core.TechnicalInformationHandler;
import weka.core.Utils;
import weka.experiment.PairedStats;
import weka.experiment.Stats;
import java.util.BitSet;
import java.util.Enumeration;
import java.util.Random;
import java.util.Vector;
/**
<!-- globalinfo-start -->
* Races the cross validation error of competing attribute subsets. Use in conjuction with a ClassifierSubsetEval. RaceSearch has four modes:<br/>
* <br/>
* forward selection races all single attribute additions to a base set (initially no attributes), selects the winner to become the new base set and then iterates until there is no improvement over the base set. <br/>
* <br/>
* Backward elimination is similar but the initial base set has all attributes included and races all single attribute deletions. <br/>
* <br/>
* Schemata search is a bit different. Each iteration a series of races are run in parallel. Each race in a set determines whether a particular attribute should be included or not---ie the race is between the attribute being "in" or "out". The other attributes for this race are included or excluded randomly at each point in the evaluation. As soon as one race has a clear winner (ie it has been decided whether a particular attribute should be inor not) then the next set of races begins, using the result of the winning race from the previous iteration as new base set.<br/>
* <br/>
* Rank race first ranks the attributes using an attribute evaluator and then races the ranking. The race includes no attributes, the top ranked attribute, the top two attributes, the top three attributes, etc.<br/>
* <br/>
* It is also possible to generate a raked list of attributes through the forward racing process. If generateRanking is set to true then a complete forward race will be run---that is, racing continues until all attributes have been selected. The order that they are added in determines a complete ranking of all the attributes.<br/>
* <br/>
* Racing uses paired and unpaired t-tests on cross-validation errors of competing subsets. When there is a significant difference between the means of the errors of two competing subsets then the poorer of the two can be eliminated from the race. Similarly, if there is no significant difference between the mean errors of two competing subsets and they are within some threshold of each other, then one can be eliminated from the race.<br/>
* <br/>
* For more information see:<br/>
* <br/>
* Andrew W. Moore, Mary S. Lee: Efficient Algorithms for Minimizing Cross Validation Error. In: Eleventh International Conference on Machine Learning, 190-198, 1994.
* <p/>
<!-- globalinfo-end -->
*
<!-- technical-bibtex-start -->
* BibTeX:
* <pre>
* @inproceedings{Moore1994,
* author = {Andrew W. Moore and Mary S. Lee},
* booktitle = {Eleventh International Conference on Machine Learning},
* pages = {190-198},
* publisher = {Morgan Kaufmann},
* title = {Efficient Algorithms for Minimizing Cross Validation Error},
* year = {1994}
* }
* </pre>
* <p/>
<!-- technical-bibtex-end -->
*
<!-- options-start -->
* Valid options are: <p/>
*
* <pre> -R <0 = forward | 1 = backward race | 2 = schemata | 3 = rank>
* Type of race to perform.
* (default = 0).</pre>
*
* <pre> -L <significance>
* Significance level for comaparisons
* (default = 0.001(forward/backward/rank)/0.01(schemata)).</pre>
*
* <pre> -T <threshold>
* Threshold for error comparison.
* (default = 0.001).</pre>
*
* <pre> -A <attribute evaluator>
* Attribute ranker to use if doing a
* rank search. Place any
* evaluator options LAST on the
* command line following a "--".
* eg. -A weka.attributeSelection.GainRatioAttributeEval ... -- -M.
* (default = GainRatioAttributeEval)</pre>
*
* <pre> -F <0 = 10 fold | 1 = leave-one-out>
* Folds for cross validation
* (default = 0 (1 if schemata race)</pre>
*
* <pre> -Q
* Generate a ranked list of attributes.
* Forces the search to be forward
* . and races until all attributes have
* selected, thus producing a ranking.</pre>
*
* <pre> -N <num to select>
* Specify number of attributes to retain from
* the ranking. Overides -T. Use in conjunction with -Q</pre>
*
* <pre> -T <threshold>
* Specify a theshold by which attributes
* may be discarded from the ranking.
* Use in conjuction with -Q</pre>
*
* <pre> -Z
* Verbose output for monitoring the search.</pre>
*
* <pre>
* Options specific to evaluator weka.attributeSelection.GainRatioAttributeEval:
* </pre>
*
* <pre> -M
* treat missing values as a seperate value.</pre>
*
<!-- options-end -->
*
* @author Mark Hall (mhall@cs.waikato.ac.nz)
* @version $Revision: 1.20 $
*/
public class RaceSearch
extends ASSearch
implements RankedOutputSearch, OptionHandler, TechnicalInformationHandler {
/** for serialization */
static final long serialVersionUID = 4015453851212985720L;
/** the training instances */
private Instances m_Instances = null;
/** search types */
private static final int FORWARD_RACE = 0;
private static final int BACKWARD_RACE = 1;
private static final int SCHEMATA_RACE = 2;
private static final int RANK_RACE = 3;
public static final Tag [] TAGS_SELECTION = {
new Tag(FORWARD_RACE, "Forward selection race"),
new Tag(BACKWARD_RACE, "Backward elimination race"),
new Tag(SCHEMATA_RACE, "Schemata race"),
new Tag(RANK_RACE, "Rank race")
};
/** the selected search type */
private int m_raceType = FORWARD_RACE;
/** xval types */
private static final int TEN_FOLD = 0;
private static final int LEAVE_ONE_OUT = 1;
public static final Tag [] XVALTAGS_SELECTION = {
new Tag(TEN_FOLD, "10 Fold"),
new Tag(LEAVE_ONE_OUT, "Leave-one-out"),
};
/** the selected xval type */
private int m_xvalType = TEN_FOLD;
/** the class index */
private int m_classIndex;
/** the number of attributes in the data */
private int m_numAttribs;
/** the total number of partially/fully evaluated subsets */
private int m_totalEvals;
/** holds the merit of the best subset found */
private double m_bestMerit = -Double.MAX_VALUE;
/** the subset evaluator to use */
private HoldOutSubsetEvaluator m_theEvaluator = null;
/** the significance level for comparisons */
private double m_sigLevel = 0.001;
/** threshold for comparisons */
private double m_delta = 0.001;
/** the number of samples above which to begin testing for similarity
between competing subsets */
private int m_samples = 20;
/** number of cross validation folds---equal to the number of instances
for leave-one-out cv */
private int m_numFolds = 10;
/** the attribute evaluator to generate the initial ranking when
doing a rank ra