source: src/main/java/weka/attributeSelection/SVMAttributeEval.java @ 14

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

Import di weka.

File size: 26.4 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 *    SVMAttributeEval.java
19 *    Copyright (C) 2002 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.attributeSelection;
24
25import weka.classifiers.functions.SMO;
26import weka.core.Capabilities;
27import weka.core.Instances;
28import weka.core.Option;
29import weka.core.OptionHandler;
30import weka.core.RevisionUtils;
31import weka.core.SelectedTag;
32import weka.core.TechnicalInformation;
33import weka.core.TechnicalInformationHandler;
34import weka.core.Utils;
35import weka.core.Capabilities.Capability;
36import weka.core.TechnicalInformation.Field;
37import weka.core.TechnicalInformation.Type;
38import weka.filters.Filter;
39import weka.filters.unsupervised.attribute.MakeIndicator;
40
41import java.util.ArrayList;
42import java.util.Enumeration;
43import java.util.Iterator;
44import java.util.Vector;
45
46/**
47 <!-- globalinfo-start -->
48 * SVMAttributeEval :<br/>
49 * <br/>
50 * Evaluates the worth of an attribute by using an SVM classifier. Attributes are ranked by the square of the weight assigned by the SVM. Attribute selection for multiclass problems is handled by ranking attributes for each class seperately using a one-vs-all method and then "dealing" from the top of each pile to give a final ranking.<br/>
51 * <br/>
52 * For more information see:<br/>
53 * <br/>
54 * I. Guyon, J. Weston, S. Barnhill, V. Vapnik (2002). Gene selection for cancer classification using support vector machines. Machine Learning. 46:389-422.
55 * <p/>
56 <!-- globalinfo-end -->
57 *
58 <!-- technical-bibtex-start -->
59 * BibTeX:
60 * <pre>
61 * &#64;article{Guyon2002,
62 *    author = {I. Guyon and J. Weston and S. Barnhill and V. Vapnik},
63 *    journal = {Machine Learning},
64 *    pages = {389-422},
65 *    title = {Gene selection for cancer classification using support vector machines},
66 *    volume = {46},
67 *    year = {2002}
68 * }
69 * </pre>
70 * <p/>
71 <!-- technical-bibtex-end -->
72 *
73 <!-- options-start -->
74 * Valid options are: <p/>
75 *
76 * <pre> -X &lt;constant rate of elimination&gt;
77 *  Specify the constant rate of attribute
78 *  elimination per invocation of
79 *  the support vector machine.
80 *  Default = 1.</pre>
81 *
82 * <pre> -Y &lt;percent rate of elimination&gt;
83 *  Specify the percentage rate of attributes to
84 *  elimination per invocation of
85 *  the support vector machine.
86 *  Trumps constant rate (above threshold).
87 *  Default = 0.</pre>
88 *
89 * <pre> -Z &lt;threshold for percent elimination&gt;
90 *  Specify the threshold below which
91 *  percentage attribute elimination
92 *  reverts to the constant method.</pre>
93 *
94 * <pre> -P &lt;epsilon&gt;
95 *  Specify the value of P (epsilon
96 *  parameter) to pass on to the
97 *  support vector machine.
98 *  Default = 1.0e-25</pre>
99 *
100 * <pre> -T &lt;tolerance&gt;
101 *  Specify the value of T (tolerance
102 *  parameter) to pass on to the
103 *  support vector machine.
104 *  Default = 1.0e-10</pre>
105 *
106 * <pre> -C &lt;complexity&gt;
107 *  Specify the value of C (complexity
108 *  parameter) to pass on to the
109 *  support vector machine.
110 *  Default = 1.0</pre>
111 *
112 * <pre> -N
113 *  Whether the SVM should 0=normalize/1=standardize/2=neither.
114 *  (default 0=normalize)</pre>
115 *
116 <!-- options-end -->
117 *
118 * @author Eibe Frank (eibe@cs.waikato.ac.nz)
119 * @author Mark Hall (mhall@cs.waikato.ac.nz)
120 * @author Kieran Holland
121 * @version $Revision: 1.28 $
122 */
123public class SVMAttributeEval 
124  extends ASEvaluation
125  implements AttributeEvaluator, 
126             OptionHandler, 
127             TechnicalInformationHandler {
128 
129  /** for serialization */
130  static final long serialVersionUID = -6489975709033967447L;
131
132  /** The attribute scores */
133  private double[] m_attScores;
134
135  /** Constant rate of attribute elimination per iteration */
136  private int m_numToEliminate = 1;
137
138  /** Percentage rate of attribute elimination, trumps constant
139      rate (above threshold), ignored if = 0  */
140  private int m_percentToEliminate = 0;
141
142  /** Threshold below which percent elimination switches to
143      constant elimination */
144  private int m_percentThreshold = 0;
145
146  /** Complexity parameter to pass on to SMO */
147  private double m_smoCParameter = 1.0;
148
149  /** Tolerance parameter to pass on to SMO */
150  private double m_smoTParameter = 1.0e-10;
151
152  /** Epsilon parameter to pass on to SMO */
153  private double m_smoPParameter = 1.0e-25;
154
155  /** Filter parameter to pass on to SMO */
156  private int m_smoFilterType = 0;
157
158  /**
159   * Returns a string describing this attribute evaluator
160   * @return a description of the evaluator suitable for
161   * displaying in the explorer/experimenter gui
162   */
163  public String globalInfo() {
164    return "SVMAttributeEval :\n\nEvaluates the worth of an attribute by "
165      + "using an SVM classifier. Attributes are ranked by the square of the "
166      + "weight assigned by the SVM. Attribute selection for multiclass "
167      + "problems is handled by ranking attributes for each class seperately "
168      + "using a one-vs-all method and then \"dealing\" from the top of "
169      + "each pile to give a final ranking.\n\n"
170      + "For more information see:\n\n"
171      + getTechnicalInformation().toString();
172  }
173
174  /**
175   * Returns an instance of a TechnicalInformation object, containing
176   * detailed information about the technical background of this class,
177   * e.g., paper reference or book this class is based on.
178   *
179   * @return the technical information about this class
180   */
181  public TechnicalInformation getTechnicalInformation() {
182    TechnicalInformation        result;
183   
184    result = new TechnicalInformation(Type.ARTICLE);
185    result.setValue(Field.AUTHOR, "I. Guyon and J. Weston and S. Barnhill and V. Vapnik");
186    result.setValue(Field.YEAR, "2002");
187    result.setValue(Field.TITLE, "Gene selection for cancer classification using support vector machines");
188    result.setValue(Field.JOURNAL, "Machine Learning");
189    result.setValue(Field.VOLUME, "46");
190    result.setValue(Field.PAGES, "389-422");
191   
192    return result;
193  }
194
195  /**
196   * Constructor
197   */
198  public SVMAttributeEval() {
199    resetOptions();
200  }
201
202  /**
203   * Returns an enumeration describing all the available options
204   *
205   * @return an enumeration of options
206   */
207  public Enumeration listOptions() {
208    Vector newVector = new Vector(4);
209
210    newVector.addElement(
211                         new Option(
212                                    "\tSpecify the constant rate of attribute\n"
213                                    + "\telimination per invocation of\n"
214                                    + "\tthe support vector machine.\n"
215                                    + "\tDefault = 1.",
216                                    "X",
217                                    1,
218                                    "-X <constant rate of elimination>"));
219
220    newVector.addElement(
221                         new Option(
222                                    "\tSpecify the percentage rate of attributes to\n"
223                                    + "\telimination per invocation of\n"
224                                    + "\tthe support vector machine.\n"
225                                    + "\tTrumps constant rate (above threshold).\n"
226                                    + "\tDefault = 0.",
227                                    "Y",
228                                    1,
229                                    "-Y <percent rate of elimination>"));
230
231    newVector.addElement(
232                         new Option(
233                                    "\tSpecify the threshold below which \n"
234                                    + "\tpercentage attribute elimination\n"
235                                    + "\treverts to the constant method.",
236                                    "Z",
237                                    1,
238                                    "-Z <threshold for percent elimination>"));
239
240
241    newVector.addElement(
242                         new Option(
243                                    "\tSpecify the value of P (epsilon\n"
244                                    + "\tparameter) to pass on to the\n"
245                                    + "\tsupport vector machine.\n"
246                                    + "\tDefault = 1.0e-25",
247                                    "P",
248                                    1,
249                                    "-P <epsilon>"));
250
251    newVector.addElement(
252                         new Option(
253                                    "\tSpecify the value of T (tolerance\n"
254                                    + "\tparameter) to pass on to the\n"
255                                    + "\tsupport vector machine.\n"
256                                    + "\tDefault = 1.0e-10",
257                                    "T",
258                                    1,
259                                    "-T <tolerance>"));
260
261    newVector.addElement(
262                         new Option(
263                                    "\tSpecify the value of C (complexity\n"
264                                    + "\tparameter) to pass on to the\n"
265                                    + "\tsupport vector machine.\n"
266                                    + "\tDefault = 1.0",
267                                    "C",
268                                    1,
269                                    "-C <complexity>"));
270
271    newVector.addElement(new Option("\tWhether the SVM should "
272                                    + "0=normalize/1=standardize/2=neither.\n"
273                                    + "\t(default 0=normalize)",
274                                    "N",
275                                    1,
276                                    "-N"));
277
278    return newVector.elements();
279  }
280
281  /**
282   * Parses a given list of options. <p/>
283   *
284   <!-- options-start -->
285   * Valid options are: <p/>
286   *
287   * <pre> -X &lt;constant rate of elimination&gt;
288   *  Specify the constant rate of attribute
289   *  elimination per invocation of
290   *  the support vector machine.
291   *  Default = 1.</pre>
292   *
293   * <pre> -Y &lt;percent rate of elimination&gt;
294   *  Specify the percentage rate of attributes to
295   *  elimination per invocation of
296   *  the support vector machine.
297   *  Trumps constant rate (above threshold).
298   *  Default = 0.</pre>
299   *
300   * <pre> -Z &lt;threshold for percent elimination&gt;
301   *  Specify the threshold below which
302   *  percentage attribute elimination
303   *  reverts to the constant method.</pre>
304   *
305   * <pre> -P &lt;epsilon&gt;
306   *  Specify the value of P (epsilon
307   *  parameter) to pass on to the
308   *  support vector machine.
309   *  Default = 1.0e-25</pre>
310   *
311   * <pre> -T &lt;tolerance&gt;
312   *  Specify the value of T (tolerance
313   *  parameter) to pass on to the
314   *  support vector machine.
315   *  Default = 1.0e-10</pre>
316   *
317   * <pre> -C &lt;complexity&gt;
318   *  Specify the value of C (complexity
319   *  parameter) to pass on to the
320   *  support vector machine.
321   *  Default = 1.0</pre>
322   *
323   * <pre> -N
324   *  Whether the SVM should 0=normalize/1=standardize/2=neither.
325   *  (default 0=normalize)</pre>
326   *
327   <!-- options-end -->
328   *
329   * @param options the list of options as an array of strings
330   * @throws Exception if an error occurs
331   */
332  public void setOptions(String[] options) throws Exception {
333    String optionString;
334
335    optionString = Utils.getOption('X', options);
336    if (optionString.length() != 0) {
337      setAttsToEliminatePerIteration(Integer.parseInt(optionString));
338    }
339
340    optionString = Utils.getOption('Y', options);
341    if (optionString.length() != 0) {
342      setPercentToEliminatePerIteration(Integer.parseInt(optionString));
343    }
344
345    optionString = Utils.getOption('Z', options);
346    if (optionString.length() != 0) {
347      setPercentThreshold(Integer.parseInt(optionString));
348    }
349
350    optionString = Utils.getOption('P', options);
351    if (optionString.length() != 0) {
352      setEpsilonParameter((new Double(optionString)).doubleValue());
353    }
354
355    optionString = Utils.getOption('T', options);
356    if (optionString.length() != 0) {
357      setToleranceParameter((new Double(optionString)).doubleValue());
358    }
359
360    optionString = Utils.getOption('C', options);
361    if (optionString.length() != 0) {
362      setComplexityParameter((new Double(optionString)).doubleValue());
363    }
364
365    optionString = Utils.getOption('N', options);
366    if (optionString.length() != 0) {
367      setFilterType(new SelectedTag(Integer.parseInt(optionString), SMO.TAGS_FILTER));
368    } else {
369      setFilterType(new SelectedTag(SMO.FILTER_NORMALIZE, SMO.TAGS_FILTER));
370    }
371
372    Utils.checkForRemainingOptions(options);
373  }
374
375  /**
376   * Gets the current settings of SVMAttributeEval
377   *
378   * @return an array of strings suitable for passing to setOptions()
379   */
380  public String[] getOptions() {
381    String[] options = new String[14];
382    int current = 0;
383
384    options[current++] = "-X";
385    options[current++] = "" + getAttsToEliminatePerIteration();
386
387    options[current++] = "-Y";
388    options[current++] = "" + getPercentToEliminatePerIteration();
389
390    options[current++] = "-Z";
391    options[current++] = "" + getPercentThreshold();
392               
393    options[current++] = "-P";
394    options[current++] = "" + getEpsilonParameter();
395
396    options[current++] = "-T";
397    options[current++] = "" + getToleranceParameter();         
398
399    options[current++] = "-C";
400    options[current++] = "" + getComplexityParameter();         
401
402    options[current++] = "-N";
403    options[current++] = "" + m_smoFilterType;         
404
405    while (current < options.length) {
406      options[current++] = "";
407    }
408
409    return options;
410  }
411
412  //________________________________________________________________________
413
414  /**
415   * Returns a tip text for this property suitable for display in the
416   * GUI
417   *
418   * @return tip text string describing this property
419   */
420  public String attsToEliminatePerIterationTipText() {
421    return "Constant rate of attribute elimination.";
422  }
423
424  /**
425   * Returns a tip text for this property suitable for display in the
426   * GUI
427   *
428   * @return tip text string describing this property
429   */
430  public String percentToEliminatePerIterationTipText() {
431    return "Percent rate of attribute elimination.";
432  }
433
434  /**
435   * Returns a tip text for this property suitable for display in the
436   * GUI
437   *
438   * @return tip text string describing this property
439   */
440  public String percentThresholdTipText() {
441    return "Threshold below which percent elimination reverts to constant elimination.";
442  }
443
444  /**
445   * Returns a tip text for this property suitable for display in the
446   * GUI
447   *
448   * @return tip text string describing this property
449   */
450  public String epsilonParameterTipText() {
451    return "P epsilon parameter to pass to the SVM";
452  }
453
454  /**
455   * Returns a tip text for this property suitable for display in the
456   * GUI
457   *
458   * @return tip text string describing this property
459   */
460  public String toleranceParameterTipText() {
461    return "T tolerance parameter to pass to the SVM";
462  }
463
464  /**
465   * Returns a tip text for this property suitable for display in the
466   * GUI
467   *
468   * @return tip text string describing this property
469   */
470  public String complexityParameterTipText() {
471    return "C complexity parameter to pass to the SVM";
472  }
473
474  /**
475   * Returns a tip text for this property suitable for display in the
476   * GUI
477   *
478   * @return tip text string describing this property
479   */
480  public String filterTypeTipText() {
481    return "filtering used by the SVM";
482  }
483
484  //________________________________________________________________________
485
486  /**
487   * Set the constant rate of attribute elimination per iteration
488   *
489   * @param cRate the constant rate of attribute elimination per iteration
490   */
491  public void setAttsToEliminatePerIteration(int cRate) {
492    m_numToEliminate = cRate;
493  }
494
495  /**
496   * Get the constant rate of attribute elimination per iteration
497   *
498   * @return the constant rate of attribute elimination per iteration
499   */
500  public int getAttsToEliminatePerIteration() {
501    return m_numToEliminate;
502  }
503
504  /**
505   * Set the percentage of attributes to eliminate per iteration
506   *
507   * @param pRate percent of attributes to eliminate per iteration
508   */
509  public void setPercentToEliminatePerIteration(int pRate) {
510    m_percentToEliminate = pRate;
511  }
512
513  /**
514   * Get the percentage rate of attribute elimination per iteration
515   *
516   * @return the percentage rate of attribute elimination per iteration
517   */
518  public int getPercentToEliminatePerIteration() {
519    return m_percentToEliminate;
520  }
521
522  /**
523   * Set the threshold below which percentage elimination reverts to
524   * constant elimination.
525   *
526   * @param pThresh percent of attributes to eliminate per iteration
527   */
528  public void setPercentThreshold(int pThresh) {
529    m_percentThreshold = pThresh;
530  }
531
532  /**
533   * Get the threshold below which percentage elimination reverts to
534   * constant elimination.
535   *
536   * @return the threshold below which percentage elimination stops
537   */
538  public int getPercentThreshold() {
539    return m_percentThreshold;
540  }
541
542  /**
543   * Set the value of P for SMO
544   *
545   * @param svmP the value of P
546   */
547  public void setEpsilonParameter(double svmP) {
548    m_smoPParameter = svmP;
549  }
550
551  /**
552   * Get the value of P used with SMO
553   *
554   * @return the value of P
555   */
556  public double getEpsilonParameter() {
557    return m_smoPParameter;
558  }
559       
560  /**
561   * Set the value of T for SMO
562   *
563   * @param svmT the value of T
564   */
565  public void setToleranceParameter(double svmT) {
566    m_smoTParameter = svmT;
567  }
568
569  /**
570   * Get the value of T used with SMO
571   *
572   * @return the value of T
573   */
574  public double getToleranceParameter() {
575    return m_smoTParameter;
576  }
577
578
579  /**
580   * Set the value of C for SMO
581   *
582   * @param svmC the value of C
583   */
584  public void setComplexityParameter(double svmC) {
585    m_smoCParameter = svmC;
586  }
587
588  /**
589   * Get the value of C used with SMO
590   *
591   * @return the value of C
592   */
593  public double getComplexityParameter() {
594    return m_smoCParameter;
595  }
596
597  /**
598   * The filtering mode to pass to SMO
599   *
600   * @param newType the new filtering mode
601   */
602  public void setFilterType(SelectedTag newType) {
603   
604    if (newType.getTags() == SMO.TAGS_FILTER) {
605      m_smoFilterType = newType.getSelectedTag().getID();
606    }
607  }
608
609  /**
610   * Get the filtering mode passed to SMO
611   *
612   * @return the filtering mode
613   */
614  public SelectedTag getFilterType() {
615
616    return new SelectedTag(m_smoFilterType, SMO.TAGS_FILTER);
617  }
618
619  //________________________________________________________________________
620
621  /**
622   * Returns the capabilities of this evaluator.
623   *
624   * @return            the capabilities of this evaluator
625   * @see               Capabilities
626   */
627  public Capabilities getCapabilities() {
628    Capabilities        result;
629   
630    result = new SMO().getCapabilities();
631   
632    result.setOwner(this);
633   
634    // only binary attributes are allowed, otherwise the NominalToBinary
635    // filter inside SMO will increase the number of attributes which in turn
636    // will lead to ArrayIndexOutOfBounds-Exceptions.
637    result.disable(Capability.NOMINAL_ATTRIBUTES);
638    result.enable(Capability.BINARY_ATTRIBUTES);
639    result.disableAllAttributeDependencies();
640   
641    return result;
642  }
643
644  /**
645   * Initializes the evaluator.
646   *
647   * @param data set of instances serving as training data
648   * @throws Exception if the evaluator has not been
649   * generated successfully
650   */
651  public void buildEvaluator(Instances data) throws Exception {
652    // can evaluator handle data?
653    getCapabilities().testWithFail(data);
654
655    //System.out.println("Class attribute: " + data.attribute(data.classIndex()).name());
656    // Check settings           
657    m_numToEliminate = (m_numToEliminate > 1) ? m_numToEliminate : 1;
658    m_percentToEliminate = (m_percentToEliminate < 100) ? m_percentToEliminate : 100;
659    m_percentToEliminate = (m_percentToEliminate > 0) ? m_percentToEliminate : 0;
660    m_percentThreshold = (m_percentThreshold < data.numAttributes()) ? m_percentThreshold : data.numAttributes() - 1;
661    m_percentThreshold = (m_percentThreshold > 0) ? m_percentThreshold : 0;
662
663    // Get ranked attributes for each class seperately, one-vs-all
664    int[][] attScoresByClass;
665    int numAttr = data.numAttributes() - 1;
666    if(data.numClasses()>2) {
667      attScoresByClass = new int[data.numClasses()][numAttr];
668      for (int i = 0; i < data.numClasses(); i++) {
669        attScoresByClass[i] = rankBySVM(i, data);
670      }
671    }
672    else {
673      attScoresByClass = new int[1][numAttr];
674      attScoresByClass[0] = rankBySVM(0, data);
675    }
676
677    // Cycle through class-specific ranked lists, poping top one off for each class
678    // and adding it to the overall ranked attribute list if it's not there already
679    ArrayList ordered = new ArrayList(numAttr);
680    for (int i = 0; i < numAttr; i++) {
681      for (int j = 0; j < (data.numClasses()>2 ? data.numClasses() : 1); j++) {
682        Integer rank = new Integer(attScoresByClass[j][i]);
683        if (!ordered.contains(rank))
684          ordered.add(rank);
685      }
686    }
687    m_attScores = new double[data.numAttributes()];
688    Iterator listIt = ordered.iterator();
689    for (double i = (double) numAttr; listIt.hasNext(); i = i - 1.0) {
690      m_attScores[((Integer) listIt.next()).intValue()] = i;
691    }
692  }
693
694  /**
695   * Get SVM-ranked attribute indexes (best to worst) selected for
696   * the class attribute indexed by classInd (one-vs-all).
697   */
698  private int[] rankBySVM(int classInd, Instances data) {
699    // Holds a mapping into the original array of attribute indices
700    int[] origIndices = new int[data.numAttributes()];
701    for (int i = 0; i < origIndices.length; i++)
702      origIndices[i] = i;
703   
704    // Count down of number of attributes remaining
705    int numAttrLeft = data.numAttributes()-1;
706    // Ranked attribute indices for this class, one vs.all (highest->lowest)
707    int[] attRanks = new int[numAttrLeft];
708
709    try {
710      MakeIndicator filter = new MakeIndicator();
711      filter.setAttributeIndex("" + (data.classIndex() + 1));
712      filter.setNumeric(false);
713      filter.setValueIndex(classInd);
714      filter.setInputFormat(data);
715      Instances trainCopy = Filter.useFilter(data, filter);
716      double pctToElim = ((double) m_percentToEliminate) / 100.0;
717      while (numAttrLeft > 0) {
718        int numToElim;
719        if (pctToElim > 0) {
720          numToElim = (int) (trainCopy.numAttributes() * pctToElim);
721          numToElim = (numToElim > 1) ? numToElim : 1;
722          if (numAttrLeft - numToElim <= m_percentThreshold) {
723            pctToElim = 0;
724            numToElim = numAttrLeft - m_percentThreshold;
725          }
726        } else {
727          numToElim = (numAttrLeft >= m_numToEliminate) ? m_numToEliminate : numAttrLeft;
728        }
729       
730        // Build the linear SVM with default parameters
731        SMO smo = new SMO();
732                               
733        // SMO seems to get stuck if data not normalised when few attributes remain
734        // smo.setNormalizeData(numAttrLeft < 40);
735        smo.setFilterType(new SelectedTag(m_smoFilterType, SMO.TAGS_FILTER));
736        smo.setEpsilon(m_smoPParameter);
737        smo.setToleranceParameter(m_smoTParameter);
738        smo.setC(m_smoCParameter);
739        smo.buildClassifier(trainCopy);
740                               
741        // Find the attribute with maximum weight^2
742        double[] weightsSparse = smo.sparseWeights()[0][1];
743        int[] indicesSparse = smo.sparseIndices()[0][1];
744        double[] weights = new double[trainCopy.numAttributes()];
745        for (int j = 0; j < weightsSparse.length; j++) {
746          weights[indicesSparse[j]] = weightsSparse[j] * weightsSparse[j];
747        }
748        weights[trainCopy.classIndex()] = Double.MAX_VALUE;
749        int minWeightIndex;
750        int[] featArray = new int[numToElim];
751        boolean[] eliminated = new boolean[origIndices.length];
752        for (int j = 0; j < numToElim; j++) {
753          minWeightIndex = Utils.minIndex(weights);
754          attRanks[--numAttrLeft] = origIndices[minWeightIndex];
755          featArray[j] = minWeightIndex;
756          eliminated[minWeightIndex] = true;
757          weights[minWeightIndex] = Double.MAX_VALUE;
758        }
759                               
760        // Delete the worst attributes.
761        weka.filters.unsupervised.attribute.Remove delTransform =
762          new weka.filters.unsupervised.attribute.Remove();
763        delTransform.setInvertSelection(false);
764        delTransform.setAttributeIndicesArray(featArray);
765        delTransform.setInputFormat(trainCopy);
766        trainCopy = Filter.useFilter(trainCopy, delTransform);
767                               
768        // Update the array of remaining attribute indices
769        int[] temp = new int[origIndices.length - numToElim];
770        int k = 0;
771        for (int j = 0; j < origIndices.length; j++) {
772          if (!eliminated[j]) {
773            temp[k++] = origIndices[j];
774          }
775        }
776        origIndices = temp;
777      }                 
778      // Carefully handle all exceptions
779    } catch (Exception e) {
780      e.printStackTrace();                     
781    }
782    return attRanks;
783  }
784
785  /**
786   * Resets options to defaults.
787   */
788  protected void resetOptions() {
789    m_attScores = null;
790  }
791
792  /**
793   * Evaluates an attribute by returning the rank of the square of its coefficient in a
794   * linear support vector machine.
795   *
796   * @param attribute the index of the attribute to be evaluated
797   * @throws Exception if the attribute could not be evaluated
798   */
799  public double evaluateAttribute(int attribute) throws Exception {
800    return m_attScores[attribute];
801  }
802
803  /**
804   * Return a description of the evaluator
805   * @return description as a string
806   */
807  public String toString() {
808
809    StringBuffer text = new StringBuffer();
810    if (m_attScores == null) {
811      text.append("\tSVM feature evaluator has not been built yet");
812    } else {
813      text.append("\tSVM feature evaluator");
814    }
815
816    text.append("\n");
817    return text.toString();
818  }
819 
820  /**
821   * Returns the revision string.
822   *
823   * @return            the revision
824   */
825  public String getRevision() {
826    return RevisionUtils.extract("$Revision: 1.28 $");
827  }
828
829  /**
830   * Main method for testing this class.
831   *
832   * @param args the options
833   */
834  public static void main(String[] args) {
835    runEvaluator(new SVMAttributeEval(), args);
836  }
837}
Note: See TracBrowser for help on using the repository browser.