All Downloads are FREE. Search and download functionalities are using the official Maven repository.

weka.core.setupgenerator.MLPLayersParameter Maven / Gradle / Ivy

There is a newer version: 2021.2.17
Show newest version
/*
 *   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 .
 */

/*
 * MLPLayersParameter.java
 * Copyright (C) 2008-2018 University of Waikato, Hamilton, New Zealand
 */

package weka.core.setupgenerator;

import weka.core.Option;
import weka.core.Utils;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Vector;

/**
 * Container specialized class for the hiddenLayers search parameter of the
 * MultiLayerPerceptron.
 *
 * @author janvanrijn (janvanrijn at gmail dot com)
 * @version $Revision: 4521 $
 */
public class MLPLayersParameter extends AbstractPropertyParameter {

  /** for serialization. */
  private static final long serialVersionUID = -5119694776105238138L;

  /** restricts the number of candidates that are being generated exhaustively **/
  public final static int MAX_CANDIDATES_TO_GENERATE = 65536;

  /** default value for minLayers **/
  protected final static int MIN_LAYERS_DEFAULT = 1;

  /** default value for maxLayers **/
  protected final static int MAX_LAYERS_DEFAULT = 2;

  /** default value for minLayerSize **/
  protected final static int MIN_LAYER_SIZE_DEFAULT = 8;

  /** default value for maxLayerSize **/
  protected final static int MAX_LAYER_SIZE_DEFAULT = 128;

  /** the minimum numbers of layers. */
  protected int m_MinLayers = MIN_LAYERS_DEFAULT;

  /** the maximum number of layers. */
  protected int m_MaxLayers = MAX_LAYERS_DEFAULT;

  /** the minimum size of each layer **/
  protected int m_MinLayerSize = MIN_LAYER_SIZE_DEFAULT;

  /** the maximum size of each layer **/
  protected int m_MaxLayerSize = MAX_LAYER_SIZE_DEFAULT;

  /**
   * Returns a string describing the object.
   *
   * @return a description suitable for displaying in the explorer/experimenter
   *         gui
   */
  public String globalInfo() {
    return "Container class defining the hiddenLayer search parameter "
      + "of the MultiLayerPerceptron.\n"
      + "Given minLayers, maxLayers, minLayerSize and maxLayerSize, "
      + "it generates a comma-separated string s integers, such that "
      + "minLayers <= s <= maxLayers, and for every integer n "
      + "minLayerSize <= n <= maxLayerSize. ";
  }

  /**
   * 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.add(enm);

    result.addElement(new Option(
      "\tThe minimum number of layers.\n" + "\t(default: " + MIN_LAYERS_DEFAULT + ")",
      "minLayers", MIN_LAYERS_DEFAULT, "-minLayers "));

    result.addElement(new Option(
      "\tThe maximal number of layers.\n" + "\t(default: " + MAX_LAYERS_DEFAULT + ")",
      "maxLayers", MAX_LAYERS_DEFAULT, "-maxLayers "));

    result.addElement(new Option(
      "\tTThe minimum size for each layer.\n" + "\t(default: "
	+ MIN_LAYER_SIZE_DEFAULT + ")",
      "minLayerSize", MIN_LAYER_SIZE_DEFAULT, "-minLayerSize "));

    result.addElement(new Option(
      "\tTThe maximal size for each layer.\n" + "\t(default: "
	+ MAX_LAYER_SIZE_DEFAULT + ")",
      "maxLayerSize", MAX_LAYER_SIZE_DEFAULT, "-maxLayerSize "));

    return result.elements();
  }

  /**
   * returns the options of the current setup.
   *
   * @return the current options
   */
  public String[] getOptions() {
    Vector result;
    String[] options;
    int i;

    result = new Vector();

    options = super.getOptions();
    for (i = 0; i < options.length; i++)
      result.add(options[i]);

    result.add("-minLayers");
    result.add("" + getMinLayers());

    result.add("-maxLayers");
    result.add("" + getMaxLayers());

    result.add("-minLayerSize");
    result.add("" + getMinLayerSize());

    result.add("-maxLayerSize");
    result.add("" + getMaxLayerSize());

    return result.toArray(new String[result.size()]);
  }

  /**
   * Parses the options for this object.
   *
   * @param options
   *          the options to use
   * @throws Exception
   *           if setting of options fails
   */
  public void setOptions(String[] options) throws Exception {
    String tmpStr;

    tmpStr = Utils.getOption("minLayers", options);
    if (tmpStr.length() != 0)
      setMinLayers(Integer.parseInt(tmpStr));
    else
      setMinLayers(MIN_LAYERS_DEFAULT);

    tmpStr = Utils.getOption("maxLayers", options);
    if (tmpStr.length() != 0)
      setMaxLayers(Integer.parseInt(tmpStr));
    else
      setMaxLayers(MAX_LAYERS_DEFAULT);

    tmpStr = Utils.getOption("minLayerSize", options);
    if (tmpStr.length() != 0)
      setMinLayerSize(Integer.parseInt(tmpStr));
    else
      setMinLayerSize(MIN_LAYER_SIZE_DEFAULT);

    tmpStr = Utils.getOption("maxLayerSize", options);
    if (tmpStr.length() != 0)
      setMaxLayerSize(Integer.parseInt(tmpStr));
    else
      setMaxLayerSize(MIN_LAYER_SIZE_DEFAULT);

    checkStructureParams();

    super.setOptions(options);
  }

  /**
   * Returns the tip text for this property.
   *
   * @return tip text for this property suitable for displaying in the
   *         explorer/experimenter gui
   */
  public String minLayersTipText() {
    return "The minimal number of layers to generate";
  }

  /**
   * Returns the value for this property.
   *
   * @return the number of layers to generate
   */
  public int getMinLayers() {
    return m_MinLayers;
  }

  /**
   * Sets the value for this property.
   *
   * @param minLayers
   *          minimal number of layers to generate
   */
  public void setMinLayers(int minLayers) {
    this.m_MinLayers = minLayers;
  }


  /**
   * Returns the tip text for this property.
   *
   * @return tip text for this property suitable for displaying in the
   *         explorer/experimenter gui
   */
  public String maxLayersTipText() {
    return "The maximal number of layers to generate";
  }

  /**
   * Returns the value for this property.
   *
   * @return the number of layers to generate
   */
  public int getMaxLayers() {
    return m_MaxLayers;
  }

  /**
   * Sets the value for this property.
   *
   * @param maxLayers
   *          maximal number of layers to generate
   */
  public void setMaxLayers(int maxLayers) {
    this.m_MaxLayers = maxLayers;
  }

  /**
   * Returns the tip text for this property.
   *
   * @return tip text for this property suitable for displaying in the
   *         explorer/experimenter gui
   */
  public String minLayerSizeTipText() {
    return "The minimum size of each layer";
  }

  /**
   * Returns the value for this property.
   *
   * @return the minimum layer size
   */
  public int getMinLayerSize() {
    return m_MinLayerSize;
  }

  /**
   * Sets the value for this property.
   *
   * @param minLayerSize
   *          minimum layer size
   */
  public void setMinLayerSize(int minLayerSize) {
    this.m_MinLayerSize = minLayerSize;
  }

  /**
   * Returns the tip text for this property.
   *
   * @return tip text for this property suitable for displaying in the
   *         explorer/experimenter gui
   */
  public String maxLayerSizeTipText() {
    return "The maximum size of each layer";
  }

  /**
   * Returns the value for this property.
   *
   * @return the maximum layer size
   */
  public int getMaxLayerSize() {
    return m_MaxLayerSize;
  }

  /**
   * Sets the value for this property.
   *
   * @param maxLayerSize
   *          maximum layer size
   */
  public void setMaxLayerSize(int maxLayerSize) {
    this.m_MaxLayerSize = maxLayerSize;
  }

  /**
   * Calculates the number of possible candidate structures
   *
   * @return number of possible candidate structures
   */
  public long calculateNumberOfCandidates() {
    long result = 0L;
    for (int i = getMinLayers(); i <= getMaxLayers(); ++i) {
      result += Math.pow(getMaxLayerSize() - getMinLayerSize() + 1, i);
    }
    return result;
  }

  /**
   * Checks the given parameters for simple constraint violations
   */
  private void checkStructureParams() throws Exception {
    if (getMaxLayerSize() < getMinLayerSize()) {
      throw new Exception(
	"minLayerSize should be smaller than or equal to maxLayerSize");
    }
    if (getMaxLayers() < getMinLayers()) {
      throw new Exception(
	"minLayers should be smaller than or equal to maxLayers");
    }
    if (getMaxLayers() == getMinLayers() && getMaxLayerSize() == getMinLayerSize()) {
      throw new Exception(
	"no variation in layer structure possible");
    }
  }

  /**
   * Converts a List of integers into a delimited string
   *
   * @param list: the list to convert
   * @param delimiter: the separation string, typically a comma
   * @return the imploded list
   */
  private String implodeList(List list, String delimiter) {
    StringBuilder sb = new StringBuilder();
    for (Integer i : list) {
      sb.append(delimiter + i);
    }
    return sb.toString().substring(delimiter.length());
  }

  /**
   * Generates MLP layer structures randomly
   *
   * @param numCandidates: the number of candidates to generate
   * @param seed: the random seed to use for the RNG
   * @return the layer structures
   */
  private HashSet generateCandicatesRandom(int numCandidates, long seed) {
    Random random = new Random(seed);
    HashSet result = new HashSet();
    while (result.size() < numCandidates) {
      List current = new ArrayList();
      while (current.size() < getMaxLayers()) {
	final int range = getMaxLayerSize() - getMinLayerSize() + 1;
	final int currentLayerSize = random.nextInt(range) + getMinLayerSize();
	current.add(currentLayerSize);
	if (current.size() > getMinLayers()) {
	  String currentAsStr = implodeList(current, ",");
	  result.add(currentAsStr);
	  if (result.size() >= numCandidates) {
	    break;
	  }
	}
      }
    }
    return result;
  }

  /**
   * Generates recursively all possible MLP layer structures within the
   * constraints
   *
   * @param currentLayers: partial generated layer
   * @return the layer structures
   */
  private ArrayList generateCandidatesExhaustive(ArrayList currentLayers) {
    if (currentLayers.size() >= getMaxLayers()) {
      ArrayList result = new ArrayList();
      result.add(implodeList(currentLayers, ","));
      return result;
    } else {
      ArrayList result = new ArrayList();
      // add current result
      if (currentLayers.size() >= getMinLayers()) {
	result.add(implodeList(currentLayers, ","));
      }
      // generate layers of higher size
      for (int i = getMinLayerSize(); i <= getMaxLayerSize(); ++i) {
	currentLayers.add(i);
	result.addAll(generateCandidatesExhaustive(currentLayers));
	currentLayers.remove(currentLayers.size()-1);
      }
      return result;
    }
  }

  /**
   * Generates all possible number of layer combinations
   *
   * @return a list of all possible items
   * @throws Exception
   *           if the splitting fails
   */
  public String[] getItems() throws Exception {
    checkStructureParams();

    AbstractCollection result;
    if (calculateNumberOfCandidates() >= MAX_CANDIDATES_TO_GENERATE) {
      // Random seed does not need to be parameterized, as it will barely
      // influence results
      result = generateCandicatesRandom(MAX_CANDIDATES_TO_GENERATE, 0L);
    } else {
      result = generateCandidatesExhaustive(new ArrayList());
    }
    return result.toArray(new String[result.size()]);
  }

  /**
   * Returns a string representation of the search parameter.
   *
   * @return a string representation
   */
  public String toString() {
    String result;

    result = super.toString();
    result += ", minLayers: " + m_MinLayers;
    result += ", maxLayers: " + m_MaxLayers;
    result += ", minLayerSize: " + m_MinLayerSize;
    result += ", maxLayerSize: " + m_MaxLayerSize;
    return result;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy