/* * 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; import java.util.Iterator; import java.util.List; import com.rapidminer.example.Attribute; import com.rapidminer.example.Example; import com.rapidminer.example.ExampleSet; import com.rapidminer.operator.Model; import com.rapidminer.operator.OperatorDescription; import com.rapidminer.operator.OperatorException; import com.rapidminer.operator.UserError; import com.rapidminer.operator.learner.AbstractLearner; import com.rapidminer.operator.learner.LearnerCapability; import com.rapidminer.operator.learner.functions.kernel.gaussianprocess.Parameter; import com.rapidminer.operator.learner.functions.kernel.gaussianprocess.Regression; import com.rapidminer.operator.learner.functions.kernel.gaussianprocess.RegressionProblem; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.Kernel; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelCauchy; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelEpanechnikov; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelGaussianCombination; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelLaplace; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelMultiquadric; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelPoly; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelRadial; import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.KernelSigmoid; import com.rapidminer.parameter.ParameterType; import com.rapidminer.parameter.ParameterTypeCategory; import com.rapidminer.parameter.ParameterTypeDouble; import com.rapidminer.parameter.ParameterTypeInt; /** * Gaussian Process (GP) Learner. The GP is a probabilistic method * both for classification and regression. * * @author Piotr Kasprzak, Ingo Mierswa * @version $Id: GPLearner.java,v 1.8 2008/05/09 19:23:01 ingomierswa Exp $ * @rapidminer.index GP */ public class GPLearner extends AbstractLearner { /** The parameter name for "Regression" */ public static final String PARAMETER_GP_TYPE = "gp_type"; /** The parameter name for "The kind of kernel." */ public static final String PARAMETER_KERNEL_TYPE = "kernel_type"; /** The parameter name for "The lengthscale r for rbf kernel functions (exp{-1.0 * r^-2 * ||x - bla||})." */ public static final String PARAMETER_KERNEL_LENGTHSCALE = "kernel_lengthscale"; /** The parameter name for "The degree used in the poly kernel." */ public static final String PARAMETER_KERNEL_DEGREE = "kernel_degree"; /** The parameter name for "The bias used in the poly kernel." */ public static final String PARAMETER_KERNEL_BIAS = "kernel_bias"; /** The parameter name for "The SVM kernel parameter sigma1 (Epanechnikov, Gaussian Combination, Multiquadric)." */ public static final String PARAMETER_KERNEL_SIGMA1 = "kernel_sigma1"; /** The parameter name for "The SVM kernel parameter sigma2 (Gaussian Combination)." */ public static final String PARAMETER_KERNEL_SIGMA2 = "kernel_sigma2"; /** The parameter name for "The SVM kernel parameter sigma3 (Gaussian Combination)." */ public static final String PARAMETER_KERNEL_SIGMA3 = "kernel_sigma3"; /** The parameter name for "The SVM kernel parameter shift (polynomial, Multiquadric)." */ public static final String PARAMETER_KERNEL_SHIFT = "kernel_shift"; /** The parameter name for "The SVM kernel parameter a (neural)." */ public static final String PARAMETER_KERNEL_A = "kernel_a"; /** The parameter name for "The SVM kernel parameter b (neural)." */ public static final String PARAMETER_KERNEL_B = "kernel_b"; /** The parameter name for "Maximum number of basis vectors to be used." */ public static final String PARAMETER_MAX_BASIS_VECTORS = "max_basis_vectors"; /** The parameter name for "Tolerance for gamma induced projections" */ public static final String PARAMETER_EPSILON_TOL = "epsilon_tol"; /** The parameter name for "Tolerance for geometry induced projections" */ public static final String PARAMETER_GEOMETRICAL_TOL = "geometrical_tol"; //public static final String[] GP_TYPES = { "Regression", "Classification" }; public static final String[] KERNEL_TYPES = { "rbf", "cauchy", "laplace", "poly", "sigmoid", "Epanechnikov", "gaussian combination", "multiquadric" }; public GPLearner(OperatorDescription description) { super(description); } public boolean supportsCapability(LearnerCapability lc) { if (lc == com.rapidminer.operator.learner.LearnerCapability.NUMERICAL_ATTRIBUTES) return true; if (lc == com.rapidminer.operator.learner.LearnerCapability.BINOMINAL_CLASS) return true; if (lc == com.rapidminer.operator.learner.LearnerCapability.NUMERICAL_CLASS) return true; return false; } public Model learn(ExampleSet exampleSet) throws OperatorException { log("Creating GP-Learner."); Parameter parameter = new Parameter(); int numExamples = exampleSet.size(); /** Get user defined control parameters from RapidMiner */ /* Maximum number of basis vectors to be used */ parameter.maxBasisVectors = getParameterAsInt(PARAMETER_MAX_BASIS_VECTORS); /* Tolerance value: we project the current basis vector if it has * a orthogonal distance to the linear span of the other * basis vectors smaller than epsilon_tol */ parameter.epsilon_tol = getParameterAsDouble(PARAMETER_EPSILON_TOL); parameter.geometrical_tol = getParameterAsDouble(PARAMETER_GEOMETRICAL_TOL); /** Transfer input / target vectors into array form */ log("Creating input / output vectors."); double[][] x = new double[numExamples][exampleSet.getAttributes().size()]; double[][] t = new double[numExamples][1]; Iterator<Example> reader = exampleSet.iterator(); int k = 0; while (reader.hasNext()) { double[] targetVector = new double[1]; Example e = reader.next(); targetVector[0] = e.getLabel(); x[k] = RVMModel.makeInputVector(e); t[k] = targetVector; k++; } /** Init hyperparameters with more or less sensible values (shouldn't be too important) */ Attribute label = exampleSet.getAttributes().getLabel(); // double variance = label.getVariance(); /** Create kernel */ log("Creating kernel."); Kernel kernel = createKernel(); /** Create GP-Learner and learn the model */ //String GPType = GP_TYPES[getParameterAsInt(PARAMETER_GP_TYPE)]; com.rapidminer.operator.learner.functions.kernel.gaussianprocess.Model model = null; if (label.isNominal()) { throw new UserError(this, 102, getName(), label.getName()); /** Classification problem */ /* int[] c = new int[numExamples]; for (k = 0; k < numExamples; k++) { c[k] = (new Double(t[k][0])).intValue(); } */ // ClassificationProblem problem = new ClassificationProblem(x, c, kernels); // // if (RVMType.equals("Classification-RVM")) { // RVMClassification RVM = new RVMClassification(problem, parameter); // model = RVM.learn(); // } else { // throw new UserError(); // } } else { /** Regression problem */ RegressionProblem problem = new RegressionProblem(x, t, kernel); //if (GPType.equals("Regression")) { Regression GP = new Regression(problem, parameter); try { model = GP.learn(); } catch (Exception e) { throw new OperatorException(e.getMessage()); } //} } return new GPModel(exampleSet, model); } /** * Create the appropriate kernel function depending on the RapidMiner - ui settings. */ public Kernel createKernel() throws OperatorException { Kernel kernel = null; double lengthScale = getParameterAsDouble(PARAMETER_KERNEL_LENGTHSCALE); double bias = getParameterAsDouble(PARAMETER_KERNEL_BIAS); double degree = getParameterAsDouble(PARAMETER_KERNEL_DEGREE); double a = getParameterAsDouble(PARAMETER_KERNEL_A); double b = getParameterAsDouble(PARAMETER_KERNEL_B); double sigma1 = getParameterAsDouble(PARAMETER_KERNEL_SIGMA1); double sigma2 = getParameterAsDouble(PARAMETER_KERNEL_SIGMA2); double sigma3 = getParameterAsDouble(PARAMETER_KERNEL_SIGMA3); double shift = getParameterAsDouble(PARAMETER_KERNEL_SHIFT); switch (getParameterAsInt(PARAMETER_KERNEL_TYPE)) { case 0: kernel = new KernelRadial(lengthScale); break; case 1: kernel = new KernelCauchy(lengthScale); break; case 2: kernel = new KernelLaplace(lengthScale); break; case 3: kernel = new KernelPoly(lengthScale, bias, degree); break; case 4: kernel = new KernelSigmoid(a, b); break; case 5: kernel = new KernelEpanechnikov(sigma1, degree); break; case 6: kernel = new KernelGaussianCombination(sigma1, sigma2, sigma3); break; case 7: kernel = new KernelMultiquadric(sigma1, shift); break; default: kernel = new KernelRadial(lengthScale); } return kernel; } public List<ParameterType> getParameterTypes() { List<ParameterType> types = super.getParameterTypes(); ParameterType type; //type = new ParameterTypeCategory(PARAMETER_GP_TYPE, "Regression", GP_TYPES, 0); //type.setExpert(false); //types.add(type); type = new ParameterTypeCategory(PARAMETER_KERNEL_TYPE, "The kind of kernel.", KERNEL_TYPES, 0); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_LENGTHSCALE, "The lengthscale r for rbf kernel functions (exp{-1.0 * r^-2 * ||x - bla||}).", 0, Double.POSITIVE_INFINITY, 3.0); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_DEGREE, "The degree used in the poly kernel.", 0.0d, Double.POSITIVE_INFINITY, 2.0d); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_BIAS, "The bias used in the poly kernel.", 0, Double.POSITIVE_INFINITY, 1.0); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_SIGMA1, "The SVM kernel parameter sigma1 (Epanechnikov, Gaussian Combination, Multiquadric).", 0.0d, Double.POSITIVE_INFINITY, 1.0d); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_SIGMA2, "The SVM kernel parameter sigma2 (Gaussian Combination).", 0.0d, Double.POSITIVE_INFINITY, 0.0d); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_SIGMA3, "The SVM kernel parameter sigma3 (Gaussian Combination).", 0.0d, Double.POSITIVE_INFINITY, 2.0d); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_SHIFT, "The SVM kernel parameter shift (polynomial, Multiquadric).", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0d); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_A, "The SVM kernel parameter a (neural).", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0d); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_KERNEL_B, "The SVM kernel parameter b (neural).", Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0d); type.setExpert(false); types.add(type); type = new ParameterTypeInt(PARAMETER_MAX_BASIS_VECTORS, "Maximum number of basis vectors to be used.", 1, Integer.MAX_VALUE, 100); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_EPSILON_TOL, "Tolerance for gamma induced projections", 0, Double.POSITIVE_INFINITY, 1e-7); type.setExpert(false); types.add(type); type = new ParameterTypeDouble(PARAMETER_GEOMETRICAL_TOL, "Tolerance for geometry induced projections", 0, Double.POSITIVE_INFINITY, 1e-7); type.setExpert(false); types.add(type); return types; } }