/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program is free software: you can redistribute it and/or modify it under the terms of the * GNU Affero 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 * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License along with this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.operator.learner.functions.kernel.evosvm; import com.rapidminer.datatable.DataTable; import com.rapidminer.datatable.SimpleDataTable; import com.rapidminer.datatable.SimpleDataTableRow; import com.rapidminer.example.Attribute; import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; import com.rapidminer.gui.plotter.SimplePlotterDialog; import com.rapidminer.operator.Operator; import com.rapidminer.operator.learner.functions.kernel.SupportVector; import com.rapidminer.operator.performance.EstimatedPerformance; import com.rapidminer.operator.performance.PerformanceVector; import com.rapidminer.tools.RandomGenerator; import com.rapidminer.tools.math.kernels.Kernel; import com.rapidminer.tools.math.optimization.ec.pso.PSOOptimization; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * PSO approach for SVM optimization. Currently only classification problems are supported. * * @author Ingo Mierswa Exp $ */ public class PSOSVMOptimization extends PSOOptimization { /** Number smaller than this number are regarded as zero. */ private final static double IS_ZERO = 1e-10; /** The training example set. */ private ExampleSet exampleSet; /** The used kernel function. */ private Kernel kernel; /** This parameter indicates the weight of errors. */ private double c; /** This parameter indicates the weight of errors for regression. */ private double epsilon = 0.0d; /** The label values. */ private double[] ys; /** This function is to maximize. */ private OptimizationFunction optimizationFunction; /** Indicates if a convergence plot should be drawn. */ private boolean showPlot = false; private DataTable dataTable; private SimplePlotterDialog plotter; /** * @deprecated Since 7.4. Please use * {@link #PSOSVMOptimization(ExampleSet, Kernel, double, int, int, int, double, double, double, boolean, boolean, RandomGenerator, Operator) * PSOSVMOptimization} if an operator is known to monitor operator progress and stop * long running processes if necessary. */ @Deprecated public PSOSVMOptimization(ExampleSet exampleSet, // training data Kernel kernel, double c, // double epsilon, // SVM paras int maxIterations, int generationsWithoutImprovement, // convergence // paras int popSize, double inertiaWeight, double localWeight, double globalWeight, boolean dynamicInertiaWeight, boolean showPlot, RandomGenerator random) { this(exampleSet, kernel, c, maxIterations, generationsWithoutImprovement, popSize, inertiaWeight, localWeight, globalWeight, dynamicInertiaWeight, showPlot, random, null); } /** Creates a new evolutionary SVM optimization. */ public PSOSVMOptimization(ExampleSet exampleSet, // training data Kernel kernel, double c, // double epsilon, // SVM paras int maxIterations, int generationsWithoutImprovement, // convergence // paras int popSize, double inertiaWeight, double localWeight, double globalWeight, boolean dynamicInertiaWeight, boolean showPlot, RandomGenerator random, Operator op) { super(popSize < 1 ? exampleSet.size() : popSize, exampleSet.size(), maxIterations, generationsWithoutImprovement, inertiaWeight, localWeight, globalWeight, 0.0d, 1.0d, dynamicInertiaWeight, random, op); this.exampleSet = exampleSet; this.kernel = kernel; this.kernel.init(exampleSet); this.c = c; if (this.c <= 0.0d) { this.c = 0.0d; for (int i = 0; i < exampleSet.size(); i++) { this.c += kernel.getDistance(i, i); } this.c = exampleSet.size() / this.c; exampleSet.getLog().log("Determine probably good value for C: set to " + this.c); } setMinValue(0.0d); setMaxValue(this.c); // label values this.ys = new double[exampleSet.size()]; Iterator<Example> reader = exampleSet.iterator(); int index = 0; Attribute label = exampleSet.getAttributes().getLabel(); boolean regression = !label.isNominal() && label.getMapping().size() != 2; while (reader.hasNext()) { Example example = reader.next(); if (!regression) { ys[index++] = example.getLabel() == label.getMapping().getPositiveIndex() ? 1.0d : -1.0d; } else { ys[index++] = example.getLabel(); } } // optimization function if (!regression) { this.optimizationFunction = new ClassificationOptimizationFunction(false); } else { this.optimizationFunction = new RegressionOptimizationFunction(epsilon); } // plotter this.showPlot = showPlot; if (showPlot) { dataTable = new SimpleDataTable("Fitness vs. Generations", new String[] { "Generations", "Best Fitness", "Current Fitness" }); plotter = new SimplePlotterDialog(dataTable, false); plotter.setXAxis(0); plotter.plotColumn(1, true); plotter.plotColumn(2, true); plotter.setVisible(true); } } @Override public void nextIteration() { if (showPlot) { dataTable.add(new SimpleDataTableRow(new double[] { getGeneration(), getBestFitnessEver(), getBestFitnessInGeneration() })); } } /** Evaluates the individuals of the given population. */ @Override public PerformanceVector evaluateIndividual(double[] individual) { double fitness = optimizationFunction.getFitness(individual, ys, kernel)[0]; PerformanceVector result = new PerformanceVector(); result.addCriterion(new EstimatedPerformance("SVMOptValue", fitness, 1, false)); return result; } /** * Returns a model containing all support vectors, i.e. the examples with non-zerp alphas. */ public EvoSVMModel getModel(double[] alphas) { if (showPlot) { plotter.dispose(); } // calculate support vectors Attribute[] regularAttributes = exampleSet.getAttributes().createRegularAttributeArray(); Iterator<Example> reader = exampleSet.iterator(); List<SupportVector> supportVectors = new ArrayList<SupportVector>(); int index = 0; while (reader.hasNext()) { double currentAlpha = alphas[index]; Example currentExample = reader.next(); if (currentAlpha != 0.0d) { double[] x = new double[regularAttributes.length]; int a = 0; for (Attribute attribute : regularAttributes) { x[a++] = currentExample.getValue(attribute); } supportVectors.add(new SupportVector(x, ys[index], currentAlpha)); } index++; } // calculate all sum values double[] sum = new double[exampleSet.size()]; reader = exampleSet.iterator(); index = 0; // double maxNeg = Double.NEGATIVE_INFINITY; // double minPos = Double.POSITIVE_INFINITY; while (reader.hasNext()) { Example current = reader.next(); double[] x = new double[regularAttributes.length]; int a = 0; for (Attribute attribute : regularAttributes) { x[a++] = current.getValue(attribute); } sum[index] = kernel.getSum(supportVectors, x); // if ((ys[index] < 0) && (sum[index] > maxNeg)) // maxNeg = sum[index]; // if ((ys[index] > 0) && (sum[index] < minPos)) // minPos = sum[index]; index++; } // return new EvoSVMModel(exampleSet.getLabel(), supportVectors, kernel, // (double)(-maxNeg - minPos) / 2.0d); // calculate b (from Stefan's mySVM code) double bSum = 0.0d; int bCounter = 0; for (int i = 0; i < alphas.length; i++) { if ((ys[i] * alphas[i] - c < -IS_ZERO) && (ys[i] * alphas[i] > IS_ZERO)) { bSum += ys[i] - sum[i] - epsilon; bCounter++; } else if ((ys[i] * alphas[i] + c > IS_ZERO) && (ys[i] * alphas[i] < -IS_ZERO)) { bSum += ys[i] - sum[i] - epsilon; bCounter++; } } if (bCounter == 0) { // unlikely bSum = 0.0d; for (int i = 0; i < alphas.length; i++) { if ((ys[i] * alphas[i] < IS_ZERO) && (ys[i] * alphas[i] > -IS_ZERO)) { bSum += ys[i] - sum[i]; bCounter++; } } if (bCounter == 0) { // even unlikelier bSum = 0.0d; for (int i = 0; i < alphas.length; i++) { bSum += ys[i] - sum[i]; bCounter++; } } } return new EvoSVMModel(exampleSet, supportVectors, kernel, (bSum / bCounter)); } }