📄 multiclassclassifier.java
字号:
/* * 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. *//* * MultiClassClassifier.java * Copyright (C) 1999 Eibe Frank,Len Trigg * */package weka.classifiers;import java.io.Serializable;import java.util.Enumeration;import java.util.Random;import java.util.Vector;import weka.core.Attribute;import weka.core.AttributeStats;import weka.core.Instance;import weka.core.Instances;import weka.core.Option;import weka.core.OptionHandler;import weka.core.SelectedTag;import weka.core.Tag;import weka.core.Utils;import weka.filters.Filter;import weka.filters.MakeIndicatorFilter;/** * Class for handling multi-class datasets with 2-class distribution * classifiers.<p> * * Valid options are:<p> * * -E num <br> * Sets the error-correction mode. Valid values are 0 (no correction), * 1 (random codes), and 2 (exhaustive code). (default 0) <p> * * -R num <br> * Sets the multiplier when using random codes. (default 2.0)<p> * * -W classname <br> * Specify the full class name of a classifier as the basis for * the multi-class classifier (required).<p> * * @author Eibe Frank (eibe@cs.waikato.ac.nz) * @author Len Trigg (len@webmind.com) * @version $Revision: 1.23 $ */public class MultiClassClassifier extends DistributionClassifier implements OptionHandler { /** The classifiers. (One for each class.) */ private Classifier [] m_Classifiers; /** The filters used to transform the class. */ private MakeIndicatorFilter[] m_ClassFilters; /** The class name of the base classifier. */ private DistributionClassifier m_Classifier = new weka.classifiers.ZeroR(); /** ZeroR classifier for when all base classifier return zero probability. */ private ZeroR m_ZeroR; /** Internal copy of the class attribute for output purposes */ private Attribute m_ClassAttribute; /** * The multiplier when generating random codes. Will generate * numClasses * m_RandomWidthFactor codes */ private double m_RandomWidthFactor = 2.0; /** The error-correcting output code method to use */ private int m_ErrorMode = ERROR_NONE; /** The error correction modes */ public final static int ERROR_NONE = 0; public final static int ERROR_RANDOM = 1; public final static int ERROR_EXHAUSTIVE = 2; public static final Tag [] TAGS_ERROR = { new Tag(ERROR_NONE , "No correction"), new Tag(ERROR_RANDOM , "Random correction code"), new Tag(ERROR_EXHAUSTIVE , "Exhaustive correction code") }; /** Interface for the code constructors */ private abstract class Code implements Serializable { /** * Subclasses must allocate and fill these. * First dimension is number of codes. * Second dimension is number of classes. */ protected boolean [][]m_Codebits; /** Returns the number of codes. */ public int size() { return m_Codebits.length; } /** * Returns the indices of the values set to true for this code, * using 1-based indexing (for input to Range). */ public String getIndices(int which) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < m_Codebits[which].length; i++) { if (m_Codebits[which][i]) { if (sb.length() != 0) { sb.append(','); } sb.append(i + 1); } } return sb.toString(); } /** Returns a human-readable representation of the codes. */ public String toString() { StringBuffer sb = new StringBuffer(); for(int i = 0; i < m_Codebits[0].length; i++) { for (int j = 0; j < m_Codebits.length; j++) { sb.append(m_Codebits[j][i] ? " 1" : " 0"); } sb.append('\n'); } return sb.toString(); } } /** Constructs a code with no error correction */ private class StandardCode extends Code { public StandardCode(int numClasses) { m_Codebits = new boolean[numClasses][numClasses]; for (int i = 0; i < numClasses; i++) { m_Codebits[i][i] = true; } System.err.println("Code:\n" + this); } } /** Constructs a random code assignment */ private class RandomCode extends Code { Random r = new Random(); public RandomCode(int numClasses, int numCodes) { numCodes = Math.max(numClasses, numCodes); m_Codebits = new boolean[numCodes][numClasses]; int i = 0; do { randomize(); //System.err.println(this); } while (!good() && (i++ < 100)); System.err.println("Code:\n" + this); } private boolean good() { boolean [] ninClass = new boolean[m_Codebits[0].length]; boolean [] ainClass = new boolean[m_Codebits[0].length]; for (int i = 0; i < ainClass.length; i++) { ainClass[i] = true; } for (int i = 0; i < m_Codebits.length; i++) { boolean ninCode = false; boolean ainCode = true; for (int j = 0; j < m_Codebits[i].length; j++) { boolean current = m_Codebits[i][j]; ninCode = ninCode || current; ainCode = ainCode && current; ninClass[j] = ninClass[j] || current; ainClass[j] = ainClass[j] && current; } if (!ninCode || ainCode) { return false; } } for (int j = 0; j < ninClass.length; j++) { if (!ninClass[j] || ainClass[j]) { return false; } } return true; } private void randomize() { for (int i = 0; i < m_Codebits.length; i++) { for (int j = 0; j < m_Codebits[i].length; j++) { double temp = r.nextDouble(); m_Codebits[i][j] = (temp < 0.5) ? false : true; } } } } /** * TODO: Constructs codes as per: * Bose, R.C., Ray Chaudhuri (1960), On a class of error-correcting * binary group codes, Information and Control, 3, 68-79. * Hocquenghem, A. (1959) Codes corecteurs d'erreurs, Chiffres, 2, 147-156. */ //private class BCHCode extends Code {...} /** Constructs an exhaustive code assignment */ private class ExhaustiveCode extends Code { public ExhaustiveCode(int numClasses) { int width = (int)Math.pow(2, numClasses - 1) - 1; m_Codebits = new boolean[width][numClasses]; for (int j = 0; j < width; j++) { m_Codebits[j][0] = true; } for (int i = 1; i < numClasses; i++) { int skip = (int) Math.pow(2, numClasses - (i + 1)); for(int j = 0; j < width; j++) { m_Codebits[j][i] = ((j / skip) % 2 != 0); } } System.err.println("Code:\n" + this); } } /** * Builds the classifiers. * * @param insts the training data. * @exception Exception if a classifier can't be built */ public void buildClassifier(Instances insts) throws Exception { Instances newInsts; if (m_Classifier == null) { throw new Exception("No base classifier has been set!"); } m_ZeroR = new ZeroR(); m_ZeroR.buildClassifier(insts); int numClassifiers = insts.numClasses(); if (numClassifiers <= 2) { m_Classifiers = Classifier.makeCopies(m_Classifier, 1); m_Classifiers[0].buildClassifier(insts); } else { Code code = null; switch (m_ErrorMode) { case ERROR_EXHAUSTIVE: code = new ExhaustiveCode(numClassifiers); break; case ERROR_RANDOM: code = new RandomCode(numClassifiers, (int)(numClassifiers * m_RandomWidthFactor)); break; case ERROR_NONE: code = new StandardCode(numClassifiers); break; default: throw new Exception("Unrecognized correction code type"); } numClassifiers = code.size(); m_Classifiers = Classifier.makeCopies(m_Classifier, numClassifiers); m_ClassFilters = new MakeIndicatorFilter[numClassifiers]; AttributeStats classStats = insts.attributeStats(insts.classIndex()); for (int i = 0; i < m_Classifiers.length; i++) { if ((m_ErrorMode == ERROR_NONE) && (classStats.nominalCounts[i] == 0)) { m_Classifiers[i] = null; } else { m_ClassFilters[i] = new MakeIndicatorFilter(); m_ClassFilters[i].setAttributeIndex(insts.classIndex()); m_ClassFilters[i].setValueIndices(code.getIndices(i)); m_ClassFilters[i].setNumeric(false); m_ClassFilters[i].setInputFormat(insts); newInsts = Filter.useFilter(insts, m_ClassFilters[i]); m_Classifiers[i].buildClassifier(newInsts); } } } m_ClassAttribute = insts.classAttribute(); } /** * Returns the distribution for an instance. * * @exception Exception if the distribution can't be computed successfully */ public double[] distributionForInstance(Instance inst) throws Exception { if (m_Classifiers.length == 1) { return ((DistributionClassifier)m_Classifiers[0])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -