/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.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 java.util.ArrayList; import java.util.Iterator; import java.util.List; 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.learner.functions.kernel.SupportVector; import com.rapidminer.operator.learner.functions.kernel.functions.Kernel; import com.rapidminer.operator.performance.EstimatedPerformance; import com.rapidminer.operator.performance.PerformanceVector; import com.rapidminer.tools.RandomGenerator; import com.rapidminer.tools.math.optimization.ec.pso.PSOOptimization; /** * PSO approach for SVM optimization. Currently only classification problems are * supported. * * @author Ingo Mierswa * @version $Id: PSOSVMOptimization.java,v 1.3 2006/04/05 08:57:26 ingomierswa * 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; /** 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) { super(popSize < 1 ? exampleSet.size() : popSize, exampleSet.size(), maxIterations, generationsWithoutImprovement, inertiaWeight, localWeight, globalWeight, 0.0d, 1.0d, dynamicInertiaWeight, random); 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); } } public void nextIteration() { if (showPlot) dataTable.add(new SimpleDataTableRow(new double[] { getGeneration(), getBestFitnessEver(), getBestFitnessInGeneration() })); } /** Evaluates the individuals of the given population. */ 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 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[exampleSet.getAttributes().size()]; int a = 0; for (Attribute attribute : exampleSet.getAttributes()) 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[exampleSet.getAttributes().size()]; int a = 0; for (Attribute attribute : exampleSet.getAttributes()) 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)); } }