| 1 | /* |
|---|
| 2 | * This program is free software; you can redistribute it and/or modify |
|---|
| 3 | * it under the terms of the GNU General Public License as published by |
|---|
| 4 | * the Free Software Foundation; either version 2 of the License, or |
|---|
| 5 | * (at your option) any later version. |
|---|
| 6 | * |
|---|
| 7 | * This program is distributed in the hope that it will be useful, |
|---|
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 10 | * GNU General Public License for more details. |
|---|
| 11 | * |
|---|
| 12 | * You should have received a copy of the GNU General Public License |
|---|
| 13 | * along with this program; if not, write to the Free Software |
|---|
| 14 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 15 | */ |
|---|
| 16 | |
|---|
| 17 | /* |
|---|
| 18 | * MIRBFKernel.java |
|---|
| 19 | * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand |
|---|
| 20 | * |
|---|
| 21 | */ |
|---|
| 22 | |
|---|
| 23 | package weka.classifiers.mi.supportVector; |
|---|
| 24 | |
|---|
| 25 | import weka.classifiers.functions.supportVector.RBFKernel; |
|---|
| 26 | import weka.core.Capabilities; |
|---|
| 27 | import weka.core.Instance; |
|---|
| 28 | import weka.core.Instances; |
|---|
| 29 | import weka.core.MultiInstanceCapabilitiesHandler; |
|---|
| 30 | import weka.core.RevisionUtils; |
|---|
| 31 | import weka.core.Capabilities.Capability; |
|---|
| 32 | |
|---|
| 33 | /** |
|---|
| 34 | <!-- globalinfo-start --> |
|---|
| 35 | * The RBF kernel. K(x, y) = e^-(gamma * <x-y, x-y>^2) |
|---|
| 36 | * <p/> |
|---|
| 37 | <!-- globalinfo-end --> |
|---|
| 38 | * |
|---|
| 39 | <!-- options-start --> |
|---|
| 40 | * Valid options are: <p/> |
|---|
| 41 | * |
|---|
| 42 | * <pre> -D |
|---|
| 43 | * Enables debugging output (if available) to be printed. |
|---|
| 44 | * (default: off)</pre> |
|---|
| 45 | * |
|---|
| 46 | * <pre> -no-checks |
|---|
| 47 | * Turns off all checks - use with caution! |
|---|
| 48 | * (default: checks on)</pre> |
|---|
| 49 | * |
|---|
| 50 | * <pre> -C <num> |
|---|
| 51 | * The size of the cache (a prime number), 0 for full cache and |
|---|
| 52 | * -1 to turn it off. |
|---|
| 53 | * (default: 250007)</pre> |
|---|
| 54 | * |
|---|
| 55 | * <pre> -G <num> |
|---|
| 56 | * The Gamma parameter. |
|---|
| 57 | * (default: 0.01)</pre> |
|---|
| 58 | * |
|---|
| 59 | <!-- options-end --> |
|---|
| 60 | * |
|---|
| 61 | * @author Eibe Frank (eibe@cs.waikato.ac.nz) |
|---|
| 62 | * @author Shane Legg (shane@intelligenesis.net) (sparse vector code) |
|---|
| 63 | * @author Stuart Inglis (stuart@reeltwo.com) (sparse vector code) |
|---|
| 64 | * @author J. Lindgren (jtlindgr{at}cs.helsinki.fi) (RBF kernel) |
|---|
| 65 | * @author Lin Dong (ld21@cs.waikato.ac.nz) (MIkernel) |
|---|
| 66 | * @version $Revision: 1.4 $ |
|---|
| 67 | */ |
|---|
| 68 | public class MIRBFKernel |
|---|
| 69 | extends RBFKernel |
|---|
| 70 | implements MultiInstanceCapabilitiesHandler { |
|---|
| 71 | |
|---|
| 72 | /** for serialiation */ |
|---|
| 73 | private static final long serialVersionUID = -8711882393708956962L; |
|---|
| 74 | |
|---|
| 75 | /** The precalculated dotproducts of <inst_i,inst_i> */ |
|---|
| 76 | protected double m_kernelPrecalc[][]; |
|---|
| 77 | |
|---|
| 78 | /** |
|---|
| 79 | * default constructor - does nothing. |
|---|
| 80 | */ |
|---|
| 81 | public MIRBFKernel() { |
|---|
| 82 | super(); |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | /** |
|---|
| 86 | * Constructor. |
|---|
| 87 | * |
|---|
| 88 | * @param data the data to use |
|---|
| 89 | * @param cacheSize the size of the cache |
|---|
| 90 | * @param gamma the bandwidth |
|---|
| 91 | * @throws Exception if something goes wrong |
|---|
| 92 | */ |
|---|
| 93 | public MIRBFKernel(Instances data, int cacheSize, double gamma) |
|---|
| 94 | throws Exception { |
|---|
| 95 | |
|---|
| 96 | super(data, cacheSize, gamma); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | /** |
|---|
| 100 | * |
|---|
| 101 | * @param id1 the index of instance 1 |
|---|
| 102 | * @param id2 the index of instance 2 |
|---|
| 103 | * @param inst1 the instance 1 object |
|---|
| 104 | * @return the dot product |
|---|
| 105 | * @throws Exception if something goes wrong |
|---|
| 106 | */ |
|---|
| 107 | protected double evaluate(int id1, int id2, Instance inst1) |
|---|
| 108 | throws Exception { |
|---|
| 109 | |
|---|
| 110 | double result = 0; |
|---|
| 111 | Instances insts1, insts2; |
|---|
| 112 | if (id1 == -1) |
|---|
| 113 | insts1 = new Instances(inst1.relationalValue(1)); |
|---|
| 114 | else |
|---|
| 115 | insts1 = new Instances(m_data.instance(id1).relationalValue(1)); |
|---|
| 116 | insts2 = new Instances (m_data.instance(id2).relationalValue(1)); |
|---|
| 117 | |
|---|
| 118 | double precalc1=0; |
|---|
| 119 | for(int i = 0; i < insts1.numInstances(); i++){ |
|---|
| 120 | for (int j = 0; j < insts2.numInstances(); j++){ |
|---|
| 121 | if (id1 == -1) |
|---|
| 122 | precalc1 = dotProd(insts1.instance(i), insts1.instance(i)); |
|---|
| 123 | else |
|---|
| 124 | precalc1 = m_kernelPrecalc[id1][i]; |
|---|
| 125 | |
|---|
| 126 | double res = Math.exp(m_gamma*(2. * dotProd(insts1.instance(i), insts2.instance(j)) -precalc1 - m_kernelPrecalc[id2][j] ) ); |
|---|
| 127 | |
|---|
| 128 | result += res; |
|---|
| 129 | } |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | return result; |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | /** |
|---|
| 136 | * initializes variables etc. |
|---|
| 137 | * |
|---|
| 138 | * @param data the data to use |
|---|
| 139 | */ |
|---|
| 140 | protected void initVars(Instances data) { |
|---|
| 141 | super.initVars(data); |
|---|
| 142 | |
|---|
| 143 | m_kernelPrecalc = new double[data.numInstances()][]; |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | /** |
|---|
| 147 | * Returns the Capabilities of this kernel. |
|---|
| 148 | * |
|---|
| 149 | * @return the capabilities of this object |
|---|
| 150 | * @see Capabilities |
|---|
| 151 | */ |
|---|
| 152 | public Capabilities getCapabilities() { |
|---|
| 153 | Capabilities result = super.getCapabilities(); |
|---|
| 154 | |
|---|
| 155 | // attributes |
|---|
| 156 | result.enable(Capability.NOMINAL_ATTRIBUTES); |
|---|
| 157 | result.enable(Capability.RELATIONAL_ATTRIBUTES); |
|---|
| 158 | result.enable(Capability.MISSING_VALUES); |
|---|
| 159 | |
|---|
| 160 | // class |
|---|
| 161 | result.enableAllClasses(); |
|---|
| 162 | |
|---|
| 163 | // other |
|---|
| 164 | result.enable(Capability.ONLY_MULTIINSTANCE); |
|---|
| 165 | |
|---|
| 166 | return result; |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | /** |
|---|
| 170 | * Returns the capabilities of this multi-instance kernel for the |
|---|
| 171 | * relational data. |
|---|
| 172 | * |
|---|
| 173 | * @return the capabilities of this object |
|---|
| 174 | * @see Capabilities |
|---|
| 175 | */ |
|---|
| 176 | public Capabilities getMultiInstanceCapabilities() { |
|---|
| 177 | Capabilities result = super.getCapabilities(); |
|---|
| 178 | |
|---|
| 179 | // class |
|---|
| 180 | result.disableAllClasses(); |
|---|
| 181 | result.enable(Capability.NO_CLASS); |
|---|
| 182 | |
|---|
| 183 | return result; |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | /** |
|---|
| 187 | * builds the kernel with the given data. Initializes the kernel cache. |
|---|
| 188 | * The actual size of the cache in bytes is (64 * cacheSize). |
|---|
| 189 | * |
|---|
| 190 | * @param data the data to base the kernel on |
|---|
| 191 | * @throws Exception if something goes wrong |
|---|
| 192 | */ |
|---|
| 193 | public void buildKernel(Instances data) throws Exception { |
|---|
| 194 | // does kernel handle the data? |
|---|
| 195 | if (!getChecksTurnedOff()) |
|---|
| 196 | getCapabilities().testWithFail(data); |
|---|
| 197 | |
|---|
| 198 | initVars(data); |
|---|
| 199 | |
|---|
| 200 | for (int i = 0; i < data.numInstances(); i++){ |
|---|
| 201 | Instances insts = new Instances(data.instance(i).relationalValue(1)); |
|---|
| 202 | m_kernelPrecalc[i] = new double [insts.numInstances()]; |
|---|
| 203 | for (int j = 0; j < insts.numInstances(); j++) |
|---|
| 204 | m_kernelPrecalc[i][j] = dotProd(insts.instance(j), insts.instance(j)); |
|---|
| 205 | } |
|---|
| 206 | } |
|---|
| 207 | |
|---|
| 208 | /** |
|---|
| 209 | * Returns the revision string. |
|---|
| 210 | * |
|---|
| 211 | * @return the revision |
|---|
| 212 | */ |
|---|
| 213 | public String getRevision() { |
|---|
| 214 | return RevisionUtils.extract("$Revision: 1.4 $"); |
|---|
| 215 | } |
|---|
| 216 | } |
|---|
| 217 | |
|---|