001: /*
002: * This program is free software; you can redistribute it and/or modify
003: * it under the terms of the GNU General Public License as published by
004: * the Free Software Foundation; either version 2 of the License, or
005: * (at your option) any later version.
006: *
007: * This program is distributed in the hope that it will be useful,
008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
010: * GNU General Public License for more details.
011: *
012: * You should have received a copy of the GNU General Public License
013: * along with this program; if not, write to the Free Software
014: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
015: */
016:
017: /*
018: * MIRBFKernel.java
019: * Copyright (C) 2005 University of Waikato, Hamilton, New Zealand
020: *
021: */
022:
023: package weka.classifiers.mi.supportVector;
024:
025: import weka.classifiers.functions.supportVector.RBFKernel;
026: import weka.core.Capabilities;
027: import weka.core.Instance;
028: import weka.core.Instances;
029: import weka.core.MultiInstanceCapabilitiesHandler;
030: import weka.core.Capabilities.Capability;
031:
032: /**
033: <!-- globalinfo-start -->
034: * The RBF kernel. K(x, y) = e^-(gamma * <x-y, x-y>^2)
035: * <p/>
036: <!-- globalinfo-end -->
037: *
038: <!-- options-start -->
039: * Valid options are: <p/>
040: *
041: * <pre> -D
042: * Enables debugging output (if available) to be printed.
043: * (default: off)</pre>
044: *
045: * <pre> -no-checks
046: * Turns off all checks - use with caution!
047: * (default: checks on)</pre>
048: *
049: * <pre> -C <num>
050: * The size of the cache (a prime number).
051: * (default: 250007)</pre>
052: *
053: * <pre> -G <num>
054: * The Gamma parameter.
055: * (default: 0.01)</pre>
056: *
057: <!-- options-end -->
058: *
059: * @author Eibe Frank (eibe@cs.waikato.ac.nz)
060: * @author Shane Legg (shane@intelligenesis.net) (sparse vector code)
061: * @author Stuart Inglis (stuart@reeltwo.com) (sparse vector code)
062: * @author J. Lindgren (jtlindgr{at}cs.helsinki.fi) (RBF kernel)
063: * @author Lin Dong (ld21@cs.waikato.ac.nz) (MIkernel)
064: * @version $Revision: 1.2 $
065: */
066: public class MIRBFKernel extends RBFKernel implements
067: MultiInstanceCapabilitiesHandler {
068:
069: /** for serialiation */
070: private static final long serialVersionUID = -8711882393708956962L;
071:
072: /** The precalculated dotproducts of <inst_i,inst_i> */
073: protected double m_kernelPrecalc[][];
074:
075: /**
076: * default constructor - does nothing.
077: */
078: public MIRBFKernel() {
079: super ();
080: }
081:
082: /**
083: * Constructor.
084: *
085: * @param data the data to use
086: * @param cacheSize the size of the cache
087: * @param gamma the bandwidth
088: * @throws Exception if something goes wrong
089: */
090: public MIRBFKernel(Instances data, int cacheSize, double gamma)
091: throws Exception {
092:
093: super (data, cacheSize, gamma);
094: }
095:
096: /**
097: *
098: * @param id1 the index of instance 1
099: * @param id2 the index of instance 2
100: * @param inst1 the instance 1 object
101: * @return the dot product
102: * @throws Exception if something goes wrong
103: */
104: protected double evaluate(int id1, int id2, Instance inst1)
105: throws Exception {
106:
107: double result = 0;
108: Instances insts1, insts2;
109: if (id1 == -1)
110: insts1 = new Instances(inst1.relationalValue(1));
111: else
112: insts1 = new Instances(m_data.instance(id1)
113: .relationalValue(1));
114: insts2 = new Instances(m_data.instance(id2).relationalValue(1));
115:
116: double precalc1 = 0;
117: for (int i = 0; i < insts1.numInstances(); i++) {
118: for (int j = 0; j < insts2.numInstances(); j++) {
119: if (id1 == -1)
120: precalc1 = dotProd(insts1.instance(i), insts1
121: .instance(i));
122: else
123: precalc1 = m_kernelPrecalc[id1][i];
124:
125: double res = Math
126: .exp(m_gamma
127: * (2.
128: * dotProd(insts1.instance(i),
129: insts2.instance(j))
130: - precalc1 - m_kernelPrecalc[id2][j]));
131:
132: result += res;
133: }
134: }
135:
136: return result;
137: }
138:
139: /**
140: * initializes variables etc.
141: *
142: * @param data the data to use
143: */
144: protected void initVars(Instances data) {
145: super .initVars(data);
146:
147: m_kernelPrecalc = new double[data.numInstances()][];
148: }
149:
150: /**
151: * Returns the Capabilities of this kernel.
152: *
153: * @return the capabilities of this object
154: * @see Capabilities
155: */
156: public Capabilities getCapabilities() {
157: Capabilities result = super .getCapabilities();
158:
159: // attributes
160: result.enable(Capability.NOMINAL_ATTRIBUTES);
161: result.enable(Capability.RELATIONAL_ATTRIBUTES);
162: result.enable(Capability.MISSING_VALUES);
163:
164: // class
165: result.enableAllClasses();
166:
167: // other
168: result.enable(Capability.ONLY_MULTIINSTANCE);
169:
170: return result;
171: }
172:
173: /**
174: * Returns the capabilities of this multi-instance kernel for the
175: * relational data.
176: *
177: * @return the capabilities of this object
178: * @see Capabilities
179: */
180: public Capabilities getMultiInstanceCapabilities() {
181: Capabilities result = super .getCapabilities();
182:
183: // class
184: result.disableAllClasses();
185: result.enable(Capability.NO_CLASS);
186:
187: return result;
188: }
189:
190: /**
191: * builds the kernel with the given data. Initializes the kernel cache.
192: * The actual size of the cache in bytes is (64 * cacheSize).
193: *
194: * @param data the data to base the kernel on
195: * @throws Exception if something goes wrong
196: */
197: public void buildKernel(Instances data) throws Exception {
198: // does kernel handle the data?
199: if (!getChecksTurnedOff())
200: getCapabilities().testWithFail(data);
201:
202: initVars(data);
203:
204: for (int i = 0; i < data.numInstances(); i++) {
205: Instances insts = new Instances(data.instance(i)
206: .relationalValue(1));
207: m_kernelPrecalc[i] = new double[insts.numInstances()];
208: for (int j = 0; j < insts.numInstances(); j++)
209: m_kernelPrecalc[i][j] = dotProd(insts.instance(j),
210: insts.instance(j));
211: }
212: }
213: }
|