package de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team 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 . */ import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.database.query.DistanceSimilarityQuery; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceSimilarityQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractNumberVectorDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.distance.similarityfunction.AbstractVectorSimilarityFunction; import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; /** * Polynomial Kernel function that computes a similarity between the two feature * vectors V1 and V2 defined by (V1^T*V2)^degree. * * @author Simon Paradies */ public class PolynomialKernelFunction extends AbstractVectorSimilarityFunction implements PrimitiveDistanceFunction { /** * The default degree. */ public static final int DEFAULT_DEGREE = 2; /** * Degree of the polynomial kernel function. */ private final int degree; /** * Bias of the similarity function. */ private final double bias; /** * Constructor. * * @param degree Kernel degree * @param bias Bias offset */ public PolynomialKernelFunction(int degree, double bias) { super(); this.degree = degree; this.bias = bias; } /** * Constructor. * * @param degree Kernel degree */ public PolynomialKernelFunction(int degree) { this(degree, 0.); } @Override public double similarity(NumberVector o1, NumberVector o2) { final int dim = AbstractNumberVectorDistanceFunction.dimensionality(o1, o2); double sim = 0.; for(int i = 0; i < dim; i++) { sim += o1.doubleValue(i) * o2.doubleValue(i); } return MathUtil.powi(sim + bias, degree); } @Override public boolean isMetric() { return true; } @Override public double distance(NumberVector fv1, NumberVector fv2) { return Math.sqrt(similarity(fv1, fv1) + similarity(fv2, fv2) - 2 * similarity(fv1, fv2)); } @Override public DistanceSimilarityQuery instantiate(Relation database) { return new PrimitiveDistanceSimilarityQuery<>(database, this, this); } /** * Parameterization class. * * @author Erich Schubert * * @apiviz.exclude */ public static class Parameterizer extends AbstractParameterizer { /** * Degree parameter. */ public static final OptionID DEGREE_ID = new OptionID("kernel.polynomial.degree", "The degree of the polynomial kernel function. Default: " + DEFAULT_DEGREE); /** * Bias parameter. */ public static final OptionID BIAS_ID = new OptionID("kernel.polynomial.bias", "The bias of the polynomial kernel, a constant that is added to the scalar product."); /** * Degree of the polynomial kernel function. */ protected int degree = 0; /** * Bias parameter. */ protected double bias = 0.; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); final IntParameter degreeP = new IntParameter(DEGREE_ID, DEFAULT_DEGREE); degreeP.addConstraint(CommonConstraints.GREATER_EQUAL_ONE_INT); if(config.grab(degreeP)) { degree = degreeP.intValue(); } final DoubleParameter biasP = new DoubleParameter(BIAS_ID); biasP.setOptional(true); if(config.grab(biasP)) { bias = biasP.doubleValue(); } } @Override protected PolynomialKernelFunction makeInstance() { if(degree == 1 && (bias == 0.)) { return LinearKernelFunction.STATIC; } return new PolynomialKernelFunction(degree, bias); } } }