/*
* RapidMiner
*
* Copyright (C) 2001-2014 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* 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 http://www.gnu.org/licenses/.
*/
package com.rapidminer.operator.learner.functions.kernel.gaussianprocess;
import java.io.Serializable;
import com.rapidminer.operator.learner.functions.kernel.rvm.kernel.Kernel;
import Jama.Matrix;
/**
* The learned model.
*
* @author Piotr Kasprzak, Ingo Mierswa
*
*/
public class Model implements Serializable {
private static final long serialVersionUID = 1695426983570182267L;
/* Kernel used */
private Kernel kernel;
/* The basis vectors used */
private double[][] basisVectors;
/* Parameterisation of the approximate GP */
//private Matrix C; // GP-covariance parameterisation
private Matrix alpha; // GP-mean parameterisation
//private Matrix Q; // Inverse kernel gram matrix, could be useful later
private boolean regression; // Regression or classification model
/**
* Other variables (can be derived from the variables above)
*/
/*
* The vector k_t+1 = [K(x_1, x_t+1), K(x_2, x_t+1), ..., K(x_t, x_t+1)], holding the results of using the kernel on
* the the new input x_t+1 and the rest of the old inputs
*/
private Matrix k;
/* Temorary result: C_t * k_t+1 */
// IM: WARNING: the variable was never used !!!
// private Matrix C_times_k;
private int d; // Number of basis vectors (= dimension of all vectors / matrices)
private int inputDim; // Dimension of the input vectors
/** Constructors */
public Model(Kernel kernel, double[][] basisVectors, Matrix alpha, Matrix C, Matrix Q, int d, boolean regression) {
this.kernel = kernel;
this.basisVectors = basisVectors;
this.alpha = alpha;
//this.C = C;
//this.Q = Q;
this.regression = regression;
this.d = d;
inputDim = basisVectors[0].length; // Dimension of the input vectors
k = new Matrix(d, 1);
/* Temorary result: C_t * k_t+1 */
// IM: WARNING: the variable was never used !!!
// C_times_k = new Matrix(d, 1);
}
public int getNumberOfBasisVectors() {
return basisVectors.length;
}
public int getInputDim() {
return inputDim;
}
public double[] getBasisVector(int i) {
return this.basisVectors[i];
}
public double getBasisVectorValue(int i, int j) {
return this.basisVectors[i][j];
}
/**
* Compute the (canonical) scalar product between x and y, using only the first d components of the vectors
*/
private double scalarProduct(double[][] x, double[][] y, int d) {
/* Lengths of x and y must be both >= d */
//if (x.length < d || y.length < d)
//throw new Exception("At least one vector has a too small dimension!");
double result = 0;
for (int i = 0; i < d; i++) {
result += x[i][0] * y[i][0];
}
return result;
}
/**
* Apply the model to a (new) input vector x_t+1 in order to get a prediction, which - as a GP-marignal at x_t+1 -
* is a one-dimensional gaussian distribution with mean m and covariance sigma^2 (2.22, the parameterisation lemma).
* Returns only the function value, the mapping to a classification must be done by the invoking method.
*/
public double applyToVector(double[] x_new) {
double m = 0; // The mean of the marginalisation, we want to compute
// IM: Warning: the following variable was never used !!!
// double sigma_2 = 0; // The according covariance
double prediction = 0; // The prediction we return (will be =mean)
// IM: WARNING: the variable k_star was never used !!!
// double k_star = 0; // = Kernel(x_new, x_new)
/**
* Compute k_t+1 = [K(x_1, x_t+1), K(x_2, x_t+1), ..., K(x_t, x_t+1)] and
*
* k_star = K(x_t+1, x_t+1)
*/
for (int j = 0; j < d; j++) {
k.getArray()[j][0] = kernel.eval(basisVectors[j], x_new);
}
// IM: WARNING: the variable k_star was never used !!!
// k_star = kernel.eval(x_new, x_new);
/**
* Compute m_t+1, the mean of the marginal of the GP at x_t+1, which is gaussian:
*
* m_t+1 = {k_t+1}^T * alpha_t
*
*/
m = scalarProduct(k.getArray(), alpha.getArray(), d);
/**
* Compute sigma_t+1^2, the covariance^2 of the marginal of the GP at x_t+1, which is gaussian:
*
* {sigma_t+1}^2 = K(x_t+1, x_t+1) + {k_t+1}^T * C_t * k_t+1
*
* (see end of chapter 2.4 and chapter 5.1)
*/
// IM: WARNING: the variable was never used !!!
// C_times_k = C.times(k);
// IM: WARNING: the following variable was never used !!!
// sigma_2 = k_star + scalarProduct(k.getArray(), C_times_k.getArray(), d);
prediction = m;
/* IM: should be done by invoking method
if (!regression) {
if (prediction > 0.0)
prediction = 1.0;
else
prediction = 0.0;
}
*/
return prediction;
}
/**
* Apply the model to all input vectors
*/
public double[] apply(double[][] inputVectors) throws Exception {
double[] prediction = new double[inputVectors.length];
for (int i = 0; i < inputVectors.length; i++) {
prediction[i] = applyToVector(inputVectors[i]);
if (!regression) {
if (prediction[i] > 0.0)
prediction[i] = 1.0;
else
prediction[i] = 0.0;
}
}
return prediction;
}
}