/***********************************************************************
This file is part of KEEL-software, the Data Mining tool for regression,
classification, clustering, pattern mining and so on.
Copyright (C) 2004-2010
F. Herrera (herrera@decsai.ugr.es)
L. S�nchez (luciano@uniovi.es)
J. Alcal�-Fdez (jalcala@decsai.ugr.es)
S. Garc�a (sglopez@ujaen.es)
A. Fern�ndez (alberto.fernandez@ujaen.es)
J. Luengo (julianlm@decsai.ugr.es)
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 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
**********************************************************************/
package keel.Algorithms.SVM.SMO.supportVector;
/**
* Positive-Definite Reference Function Kernel
* To be used with PDFS algorithm
* @author Julian Luengo Martin
*
*/
import keel.Algorithms.SVM.SMO.core.Instance;
import keel.Algorithms.SVM.SMO.core.Instances;
import keel.Algorithms.SVM.SMO.core.Option;
import keel.Algorithms.SVM.SMO.core.Utils;
import java.util.Enumeration;
import java.util.Vector;
public class PDRFKernel
extends CachedKernel {
/** Type of Positive Definite Functions supported **/
public static int SymmetricTriangle = 1;
public static int Gaussian = 2;
public static int Cauchy = 3;
public static int Laplace = 4;
public static int HyperbolicSecant = 5;
public static int SquaredSinc = 6;
/** for serialization */
static final long serialVersionUID = 7672176272736783265L;
/** The precalculated dotproducts of <inst_i,inst_i> */
protected double m_kernelPrecalc[];
/** The d value for the PDRF kernel. */
protected double m_d = 0.01;
/** The type of function used by this kernel **/
protected int m_type = PDRFKernel.SymmetricTriangle;
/**
* default constructor - does nothing.
*/
public PDRFKernel() {
super();
}
/**
* Constructor. Initializes m_kernelPrecalc[].
*
* @param data the data to use
* @param cacheSize the size of the cache
* @param gamma the bandwidth
* @throws Exception if something goes wrong
*/
public PDRFKernel(Instances data, int cacheSize, double gamma)
throws Exception {
super();
setCacheSize(cacheSize);
setD(gamma);
buildKernel(data);
}
/**
* Returns a string describing the kernel
*
* @return a description suitable for displaying in the
* explorer/experimenter gui
*/
public String globalInfo() {
return
"The PRDF kernel. K(x, y) = K(u) = Productory_{k=1}^n a^k(u_k)";
}
/**
* Returns an enumeration describing the available options.
*
* @return an enumeration of all the available options.
*/
public Enumeration listOptions() {
Vector result;
Enumeration en;
result = new Vector();
en = super.listOptions();
while (en.hasMoreElements())
result.addElement(en.nextElement());
result.addElement(new Option(
"\tThe d parameter.\n"
+ "\t(default: 1)",
"D", 1, "-D <num>"));
return result.elements();
}
/**
* Parses a given list of options. <p/>
*
<!-- options-start -->
* Valid options are: <p/>
*
* <pre> -D
* Enables debugging output (if available) to be printed.
* (default: off)</pre>
*
* <pre> -no-checks
* Turns off all checks - use with caution!
* (default: checks on)</pre>
*
* <pre> -C <num>
* The size of the cache (a prime number).
* (default: 250007)</pre>
*
* <pre> -G <num>
* The Gamma parameter.
* (default: 0.01)</pre>
*
<!-- options-end -->
*
* @param options the list of options as an array of strings
* @throws Exception if an option is not supported
*/
public void setOptions(String[] options) throws Exception {
String tmpStr;
tmpStr = Utils.getOption('D', options);
if (tmpStr.length() != 0)
setD(Double.parseDouble(tmpStr));
else
setD(0.01);
super.setOptions(options);
}
/**
* Gets the current settings of the Kernel.
*
* @return an array of strings suitable for passing to setOptions
*/
public String[] getOptions() {
int i;
Vector result;
String[] options;
result = new Vector();
options = super.getOptions();
for (i = 0; i < options.length; i++)
result.add(options[i]);
result.add("-D");
result.add("" + getD());
return (String[]) result.toArray(new String[result.size()]);
}
/**
*
* @param id1 the index of instance 1
* @param id2 the index of instance 2
* @param inst1 the instance 1 object
* @return the dot product
* @throws Exception if something goes wrong
*/
protected double evaluate(int id1, int id2, Instance inst1)
throws Exception {
double u[];
if (id1 == id2) {
//for the squared sinc this is not true! but since
//the result would be 0/0, let it be 1.
return 1.0;
} else {
Instance inst2 = m_data.instance(id2);
u = new double[inst2.numAttributes()-1];
double precalc1;
if (id1 == -1){
for(int i=0,j=0;i<inst1.numAttributes();i++){
if(i!=inst1.classIndex()){
u[j] = inst1.value(i) - inst2.value(i);
j++;
}
}
}
else{
for(int i=0,j=0;i<inst1.numAttributes();i++){
if(i!=inst1.classIndex()){
u[j] = m_data.instance(id1).value(i) - inst2.value(i);
j++;
}
}
}
double result = evaluatePRDF(u);
return result;
}
}
/**
* Sets the gamma value.
*
* @param value the gamma value
*/
public void setD(double value) {
m_d = value;
}
/**
* Gets the gamma value.
*
* @return the gamma value
*/
public double getD() {
return m_d;
}
public void setPDRFType(int type){
m_type = type;
}
/**
* Returns the tip text for this property
*
* @return tip text for this property suitable for
* displaying in the explorer/experimenter gui
*/
public String dTipText() {
return "The d value.";
}
/**
* initializes variables etc.
*
* @param data the data to use
*/
protected void initVars(Instances data) {
super.initVars(data);
m_kernelPrecalc = new double[data.numInstances()];
}
/**
* Returns the Capabilities of this kernel.
*
* @return the capabilities of this object
* @see Capabilities
*/
// public Capabilities getCapabilities() {
// Capabilities result = super.getCapabilities();
//
// result.enable(Capability.NUMERIC_ATTRIBUTES);
// result.enableAllClasses();
//
// return result;
// }
/**
* builds the kernel with the given data. Initializes the kernel cache.
* The actual size of the cache in bytes is (64 * cacheSize).
*
* @param data the data to base the kernel on
* @throws Exception if something goes wrong
*/
// public void buildKernel(Instances data) throws Exception {
// does kernel handle the data?
// if (!getChecksTurnedOff())
// getCapabilities().testWithFail(data);
// initVars(data);
//
// for (int i = 0; i < data.numInstances(); i++)
// m_kernelPrecalc[i] = dotProd(data.instance(i), data.instance(i));
// }
/**
* returns a string representation for the Kernel
*
* @return a string representation of the kernel
*/
public String toString() {
return "PRDF kernel: K(x,y) = Productory_{k=1}^n a^k (x-y)_k";
}
/**
* Evaluates a vector of doubles (an instance) with the
* Positive Definite Functions associated
* @param u The instance to be evaluated
* @return The result of evaluate the instance with the PDRF
*/
public double evaluatePRDF(double u[]){
double prod = 1;
for(int i=0;i<u.length;i++){
if(m_type == SymmetricTriangle)
prod *= symmetricTriangle(u[i]);
else if(m_type == Gaussian)
prod *= gaussian(u[i]);
else if(m_type == Cauchy)
prod *= cauchy(u[i]);
else if(m_type == Laplace)
prod *= laplace(u[i]);
else if(m_type == HyperbolicSecant)
prod *= hyperbolicSecant(u[i]);
else if(m_type == SquaredSinc)
prod *= squaredSinc(u[i]);
}
return prod;
}
/**
* Computes the result of the Symmetric Triangle PDRF
* @param x The input of this function (x-z)
* @return The result obtained
*/
public double symmetricTriangle(double x){
return Math.max(0, 1 - m_d*Math.abs(x));
}
/**
* Computes the result of the Gaussian PDRF
* @param x The input of this function (x-z)
* @return The result obtained
*/
public double gaussian(double x){
return Math.exp(-m_d * Math.pow(x, 2));
}
/**
* Computes the result of the Cauchy PDRF
* @param x The input of this function (x-z)
* @return The result obtained
*/
public double cauchy(double x){
return (1.0 / (1.0+ m_d * Math.pow(x,2)));
}
/**
* Computes the result of the Laplace PDRF
* @param x The input of this function (x-z)
* @return The result obtained
*/
public double laplace(double x){
return Math.exp(-m_d * Math.abs(x));
}
/**
* Computes the result of the Hyperbolic Secant PDRF
* @param x The input of this function (x-z)
* @return The result obtained
*/
public double hyperbolicSecant(double x){
return ((2.0)/(Math.exp(m_d * x) + Math.exp(-m_d * x)));
}
/**
* Computes the result of the Squared Sinc PDRF
* @param x The input of this function (x-z)
* @return The result obtained
*/
public double squaredSinc(double x){
return ((Math.pow(Math.sin(m_d * x), 2)) / (Math.pow(m_d, 2)) * Math.pow(x,2));
}
}