📄 featuregenerator.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.generator;import edu.udo.cs.yale.example.Example;import edu.udo.cs.yale.example.ExampleTable;import edu.udo.cs.yale.example.ExampleReader;import edu.udo.cs.yale.example.Attribute;import edu.udo.cs.yale.example.DataRow;import edu.udo.cs.yale.example.DataRowReader;import edu.udo.cs.yale.tools.LogService;import edu.udo.cs.yale.tools.RandomGenerator;import edu.udo.cs.yale.MethodNotSupportedException;import java.util.ArrayList;import java.util.Collection;import java.util.Hashtable;import java.util.Iterator;import java.util.List;import java.util.LinkedList;import java.util.Map;/** Abstract superclass of all attribute generators. * Implementing classes have to implement the <tt>generate(Example)</tt>, method and specify the * input and output attributes by the appropriate methods so that the using algorithms can use them * correctly. * * @author simon, ingo * @version $Id: FeatureGenerator.java,v 2.6 2003/09/10 13:02:06 fischer Exp $ */public abstract class FeatureGenerator { private static final String[] FUNCTION_NAMES2 = { "+", "-", "*", "/",// BasicArithmeticOperationGenerator.FUNCTION_NAMES[0], // BasicArithmeticOperationGenerator.FUNCTION_NAMES[1], // BasicArithmeticOperationGenerator.FUNCTION_NAMES[2], // BasicArithmeticOperationGenerator.FUNCTION_NAMES[3], "WP1.X", "WP1.Y", "Max.X", "Max.Y", "WP2.X", "WP2.Y",// FunctionCharacteristicaGenerator.FUNCTION_NAMES[0], // FunctionCharacteristicaGenerator.FUNCTION_NAMES[1], // FunctionCharacteristicaGenerator.FUNCTION_NAMES[2], // FunctionCharacteristicaGenerator.FUNCTION_NAMES[3], // FunctionCharacteristicaGenerator.FUNCTION_NAMES[4], // FunctionCharacteristicaGenerator.FUNCTION_NAMES[5], "1/",// ReciprocalValueGenerator.FUNCTION_NAMES[0] "norm" }; private static final Class[] GENERATOR_CLASSES = { BasicArithmeticOperationGenerator.class, BasicArithmeticOperationGenerator.class, BasicArithmeticOperationGenerator.class, BasicArithmeticOperationGenerator.class, FunctionCharacteristicaGenerator.class, FunctionCharacteristicaGenerator.class, FunctionCharacteristicaGenerator.class, FunctionCharacteristicaGenerator.class, FunctionCharacteristicaGenerator.class, FunctionCharacteristicaGenerator.class, ReciprocalValueGenerator.class, NormalizationGenerator.class }; /** Maps function names to generators. */ private static Map generatorMap; static { generatorMap = new Hashtable(); for (int i = 0; i < FUNCTION_NAMES2.length; i++) { generatorMap.put(FUNCTION_NAMES2[i], GENERATOR_CLASSES[i]); } } /** The attributes of the function(s) calculated by this FeatureGenerator. */ protected Attribute[] resultAttributes; /** The argument attributes on which to operate with respect to the example tables * attribute array. */ private Attribute[] arguments; private ExampleTable exampleTable; /** The number of argument combinations the generator can be applied to. This is user data * and can be set by certain algorithms that want to use the <code>selectGenerator()</code> method. * @see edu.udo.cs.yale.generator.FeatureGenerator#selectGenerator(List) */ private int argumentCombinations; public FeatureGenerator() { arguments = null; } // ------------------------------ The abstract methods ------------------------------ /** Generates the new attribute values for the example e and returns the new attribute * values as doubles. <tt>e.getAttribute(getArgument(i))</tt> is the correct way to access * argument <i>i</i>. * If the according attribute's type is VALUE_SERIES, the end index can be determined by * <tt>i_end = getExampleTable().getBlockEndIndex(getArgument(i))</tt>. Thus all values of the series * can be accessed using indices <i>i</i> through <i>i_end</i>. */ public abstract void generate(DataRow data) throws GenerationException; /** Returns an array of Attributes where the length is the arity of the generator, * <tt>[i]</tt> is the attribute type of the i-th argument. */ public abstract Attribute[] getInputAttributes(); /** Returns the generated attributes types. */ public abstract Attribute[] getOutputAttributes(ExampleTable input); /** Subclasses must implement this method so that a new instance of this generator * class is returned. The arguments and the example table will not be cloned and thus * be null. This kind of clone is needed as generating algorithms must be able * to clone generators form their pool without changing the arguments already set * for the others. */ public abstract FeatureGenerator newInstance(); /** Sets the function name. This method is only useful if subclasses can generate more * than one function. (like the BasicArithmeticOperationGenerator). */ public abstract void setFunction(String name); /** Sets the function name. This method is only useful if subclasses can generate more * than one function. (like the BasicArithmeticOperationGenerator). */ public abstract String getFunction(); // -------------------------------------------------------------------------------- protected void setExampleTable(ExampleTable et) { this.exampleTable = et; } /** Gets the example table the examples are from. */ protected ExampleTable getExampleTable() { return exampleTable; } /** Sets the arguments (indices) used in future <tt>generate(...)</tt> calls and has to be called prior * to any <tt>generate(...)</tt> calls. The caller of this method has to take care that: * <ul> * <li><tt>args.length == getInputAttributes().length</tt>, i.e. that the arity is correct. * <li>The types of the example attributes match the types specified by * <tt>getInputAttributes()</tt>. * <li>The true attribute indices are used (as used by the example set's example table) * </ul> */ public void setArguments(Attribute[] args) { arguments = args; } /** returns <tt>true</tt>, if the arguments have already been set, and <tt>false</tt> otherwise. */ public boolean argumentsSet() { return arguments != null; } /** Returns the i-th selected argument (the true index as used in the example set's * example table). */ public Attribute getArgument(int i) { return arguments[i]; } /** Checks if the arguments are compatible with the attributes specified by getInputAttributes(). */ private boolean argumentsOk(ExampleTable input) { Attribute[] inputA = getInputAttributes(); for (int i = 0; i < inputA.length; i++) { if (!arguments[i].compatible(inputA[i])) return false; } return true; } // -------------------------------------------------------------------------------- /** @see edu.udo.cs.yale.generator.FeatureGenerator#selectGenerator(List) */ public int getArgumentCombinations() { return argumentCombinations; } /** @see edu.udo.cs.yale.generator.FeatureGenerator#selectGenerator(List) */ public void setArgumentCombinations(int v) { this.argumentCombinations = v; } // -------------------------------------------------------------------------------- /** Creates a new FeatureGenerator for a given function name. */ public static FeatureGenerator createGeneratorForFunction(String functionName) { Class genClass = (Class)generatorMap.get(functionName); if (genClass == null) { LogService.logMessage("Unknown feature generator: '"+functionName+"'", LogService.ERROR); return null; } try { FeatureGenerator gen = (FeatureGenerator)genClass.newInstance(); gen.setFunction(functionName); return gen; } catch (Exception e) { LogService.logMessage("Cannot instanciate '"+genClass.getName()+"'", LogService.ERROR); return null; } } // -------------------------------------------------------------------------------- /** Randomly selects a generator from the generator list. The probability of a generator * to be selected is proportional to its number of attribute combinations as set by the * setArgumentCombinations() method. * @param generators List of {@link FeatureGenerator}s */ public static FeatureGenerator selectGenerator(List generators) { int combinationSum = 0; Iterator i = generators.iterator(); while ((i.hasNext())) { combinationSum += ((FeatureGenerator)i.next()).getArgumentCombinations(); } int r = RandomGenerator.getGlobalRandomGenerator().nextInt(combinationSum); int n = 0; i = generators.iterator(); while (i.hasNext()) { FeatureGenerator g = (FeatureGenerator)i.next(); if (n+g.getArgumentCombinations() >= r) return g; n += g.getArgumentCombinations(); } return null; } // -------------------------------------------------------------------------------- /** Generates all new attributes and updates the ExampleTable. * Returns a list of Attributes for the newly generated attributes. * @param exampleTable the source example table * @param generatorList List of FeatureGenerators * @return A list of AttributeReferences */ public static List generateAll(ExampleTable exampleTable, Collection generatorList) throws GenerationException { LogService.logMessage("Starting feature generation with " + generatorList.size() + " generators.", LogService.OPERATOR); Iterator gi = generatorList.iterator(); while (gi.hasNext()) ((FeatureGenerator)gi.next()).setExampleTable(exampleTable); // for performance reasons convert the list to an array FeatureGenerator[] generators = new FeatureGenerator[generatorList.size()]; Iterator li = generatorList.iterator(); int g = 0; while (li.hasNext()) generators[g++] = (FeatureGenerator)li.next(); List newAttributeList = newAttributes(generators, exampleTable); double[] minimum = new double[newAttributeList.size()]; double[] maximum = new double[newAttributeList.size()]; double[] average = new double[newAttributeList.size()]; for (int n = 0; n < newAttributeList.size(); n++) { minimum[n] = Double.POSITIVE_INFINITY; maximum[n] = Double.NEGATIVE_INFINITY; average[n] = 0; } // add the attributes to the example table and ensure length of the DataRows exampleTable.addAttributes(newAttributeList); LogService.logMessage("Generator list: " + generatorList, LogService.TASK); LogService.logMessage("Input set has " + exampleTable.getAttributeCount() + " features, " + exampleTable.getSize() + " examples.", LogService.OPERATOR); // generate the attribute values: DataRowReader reader = exampleTable.getDataReader(); // for all examples: while (reader.hasNext()) { DataRow dataRow = reader.next(); for (int j = 0; j < generators.length; j++) { generators[j].generate(dataRow); } int k = 0; Iterator j = newAttributeList.iterator(); while (j.hasNext()) { Attribute generatedAttribute = (Attribute)j.next(); //int index = generatedAttribute.getIndex(); double value = dataRow.get(generatedAttribute); minimum[k] = Math.min(minimum[k], value); maximum[k] = Math.max(maximum[k], value); average[k] += value; k++; } } // set the calculated minimum, maximum and average of each attribute int k = 0; Iterator i = newAttributeList.iterator(); while (i.hasNext()) { Attribute attribute = (Attribute)i.next(); average[k] /= exampleTable.getSize(); attribute.setMinimum(minimum[k]); attribute.setMaximum(maximum[k]); attribute.setAverage(average[k]); k++; } LogService.logMessage("Finished feature generation.", LogService.OPERATOR); LogService.logMessage("Generated set has " + exampleTable.getAttributeCount() + " features, " + exampleTable.getSize() + " examples.", LogService.OPERATOR); return newAttributeList; } /** Returns a list of new Attributes that are generated by the given generators. */ private static List newAttributes(FeatureGenerator[] generators, ExampleTable exampleTable) { List newAttributeList = new LinkedList(); // add the attributes to the attribute set for (int i = 0; i < generators.length; i++) { Attribute outputAttribute[] = generators[i].getOutputAttributes(exampleTable); generators[i].resultAttributes = new Attribute[outputAttribute.length]; for (int j = 0; j < outputAttribute.length; j++) { Attribute newAttribute = exampleTable.getAttribute(outputAttribute[j]); if (newAttribute == null) { newAttributeList.add(outputAttribute[j]); generators[i].resultAttributes[j] = outputAttribute[j]; } else { generators[i].resultAttributes[i] = null; LogService.logMessage("Attribute '"+outputAttribute[j].getConstructionDescription()+ "' already generated", LogService.MINIMUM); } } // check the arguments if (!generators[i].argumentsSet()) { throw new RuntimeException("Catastrophic error: arguments not set for "+generators[i]+"!"); } if (!generators[i].argumentsOk(exampleTable)) { LogService.logMessage("Wrong argument types for " + generators[i] + ".", LogService.WARNING); } } return newAttributeList; } public String toString() { return "FeatureGenerator (" + getClass().getName() + ")"; } /** A FeatureGenerator equals another FeatureGenerator if its class is equal and its arguments are equal * and its function names are equal. */ public boolean equals(Object o) { if (!this.getClass().equals(o.getClass())) return false; FeatureGenerator fg = (FeatureGenerator)o; if (!this.getFunction().equals(fg.getFunction())) return false; if (this.arguments.length != fg.arguments.length) return false; for (int i = 0; i < arguments.length; i++) { if (!this.arguments[i].equals(fg.arguments[i])) return false; } return true; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -