/* * 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 3 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, see <http://www.gnu.org/licenses/>. */ /* * SerializedClassifier.java * Copyright (C) 2007-2012 University of Waikato, Hamilton, New Zealand */ package weka.classifiers.misc; import java.io.File; import java.util.Enumeration; import java.util.Vector; import weka.classifiers.AbstractClassifier; import weka.classifiers.Classifier; import weka.core.Capabilities; import weka.core.Capabilities.Capability; import weka.core.Instance; import weka.core.Instances; import weka.core.Option; import weka.core.RevisionUtils; import weka.core.SerializationHelper; import weka.core.Utils; /** <!-- globalinfo-start --> * A wrapper around a serialized classifier model. This classifier loads a serialized models and uses it to make predictions.<br/> * <br/> * Warning: since the serialized model doesn't get changed, cross-validation cannot bet used with this classifier. * <p/> <!-- globalinfo-end --> * <!-- options-start --> * Valid options are: <p/> * * <pre> -D * If set, classifier is run in debug mode and * may output additional info to the console</pre> * * <pre> -model <filename> * The file containing the serialized model. * (required)</pre> * <!-- options-end --> * * @author fracpete (fracpete at waikato dot ac dot nz) * @version $Revision: 8034 $ */ public class SerializedClassifier extends AbstractClassifier { /** for serialization */ private static final long serialVersionUID = 4599593909947628642L; /** the serialized classifier model used for making predictions */ protected transient Classifier m_Model = null; /** the file where the serialized model is stored */ protected File m_ModelFile = new File(System.getProperty("user.dir")); /** * Returns a string describing classifier * * @return a description suitable for displaying in the * explorer/experimenter gui */ public String globalInfo() { return "A wrapper around a serialized classifier model. This classifier loads " + "a serialized models and uses it to make predictions.\n\n" + "Warning: since the serialized model doesn't get changed, cross-validation " + "cannot bet used with this classifier."; } /** * Gets an enumeration describing the available options. * * @return an enumeration of all the available options. */ public Enumeration listOptions(){ Vector result; Enumeration enm; result = new Vector(); enm = super.listOptions(); while (enm.hasMoreElements()) result.addElement(enm.nextElement()); result.addElement(new Option( "\tThe file containing the serialized model.\n" + "\t(required)", "model", 1, "-model <filename>")); return result.elements(); } /** * returns the options of the current setup * * @return the current options */ public String[] getOptions(){ int i; Vector result; String[] options; result = new Vector(); options = super.getOptions(); for (i = 0; i < options.length; i++) result.add(options[i]); result.add("-model"); result.add("" + getModelFile()); return (String[]) result.toArray(new String[result.size()]); } /** * Parses the options for this object. <p/> * <!-- options-start --> * Valid options are: <p/> * * <pre> -D * If set, classifier is run in debug mode and * may output additional info to the console</pre> * * <pre> -model <filename> * The file containing the serialized model. * (required)</pre> * <!-- options-end --> * * @param options the options to use * @throws Exception if setting of options fails */ public void setOptions(String[] options) throws Exception { String tmpStr; super.setOptions(options); tmpStr = Utils.getOption("model", options); if (tmpStr.length() != 0) setModelFile(new File(tmpStr)); else setModelFile(new File(System.getProperty("user.dir"))); } /** * Returns the tip text for this property * * @return tip text for this property suitable for * displaying in the explorer/experimenter gui */ public String modelFileTipText() { return "The serialized classifier model to use for predictions."; } /** * Gets the file containing the serialized model. * * @return the file. */ public File getModelFile() { return m_ModelFile; } /** * Sets the file containing the serialized model. * * @param value the file. */ public void setModelFile(File value) { m_ModelFile = value; if (value.exists() && value.isFile()) { try { initModel(); } catch (Exception e) { throw new IllegalArgumentException("Cannot load model from file '" + value + "': " + e); } } } /** * Sets the fully built model to use, if one doesn't want to load a model * from a file or already deserialized a model from somewhere else. * * @param value the built model * @see #getCurrentModel() */ public void setModel(Classifier value) { m_Model = value; } /** * Gets the currently loaded model (can be null). Call buildClassifier method * to load model from file. * * @return the current model * @see #setModel(Classifier) */ public Classifier getCurrentModel() { return m_Model; } /** * loads the serialized model if necessary, throws an Exception if the * derserialization fails. * * @throws Exception if deserialization fails */ protected void initModel() throws Exception { if (m_Model == null) m_Model = (Classifier) SerializationHelper.read(m_ModelFile.getAbsolutePath()); } /** * Returns default capabilities of the base classifier. * * @return the capabilities of the base classifier */ public Capabilities getCapabilities() { Capabilities result; // init model if necessary if (m_ModelFile != null && m_ModelFile.exists() && m_ModelFile.isFile()) { try { initModel(); } catch (Exception e) { System.err.println(e); } } if (m_Model != null) { result = m_Model.getCapabilities(); } else { result = new Capabilities(this); result.disableAll(); } // set dependencies for (Capability cap: Capability.values()) result.enableDependency(cap); result.setOwner(this); return result; } /** * Calculates the class membership probabilities for the given test * instance. * * @param instance the instance to be classified * @return preedicted class probability distribution * @throws Exception if distribution can't be computed successfully */ public double[] distributionForInstance(Instance instance) throws Exception { double[] result; // init model if necessary initModel(); result = m_Model.distributionForInstance(instance); return result; } /** * loads only the serialized classifier * * @param data the training instances * @throws Exception if something goes wrong */ public void buildClassifier(Instances data) throws Exception { // init model if necessary initModel(); // can classifier handle the data? getCapabilities().testWithFail(data); } /** * Returns a string representation of the classifier * * @return the string representation of the classifier */ public String toString() { StringBuffer result; if (m_Model == null) { result = new StringBuffer("No model loaded yet."); } else { result = new StringBuffer(); result.append("SerializedClassifier\n"); result.append("====================\n\n"); result.append("File: " + getModelFile() + "\n\n"); result.append(m_Model.toString()); } return result.toString(); } /** * Returns the revision string. * * @return the revision */ public String getRevision() { return RevisionUtils.extract("$Revision: 8034 $"); } /** * Runs the classifier with the given options * * @param args the commandline options */ public static void main(String[] args) { runClassifier(new SerializedClassifier(), args); } }