/* * 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. */ /* * SVMlight.java * Copyright (C) 2002-2003 Mikhail Bilenko * * TODO: * - implement UpdateableClassifier * - implement the remaining options for SVM-light * - implement WeightedInstancesHandler * - proper conversion from margin to distribution (see Zadrozny & Elkan, Wahba, Platt...) */ package weka.classifiers.sparse; import weka.classifiers.Classifier; import weka.classifiers.DistributionClassifier; import weka.classifiers.Evaluation; import weka.classifiers.UpdateableClassifier; import java.io.*; import java.util.*; import weka.core.*; /** * <i> A wrapper for SVMlight package by Thorsten Joachims * For more information, see <p> * * http://www.cs.cornell.edu/People/tj/svm_light * * Valid options are:<p> * * * @author Mikhail Bilenko (mbilenko@cs.utexas.edu) * @version $Revision: 1.9 $ */ public class SVMlight extends DistributionClassifier implements OptionHandler { /** The training instances used for classification. */ protected Instances m_train; /** Has the SVM been trained */ protected boolean m_svmTrained = false; /** Output debugging information */ protected boolean m_debug = false; /** Path to the directory where SVM-light executables are located */ protected String m_binPath = new String("/u/ml/software/svm_light/"); /** Path to the directory where temporary files will be stored */ protected String m_tempDirPath = new String("/var/local/tmp/"); protected File m_tempDirFile = null; /** Name of the temporary file where training data will be dumped temporarily */ protected String m_trainFilenameBase = new String("SVMtrain"); protected String m_trainFilename = null; /** Name of the temporary file where a test instance is dumped if buffered IO is not used */ protected String m_testFilenameBase = new String("SVMtest"); protected String m_testFilename = null; /** Name of the file where a model will be temporarily created*/ protected String m_modelFilenameBase = new String("SVMmodel"); protected String m_modelFilename = null; /** Name of the file where predictions will be temporarily stored unless buffered IO is used*/ protected String m_predictionFilenameBase = new String("SVMpredict"); protected String m_predictionFilename = null; /** SVM-light predictions are positive or negative margins; to convert * to a distribution we need min/max margin values... */ protected double m_maxMargin = -45; protected double m_minMargin = 45; protected boolean m_autoBounds = false; /** Is classification done via temporary files or via a buffer? */ protected boolean m_bufferedMode = true; protected BufferedReader m_procReader = null; protected BufferedWriter m_procWriter = null; /**********************/ /** SVM-light options */ /** verbosity level */ protected int m_verbosityLevel = 1; /** SVM-light can work in classification, regression and preference ranking modes */ public static final int SVM_MODE_CLASSIFICATION = 1; public static final int SVM_MODE_REGRESSION = 2; public static final int SVM_MODE_PREFERENCE_RANKING = 4; public static final Tag[] TAGS_SVM_MODE = { new Tag(SVM_MODE_CLASSIFICATION, "Classification"), new Tag(SVM_MODE_REGRESSION, "Regression"), new Tag(SVM_MODE_PREFERENCE_RANKING, "Preference ranking") }; protected int m_mode = SVM_MODE_CLASSIFICATION; /** trade-off between training error and margin (default 0 corresponds to [avg. x*x]^-1) */ protected double m_C = 0; /** Epsilon width of tube for regression */ protected double m_width = 0.1; /** Cost: cost-factor, by which training errors on positive examples outweight errors on negative examples */ protected double m_costFactor = 1; /** Use biased hyperplane (i.e. x*w+b>0) instead of unbiased hyperplane (i.e. x*w>0) */ protected boolean m_biased = true; /** remove inconsistent training examples and retrain */ protected boolean m_removeInconsistentExamples = false; /** Kernel type */ public static final int KERNEL_LINEAR = 1; public static final int KERNEL_POLYNOMIAL = 2; public static final int KERNEL_RBF = 4; public static final int KERNEL_SIGMOID_TANH = 8; public static final Tag[] TAGS_KERNEL_TYPE = { new Tag(KERNEL_LINEAR, "Linear"), new Tag(KERNEL_POLYNOMIAL, "Polynomial (s a*b+c)^d"), new Tag(KERNEL_RBF, "Radial basis function exp(-gamma ||a-b||^2)"), new Tag(KERNEL_SIGMOID_TANH, "Sigmoid tanh(s a*b + c)") }; protected int m_kernelType = KERNEL_RBF; /** Parameter d in polynomial kernel */ protected int m_d = 3; /** Parameter gamma in rbf kernel */ protected double m_gamma = 1; /** Parameter s in sigmoid/polynomial kernel */ protected double m_s = 1; /** parameter c in sigmoid/poly kernel */ protected double m_c1 = 1; /** A default constructor */ public SVMlight() { } /** Take care of closing the SVM-light process before the object is destroyed */ protected void finalize() { cleanupIO(); } /** The buffered version of SVM-light needs to release some I/O resources * before exiting */ protected void cleanupIO() { try { // kill the svm_classify_std process if (m_procWriter != null) { m_procWriter.close(); } if (m_procReader != null) { m_procReader.close(); } m_procReader = null; m_procWriter = null; // delete the model file if (!m_debug && (m_modelFilename != null)) { File modelFile = new File(m_modelFilename); modelFile.delete(); } } catch (Exception e) { System.out.println("Problems when cleaning up IO"); e.printStackTrace(); } } /** * Generates the classifier. * * @param instances set of instances serving as training data * @exception Exception if the classifier has not been generated successfully */ public void buildClassifier(Instances instances) throws Exception { if (instances.classIndex() < 0) { throw new Exception ("No class attribute assigned to instances."); } if (instances.checkForStringAttributes()) { throw new UnsupportedAttributeTypeException("Cannot handle string attributes."); } int numClasses = instances.numClasses(); if (numClasses != 2) { throw new Exception("Training data should have two classes; has " + numClasses + " classes"); } // if a classifier has been built, clean up the IO if (m_bufferedMode && m_procWriter != null) { cleanupIO(); } // create a working copy of training data m_tempDirFile = new File(m_tempDirPath); m_train = new Instances(instances, 0, instances.numInstances()); // Unlike most Weka classifiers, we are *not* throwing away training // instances with missing class, since they may be used for transduction. // If it is desired to avoid transduction and throw out unlabeled data, // uncomment the following line: // m_train.deleteWithMissingClass(); // Convert training instances into SVMlight format and dump into a training file dumpTrainingData(m_train); // Train the model trainSVMlight(); // set min and max margin if desired if (m_autoBounds) { setBounds(instances); } } /** Set the bounds using "extreme" training examples - TODO!*/ protected void setBounds(Instances data) { try { // get the minimum margin double[] values = new double[data.numAttributes()]; Instance zeroInstance = new Instance(1.0, values); zeroInstance.setDataset(data); if (!m_bufferedMode) { File testFile = File.createTempFile(m_testFilenameBase, ".dat", m_tempDirFile); if (!m_debug) { testFile.deleteOnExit(); } dumpInstance(zeroInstance, testFile); } double minMargin = classifySVMlight(zeroInstance); setMinMargin(minMargin); // get the maximum margin double maxMargin = 0; for (int i = 0; i < data.numInstances(); i++) { Instance instance = data.instance(i); // we only care about positive examples if (instance.classValue() == 0) { if (!m_bufferedMode) { File testFile = File.createTempFile(m_testFilenameBase, ".dat", m_tempDirFile); if (!m_debug) { testFile.deleteOnExit(); } dumpInstance(zeroInstance, testFile); } double margin = classifySVMlight(instance); if (margin < maxMargin) { maxMargin = margin; } } setMaxMargin(maxMargin); } System.out.println("xxxxx MINMARGIN=" + minMargin + "\tMAX_MARGIN=" + maxMargin); } catch (Exception e) { System.err.println("Problems obtaining automatic margins: " + e); e.printStackTrace(); } } /** * Dump training instances into a file in SVM-light format * @param instances the training instances * @param filename name of the file where instance will be dumped */ protected void dumpTrainingData(Instances instances) { try { File trainFile = File.createTempFile(m_trainFilenameBase, ".dat", m_tempDirFile); if (!m_debug) { trainFile.deleteOnExit(); } m_trainFilename = trainFile.getPath(); PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(trainFile))); int classIdx = instances.classIndex(); // Go through all instances Enumeration enum = instances.enumerateInstances(); while (enum.hasMoreElements()) { Instance trainInstance = (Instance) enum.nextElement(); // output the class value double classValue = 0; if (!trainInstance.classIsMissing()) { classValue = trainInstance.classValue(); if (classValue == 0) { classValue = -1; } else { classValue = 1; } } writer.print((int)classValue + " "); // output the attributes; iterating using numValues() skips 'missing' values for SparseInstances for (int j = 0; j < trainInstance.numValues(); j++) { Attribute attribute = trainInstance.attributeSparse(j); // Attribute index must be greater than 0 int attrIdx = attribute.index(); if (attrIdx != classIdx) { writer.print((attrIdx+1) + ":" + trainInstance.value(attrIdx) + " "); } } writer.println(); } writer.close(); } catch (Exception e) { System.err.println("Error when dumping training instances: " + e); e.printStackTrace(); } } /** * Dump a single instance into a file in SVM-light format * @param instance an instance * @param file the file where instance will be dumped */ protected void dumpInstance(Instance instance, File file) { try { PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file))); // output a dummy class value int classIdx = instance.classIndex(); writer.print(Integer.MAX_VALUE + " "); // output the attributes; iterating using numValues skips 'missing' values for SparseInstances for (int j = 0; j < instance.numValues(); j++) { Attribute attribute = instance.attributeSparse(j); int attrIdx = attribute.index(); if (attrIdx != classIdx) { writer.print((attrIdx+1) + ":" + instance.value(attrIdx) + " "); } } writer.println(); writer.close(); } catch (Exception e) { System.err.println("Error when dumping instance: " + e); e.printStackTrace(); } } /** Launch an SVM-light process assuming that the training data has been dumped */ protected void trainSVMlight() { try { String command = new String(m_binPath + "svm_learn"); // append all options for SVM-light command = command + " -v " + m_verbosityLevel; switch (m_mode) { case SVM_MODE_CLASSIFICATION: command = command + " -z c"; break; case SVM_MODE_REGRESSION: command = command + " -z r"; command = command + " -w " + m_width; break; case SVM_MODE_PREFERENCE_RANKING: command = command + " -z p"; break; default: throw new Exception("Unknown mode: " + m_mode); } command = command + " -c " + m_C; command = command + " -j " + m_costFactor; command = command + " -b " + (m_biased ? 1 : 0); command = command + " -i " + (m_removeInconsistentExamples ? 1 : 0); switch(m_kernelType) { case KERNEL_LINEAR: command = command + " -t 0"; break; case KERNEL_POLYNOMIAL: command = command + " -t 1"; command = command + " -d " + m_d; command = command + " -s " + m_s; command = command + " -r " + m_c1; break; case KERNEL_RBF: command = command + " -t 2"; command = command + " -g " + m_gamma; break; case KERNEL_SIGMOID_TANH: command = command + " -t 3"; command = command + " -s " + m_s; command = command + " -r " + m_c1; break; default: throw new Exception("Unknown kernel type: " + m_kernelType); } // create the model file File modelFile = File.createTempFile(m_modelFilenameBase, ".dat", m_tempDirFile); if (!m_debug) { modelFile.deleteOnExit(); } m_modelFilename = modelFile.getPath(); command = command + " " + m_trainFilename + " " + m_modelFilename; if (m_debug) { System.out.println("Executing SVMlight: \n\t" + command); } Process proc = Runtime.getRuntime().exec(command); // read the training output if (proc != null){ BufferedReader procOutput = new BufferedReader(new InputStreamReader(proc.getInputStream())); try { String line; while ((line = procOutput.readLine()) != null){ if (m_debug) { System.out.println("SVM: " + line); } } } catch (Exception e) { System.err.println("Problems trapping output in debug mode:"); e.printStackTrace(); System.out.println(e); } } int exitValue = proc.waitFor(); if (exitValue != 0) { throw new Exception("Problems training SVM-light: process returned value " + exitValue); } // delete the training file File trainFile = new File(m_trainFilename); // trainFile.delete(); m_svmTrained = true; } catch (Exception e) { System.out.println("Problem training: "); e.printStackTrace(); System.err.println(e); } } /** Launch an SVM-light process and classify a given instance * @param instance an instance that must be classified */ protected double classifySVMlight(Instance instance) { double prediction = Double.MIN_VALUE; String lineIn = null; StringBuffer instanceString = new StringBuffer(); try { if (m_bufferedMode) { // if this is the first time classify() is called, initialize the classifier process if (m_procWriter == null) { String command = new String(m_binPath + "svm_classify_std -v " + m_verbosityLevel + " " + m_modelFilename); if (m_debug) { System.out.println("Executing \"" + command + "\""); } Process proc = Runtime.getRuntime().exec(command); m_procReader = new BufferedReader(new InputStreamReader(proc.getInputStream())); m_procWriter = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())); System.out.println(m_procReader.readLine()); System.out.println(m_procReader.readLine()); } // pass the instance to SVMlight process // output a bogus class value instanceString.append(Integer.MAX_VALUE + " "); // output the attributes; iterating using numValues skips 'missing' values for SparseInstances int classIdx = instance.classIndex(); for (int j = 0; j < instance.numValues(); j++) { Attribute attribute = instance.attributeSparse(j); int attrIdx = attribute.index(); if (attrIdx != classIdx) { instanceString.append((attrIdx+1) + ":" + instance.value(attrIdx) + " "); } } instanceString.append("\n"); if (m_debug) { System.out.println("Sending " + instance); System.out.flush(); } m_procWriter.write(instanceString.toString()); m_procWriter.flush(); lineIn = m_procReader.readLine(); if (lineIn == null) { throw new Exception("Got null prediction from SVMlight!"); } prediction = Double.parseDouble(lineIn); if (m_debug) { System.out.println("Got " + prediction); } } else { // Non-buffered IO, a temporary test file is used for the test instance // create a temporary file where the test instance is dumped File testFile = File.createTempFile(m_testFilenameBase, ".dat", m_tempDirFile); if (!m_debug) { testFile.deleteOnExit(); } m_testFilename = testFile.getPath(); dumpInstance(instance, testFile); // create a temporary file where the SVMlight output (prediction) will be stored File predictionFile = File.createTempFile(m_predictionFilenameBase, ".dat", m_tempDirFile); if (!m_debug) { predictionFile.deleteOnExit(); } m_predictionFilename = predictionFile.getPath(); // run svm_classify String command = new String(m_binPath + "svm_classify -v " + m_verbosityLevel + " " + m_testFilename + " " + m_modelFilename + " " + m_predictionFilename ); Process proc = Runtime.getRuntime().exec(command); int exitValue = proc.waitFor(); if (exitValue != 0) { throw new Exception("Problems running SVM-light: process returned value " + exitValue); } prediction = readPrediction(predictionFile); testFile.delete(); predictionFile.delete(); } } catch (Exception e) { System.out.println("Got from SVM-light: " + lineIn); System.err.println(e); e.printStackTrace(); } return prediction; } /** Read the prediction of SVM-light * @param file file where the prediction is stored */ protected double readPrediction(File file) { double result = Double.MIN_VALUE; try { BufferedReader r = new BufferedReader(new FileReader(file)); String line = r.readLine(); if (line == null) { throw new Exception("Empty prediction file " + file.getPath()); } result = Double.parseDouble(line); } catch (Exception e) { System.err.println("Error reading the prediction file: " + e); } return result; } /** * Calculates the class membership probabilities for the given test instance. * * @param instance the instance to be classified * @return predicted class probability distribution * @exception Exception if an error occurred during the prediction */ public double [] distributionForInstance(Instance instance) throws Exception{ if (!m_svmTrained) { throw new Exception("SVM has not been trained!"); } // compute prediction double margin = classifySVMlight(instance); double[] predictions = new double[2]; predictions[0] = 1 - (margin - m_maxMargin)/(m_minMargin - m_maxMargin); if (predictions[0] > 1) { // System.out.println("overflow: " + predictions[0]); predictions[0] = 1; } if (predictions[0] < 0) { // System.out.println("underflow: " + predictions[0]); predictions[0] = 0; } predictions[1] = 1- predictions[0]; if (m_debug) { System.out.println("\t\tMargin: " + margin + "\tDistribution: {" + predictions[0] + ",\t" + predictions[1] + "}"); } return predictions; } /** Check whether the SVM has been trained * @return true if the SVM has been train and is ready to classify instances */ public boolean trained() { return m_svmTrained; } /** * Returns an enumeration describing the available options. * * @return an enumeration of all the available options. */ public Enumeration listOptions() { Vector newVector = new Vector(2); newVector.addElement(new Option( "\tOutput debug information", "D", 0, "-D")); return newVector.elements(); } /** * Parses a given list of options. Valid options are:<p> * * -D <br> * output debugging information <p> * * * @param options the list of options as an array of strings * @exception Exception if an option is not supported */ public void setOptions(String[] options) throws Exception { setDebug(Utils.getFlag('D', options)); String verbosityString = Utils.getOption('v', options); if (verbosityString.length() != 0) { setVerbosityLevel(Integer.parseInt(verbosityString)); } if (Utils.getFlag('A', options)) { setAutoBounds(true); } else { String minMarginString = Utils.getOption('n', options); if (minMarginString.length() != 0) { setMinMargin(Double.parseDouble(minMarginString)); } String maxMarginString = Utils.getOption('m', options); if (maxMarginString.length() != 0) { setMaxMargin(Double.parseDouble(maxMarginString)); } } if (Utils.getFlag('C', options)) { setMode(new SelectedTag(SVM_MODE_CLASSIFICATION, TAGS_SVM_MODE)); } else if (Utils.getFlag('R', options)) { setMode(new SelectedTag(SVM_MODE_REGRESSION, TAGS_SVM_MODE)); String widthString = Utils.getOption('w', options); if (widthString.length() != 0) { setWidth(Double.parseDouble(widthString)); } } else if (Utils.getFlag('P', options)) { setMode(new SelectedTag(SVM_MODE_PREFERENCE_RANKING, TAGS_SVM_MODE)); } String cString = Utils.getOption('c', options); if (cString.length() != 0) { setC(Double.parseDouble(cString)); } String costFactorString = Utils.getOption('j', options); if (costFactorString.length() != 0) { setCostFactor(Double.parseDouble(costFactorString)); } setBiased(Utils.getFlag('b', options)); setRemoveInconsistentExamples(Utils.getFlag('i', options)); // kernel-type related options if (Utils.getFlag('L', options)) { setKernelType(new SelectedTag(KERNEL_LINEAR, TAGS_KERNEL_TYPE)); } else if (Utils.getFlag('O', options)) { setKernelType(new SelectedTag(KERNEL_POLYNOMIAL, TAGS_KERNEL_TYPE)); String dString = Utils.getOption('d', options); if (dString.length() != 0) { setD(Integer.parseInt(dString)); } String sString = Utils.getOption('s', options); if (sString.length() != 0) { setS(Double.parseDouble(sString)); } String c1String = Utils.getOption('r', options); if (c1String.length() != 0) { setC1(Double.parseDouble(c1String)); } } else if (Utils.getFlag('B', options)) { setKernelType(new SelectedTag(KERNEL_RBF, TAGS_KERNEL_TYPE)); String gammaString = Utils.getOption('g', options); if (gammaString.length() != 0) { setC1(Double.parseDouble(gammaString)); } } else if (Utils.getFlag('S', options)) { setKernelType(new SelectedTag(KERNEL_SIGMOID_TANH, TAGS_KERNEL_TYPE)); String sString = Utils.getOption('s', options); if (sString.length() != 0) { setS(Double.parseDouble(sString)); } String c1String = Utils.getOption('r', options); if (c1String.length() != 0) { setC1(Double.parseDouble(c1String)); } } String binPathString = Utils.getOption('p', options); if (binPathString.length() != 0) { setBinPath(binPathString); } Utils.checkForRemainingOptions(options); } /** * Gets the current settings * * @return an array of strings suitable for passing to setOptions() */ public String [] getOptions() { String [] options = new String [20]; int current = 0; if (m_debug) { options[current++] = "-D"; } options[current++] = "-v"; options[current++] = "" + m_verbosityLevel; if (m_autoBounds) { options[current++] = "-A"; } else { options[current++] = "-n"; options[current++] = "" + m_minMargin; options[current++] = "-m"; options[current++] = "" + m_maxMargin; } switch(m_mode) { case SVM_MODE_CLASSIFICATION: options[current++] = "-C"; break; case SVM_MODE_REGRESSION: options[current++] = "-R"; options[current++] = "-w"; options[current++] = "" + m_width; break; case SVM_MODE_PREFERENCE_RANKING: options[current++] = "-P"; break; default: System.err.println("UNKNOWN MODE: " + m_mode); } options[current++] = "-c"; options[current++] = "" + m_C; options[current++] = "-j"; options[current++] = "" + m_costFactor; if (m_biased) { options[current++] = "-b"; } if (m_removeInconsistentExamples) { options[current++] = "-i"; } switch (m_kernelType) { case KERNEL_LINEAR: options[current++] = "-L"; break; case KERNEL_POLYNOMIAL: options[current++] = "-O"; options[current++] = "-d"; options[current++] = "" + m_d; options[current++] = "-s"; options[current++] = "" + m_s; options[current++] = "-r"; options[current++] = "" + m_c1; break; case KERNEL_RBF: options[current++] = "-B"; options[current++] = "-g"; options[current++] = "" + m_gamma; break; case KERNEL_SIGMOID_TANH: options[current++] = "-S"; options[current++] = "-s"; options[current++] = "" + m_s; options[current++] = "-r"; options[current++] = "" + m_c1; break; default: System.err.println("UNKNOWN KERNEL TYPE: " + m_kernelType); } options[current++] = "-p"; options[current++] = m_binPath; while (current < options.length) { options[current++] = ""; } return options; } /** Turn debugging output on/off * @param debug if true, SVM-light output and other debugging info will be printed */ public void setDebug(boolean debug) { m_debug = debug; } /** See whether debugging output is on/off * @returns if true, SVM-light output and other debugging info will be printed */ public boolean getDebug() { return m_debug; } /** Set SVM-light to operate via in/out bufffers or via temporary files * @param bufferedMode if true, SVM-light classification is performed via stdin/stdout */ public void setBufferedMode(boolean bufferedMode) { m_bufferedMode = bufferedMode; } /** See whether SVM-light is operating via in/out bufffers or via temporary files * @returns if true, SVM-light classification is performed via stdin/stdout */ public boolean getBufferedMode() { return m_bufferedMode; } /** Set verbosity level, can be anything between 0 and 3 * @param verbosity Verbosity level for SVM-light */ public void setVerbosityLevel(int verbosity) { m_verbosityLevel = verbosity; } /** Get verbosity level, can be anything between 0 and 3 * @param verbosity Verbosity level for SVM-light */ public int getVerbosityLevel() { return m_verbosityLevel; } /** Set the mode of the SVM * @param mode one of classification, regression and preference ranking */ public void setMode(SelectedTag mode) { if (mode.getTags() == TAGS_SVM_MODE) { m_mode = mode.getSelectedTag().getID(); } } /** * return the SVM-light mode * @return one of classification, regression and preference ranking */ public SelectedTag getMode() { return new SelectedTag(m_mode, TAGS_SVM_MODE); } /** Set the epsilon width of tube for regression */ public void setWidth(double width) { m_width = width; } /** Get the epsilon width of tube for regression */ public double getWidth() { return m_width; } /** Set the trade-off between training error and margin (default 0 corresponds to [avg. x*x]^-1) */ public void setC(double C) { m_C = C; } /** Get the trade-off between training error and margin (default 0 corresponds to [avg. x*x]^-1) */ public double getC() { return m_C; } /** Set cost-factor, by which training errors on positive examples outweight errors on negative examples */ public void setCostFactor(double costFactor) { m_costFactor = costFactor; } /** Get cost-factor, by which training errors on positive examples outweight errors on negative examples */ public double getCostFactor() { return m_costFactor; } /** Set whether the hyperplane is biased (i.e. x*w+b>0) instead of unbiased hyperplane (i.e. x*w>0) * @param biased if true, the hyperplane will be biased */ public void setBiased(boolean biased) { m_biased = biased; } /** Get whether the hyperplane is biased (i.e. x*w+b>0) instead of unbiased hyperplane (i.e. x*w>0) * @returns if true, the hyperplane will be biased */ public boolean getBiased() { return m_biased; } /** Set whether the inconsistent examples are removed and retraining follows * @param removeInconsistentExamples */ public void setRemoveInconsistentExamples(boolean removeInconsistentExamples) { m_removeInconsistentExamples = removeInconsistentExamples; } /** Get whether the inconsistent examples are removed and retraining follows * @returns removeInconsistentExamples */ public boolean getRemoveInconsistentExamples() { return m_removeInconsistentExamples; } /** Set the kernel type for SVM-light * @param type one of the kernel types */ public void setKernelType(SelectedTag kernelType) { if (kernelType.getTags() == TAGS_KERNEL_TYPE) { m_kernelType = kernelType.getSelectedTag().getID(); } } /** Get the SVM-light kernel type * @return kernel type */ public SelectedTag getKernelType() { return new SelectedTag(m_kernelType, TAGS_KERNEL_TYPE); } /** Set parameter d in polynomial kernel */ public void setD(int d) { m_d = d; } /** Get parameter d in polynomial kernel */ public int getD() { return m_d; } /** Set parameter gamma in rbf kernel */ public void setGamma(double gamma) { m_gamma = gamma; } /** Get parameter gamma in rbf kernel */ public double getGamma() { return m_gamma; } /** Set parameter s in sigmoid/polynomial kernel */ public void setS(double s) { m_s = s; } /** Get parameter s in sigmoid/polynomial kernel */ public double getS() { return m_s; } /** Set parameter c in sigmoid/poly kernel */ public void setC1(double c1) { m_c1 = c1; } /** Get parameter c in sigmoid/poly kernel */ public double getC1() { return m_c1; } /** Set the maxMargin that an SVM can return */ public void setMaxMargin(double maxMargin) { m_maxMargin = maxMargin; } /** Get the maxMargin that an SVM can return */ public double getMaxMargin() { return m_maxMargin; } /** Set the minMargin that an SVM can return */ public void setMinMargin(double minMargin) { m_minMargin = minMargin; } /** Get the minMargin that an SVM can return */ public double getMinMargin() { return m_minMargin; } /** Set whether min/max margins are determined automatically */ public void setAutoBounds(boolean autoBounds) { m_autoBounds = autoBounds; } /** Get whether min/max margins are determined automatically */ public boolean getAutoBounds() { return m_autoBounds; } /** * Returns a description of this classifier. * * @return a description of this classifier as a string. */ public String toString() { if (m_train == null) { return "SVMlight: No model built yet."; } String result = "SVM-light classifier\n"; return result; } /** Set the path for the temporary files * @param tempDirPath a full path to the temporary directory */ public void setTempDirPath(String tempDirPath) { m_tempDirPath = tempDirPath; } /** Get the path for the temporary files * @returns a full path to the temporary directory */ public String getTempDirPath() { return m_tempDirPath; } /** Set the path for the binary files * @param tempDirPath a full path to the directory where SVMlight binary files are */ public void setBinPath(String binPath) { m_binPath = binPath; } /** Get the path for the binaries * @returns a full path to the binaries directory */ public String getBinPath() { return m_binPath; } /** A little helper to create a single String from an array of Strings * @param strings an array of strings * @returns a single concatenated string, separated by commas */ public static String concatStringArray(String[] strings) { String result = new String(); for (int i = 0; i < strings.length; i++) { result = result + "\"" + strings[i] + "\" "; } return result; } /** * Main method for testing this class. * * @param argv should contain command line options (see setOptions) */ public static void main(String [] argv) { try { System.out.println(Evaluation.evaluateModel(new SVMlight(), argv)); } catch (Exception e) { e.printStackTrace(); System.err.println(e.getMessage()); } } }