001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022
023package org.biojava.stats.svm;
024
025/**
026 * This kernel computes the radial base kernel that corresponds to a gausian
027 * distribution. 
028 * <p>
029 * The formula for this is <code>exp( -||a - b|| / (2* width ^ 2))</code>. The
030 * term a-b can be represented in an arbitrary feature space by using a nested
031 * kernel k, and becomes <code>k(a, a) + k(b, b) - 2 * k(a, b)</code>.
032 * <p>
033 * As k(x, x) is required repeatedly, I suggest using a DiagonalCachingKernel as
034 * the immediately nested kernel function.
035 *
036 * @author Matthew Pocock
037 */
038public class RadialBaseKernel extends NestedKernel {
039    private double width;
040
041    public RadialBaseKernel() {
042      this(null, 1.0);
043    }
044
045    public RadialBaseKernel(SVMKernel nested, double width) {
046      super(nested);
047      this.width = width;
048    }
049    
050    public double evaluate(Object a, Object b) {
051      SVMKernel k = getNestedKernel();
052      double w = getWidth();
053      return Math.exp(-Math.abs(2.0 * k.evaluate(a, b) - k.evaluate(a, a) -
054                                k.evaluate(b, b)
055                               ) / ( 2.0 * w * w ));
056    }
057
058    public double getWidth() {
059      return width;
060    }
061
062    public void setWidth(double width) {
063      this.width = width;
064    }
065    
066    public String toString() {
067      return "Radial base kernel K(x, k) = exp(-abs(k(x,x) - k(y,y)) / (2*"
068        + getWidth() + "^2)"
069        + "; k = " + getNestedKernel().toString();
070    }
071}