📄 svmlightlearner.java
字号:
/* * YALE - Yet Another Learning Environment * Copyright (C) 2002, 2003 * Simon Fischer, Ralf Klinkenberg, Ingo Mierswa, * Katharina Morik, Oliver Ritthoff * Artificial Intelligence Unit * Computer Science Department * University of Dortmund * 44221 Dortmund, Germany * email: yale@ls8.cs.uni-dortmund.de * web: http://yale.cs.uni-dortmund.de/ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */package edu.udo.cs.yale.operator.learner;import edu.udo.cs.yale.example.Attribute;import edu.udo.cs.yale.example.ExampleReader;import edu.udo.cs.yale.example.ExampleSet;import edu.udo.cs.yale.example.Example;import edu.udo.cs.yale.example.BatchedExampleSet; // RK/2002/09/13import edu.udo.cs.yale.operator.Operator;import edu.udo.cs.yale.operator.UserError;import edu.udo.cs.yale.operator.MissingIOObjectException;import edu.udo.cs.yale.operator.OperatorException;import edu.udo.cs.yale.operator.FatalException;import edu.udo.cs.yale.operator.parameter.*;import edu.udo.cs.yale.operator.learner.Learner;import edu.udo.cs.yale.operator.learner.Model;import edu.udo.cs.yale.operator.performance.PerformanceVector;import edu.udo.cs.yale.operator.performance.EstimatedPerformance;import edu.udo.cs.yale.tools.LogService;import edu.udo.cs.yale.tools.Ontology;import edu.udo.cs.yale.tools.Tools;import edu.udo.cs.yale.tools.TempFileService;import edu.udo.cs.yale.tools.ParameterService;import java.util.ArrayList;import java.util.List;import java.util.StringTokenizer;import java.io.*;/** <code>SVMLightLearner</code> encapsulates the external * <a TARGET="_top" href="http://svmlight.joachims.org/">SVM<sup>light</sup></a> * program by * <a TARGET="_top" href="http://www.joachims.org/">Thorsten Joachims</a> {@yale.cite Joachims/99a}, * an implementation of Vladimir Vapnik's Support Vector Machine (SVM) * learning method from statistical learning theory for the * problem of pattern recognition (classification) {@yale.cite Vapnik/98a}. * The algorithm has scalable memory requirements and can handle problems * with many thousands of support vectors efficiently.<br/> * If there are two {@link ExampleSet}s in the input, the learner performs transduction. * The first is assumed to be the labeled training data and the second may contain examples without * labels, e.g. the test set. * <p> * This learner writes the training set to a file and calls the native * version of the SVM<sup>light</sup>. In order to do that, the binaries * must be correctly installed and the properties <code>yale.svmlight.learncommand</code> and * <code>yale.svmlight.applycommand</code> must be correctly set in any of the yalrc * configuraion files. * </p> * * @yale.xmlclass SVMLightLearner * @yale.reference Joachims/99a * @yale.reference Vapnik/98a * @yale.index SVM * @author Ingo Mierswa, Simon Fischer, Ralf Klinkenberg * @version $Id: SVMLightLearner.java,v 2.21 2003/08/28 14:31:06 fischer Exp $ */public class SVMLightLearner extends Learner { /* To Do: * Internal note: For transduction do the following: * <ul> * <li>Create a new attribute that will be used as label: label = new Attribute(...)</li> * <li>Add the label to the ExampleTable</li> * <li>Clone the original exampleSet and use it as temp for generating the label values * <li>Append a new AttributeReference to the temp * <li>Iterate over all examples and set the value of the new label attribute according * to your needs (e.g. example.setValue(label, "missing"))</li> * <li>Clone the original example set once again</li> * <li>Call setLabel(label) on this new example set</li> * <li>Call setUnlabelledLabelIndex(label.mapString("missing")) on the SVMLightLearner</li> * </ul> * IDEA: Maybe subclass FeatureGenerator to generate the new label? * * History: * RK/2002/07/05: performance estimation on all batches only and only with xi-alpha estimators * using the estimator values provided in the SVM^light standard output; * RK/2002/09/13: added alternative performance evaluation by reading alpha values from a * separate SVM^light output file and computing the sum of alphas estimation, * sum of alphas greater one estimation, no. of alphas greater one estimation * (on all batches or on last batch only (if (ExampleSet instanceof BatchedExampleSet))); * RK/2003/03/26: merger of RK's Yale 1.0 version of this file into Yale 2.0; */ private static final String[] KERNEL_TYPES = {"linear","polynomial","rbf","sigmoid"}; static final int ESTIMATION_CRITERION_XI_ALPHA_ERROR = 0; // RK/2002/09/13 static final int ESTIMATION_CRITERION_ALPHA_SUM = 1; // RK/2002/09/13 static final int ESTIMATION_CRITERION_ALPHA_GREATER_ONE_SUM = 2; // RK/2002/09/13 static final int ESTIMATION_CRITERION_NO_OF_ALPHAS_GREATER_ONE = 3; // RK/2002/09/13 private int positiveLabelIndex = Attribute.FIRST_CLASS_INDEX; private int unlabelledIndex = -1; private PerformanceVector performanceEstimation; /** creates configuration files and start the learning process on the given examples. * Returns a model or null, if it can not be created. */ public Model learn(ExampleSet exampleSet) throws OperatorException { LogService.logMessage("SVMLightLearner '"+getName()+"': SVMlight starts learning.", LogService.TASK); ExampleSet transductionExampleSet = null; try { transductionExampleSet = (ExampleSet)getInput(ExampleSet.class); if (transductionExampleSet != null) { LogService.logMessage("SVMLightLearner '"+getName()+"': Found "+ exampleSet.getSize()+" examples for transduction.", LogService.TASK); } } catch (MissingIOObjectException e) {} Attribute labelAtt = exampleSet.getLabel(); if (!Ontology.ATTRIBUTE_VALUE_TYPE.isA(labelAtt.getValueType(), Ontology.NOMINAL)) { throw new FatalException("SVMLightLearner '"+getName()+"': Training set does " + "not have nominal labels!"); } // this is already checked by taskIsClassification()// if (labelAtt.getNumberOfClasses() != 2) {// LogService.logMessage("SVMLightLearner '"+getName()+"': Training set label "// + "should have exactly two classes, but has " +// labelAtt.getNumberOfClasses(), LogService.ERROR);// } // error estimation on all batches (default) or on last batch only (concept drift experiments)? boolean estimateOnAllBatches = !(exampleSet instanceof BatchedExampleSet); // RK/2002/09/13 // Aus- und Eingabedatei vorbereiten boolean classificationTask = taskIsClassification(getParameterAsInt("task_type"), exampleSet); File trainingFile = writeExamples(exampleSet, transductionExampleSet, classificationTask); // Bestimme Parameter int kernelType = getParameterAsInt("kernel_type"); String parameters = getParameterAsString("additional_parameters"); if (parameters == null) parameters = ""; String command = ParameterService.getProperty("yale.svmlight.learncommand"); File modelFile = TempFileService.createTempFile(getName()+"_model_"); File alphaFile = TempFileService.createTempFile(getName()+"_alphas_"); // RK/2002/09/13 LogService.logMessage(getName()+": Using " +(classificationTask ? "classification" : "regression")+" mode.", LogService.MINIMUM); // Prozess starten Process process = null; String completeCommand; String options = " -t " + kernelType + " -z "+(classificationTask ? "c" : "r"); if (estimateOnAllBatches) { completeCommand = command + options + " " + parameters + " " + trainingFile + " " + modelFile; } else { completeCommand = command + options + " -a " + alphaFile + " " + parameters + " " + trainingFile + " " + modelFile; } LogService.logMessage("SVMLightLearner '"+getName()+"': SVMlight called with command '" + completeCommand + "'", LogService.TASK); try { process = Runtime.getRuntime().exec(completeCommand); } catch (IOException e) { TempFileService.deleteTempFile(modelFile); TempFileService.deleteTempFile(alphaFile); TempFileService.deleteTempFile(trainingFile); throw new FatalException("SVMLightLearner '"+getName()+"': " + "Cannot find command for SVMlight!", e); } // ---- get output ---- BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); // output of the external SVM^light process String output = null; try { output = Tools.readOutput(in);; } catch (IOException e) { TempFileService.deleteTempFile(modelFile); TempFileService.deleteTempFile(alphaFile); TempFileService.deleteTempFile(trainingFile); throw new UserError(this, e, 308, "SVMlight"); } try { Tools.waitForProcess(this, process, "svmlight"); } catch (OperatorException e) { TempFileService.deleteTempFile(modelFile); TempFileService.deleteTempFile(alphaFile); TempFileService.deleteTempFile(trainingFile); LogService.logMessage("Output of svm_learn:\n"+output, LogService.ERROR); throw e; } try { in.close(); } catch (IOException e) { TempFileService.deleteTempFile(modelFile); TempFileService.deleteTempFile(alphaFile); TempFileService.deleteTempFile(trainingFile); LogService.logException("SVMLightLearner '"+getName()+"': " +"Cannot close SVMlight input stream.", e); return null; } LogService.logMessage(output, LogService.MINIMUM); LogService.logMessage("SVMlight has succesfully trained a model.", LogService.TASK); // scan the output for xi-alpha-values and create an EstimatedPerformance-object, // if they are there (estimation on all batches), or compute performance criterion // from file with SVM^light alpha values (estimation on last batch only): if (estimateOnAllBatches) { // RK/2002/09/13 performanceEstimation = scanXiAlpha(output, exampleSet.getSize()); // RK/2002/09/13: old } else { // RK/2002/09/13 performanceEstimation = scanXiAlpha(exampleSet,alphaFile); // RK/2002/09/13: new } // RK/2002/09/13 // return the learned model (encapsulating the corresponding model file) try { return new SVMLightModel(modelFile, classificationTask); } catch (IOException e) { throw new UserError(this, e, 302, new Object[] { modelFile, e.getMessage() }); } finally { TempFileService.deleteTempFile(modelFile); TempFileService.deleteTempFile(alphaFile); TempFileService.deleteTempFile(trainingFile); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -