tml.vectorspace.factorisation.PrincipalCoordinateAnalysis.java Source code

Java tutorial

Introduction

Here is the source code for tml.vectorspace.factorisation.PrincipalCoordinateAnalysis.java

Source

/*******************************************************************************
 *  Copyright 2007, 2009 Stephen O'Rourke (stephen.orourke@sydney.edu.au)
 *  
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License. 
 *  You may obtain a copy of the License at 
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 *     
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License.
 *******************************************************************************/
package tml.vectorspace.factorisation;

import tml.utils.DistanceLib;
import tml.utils.DistanceLib.DistanceMeasure;
import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;
import Jama.EigenvalueDecomposition;
import Jama.Matrix;

/**
 * Principal Coordinate Analysis
 * 
 * @author Stephen O'Rourke
 */
public class PrincipalCoordinateAnalysis {
    public static final int X = 0; // attribute Y
    public static final int Y = 1; // attribute X
    private static final int p = 2; // number of dimensions
    private DistanceMeasure distanceMeasure = DistanceMeasure.EUCLIDEAN;

    public Instances scale(Instances instances) {
        // number of points
        int n = instances.numInstances();

        // distance matrix
        Matrix d = new Matrix(n, n);
        Matrix G = new Matrix(n, n);

        // points instances
        FastVector attributes = new FastVector(p);
        attributes.addElement(new Attribute("X"));
        attributes.addElement(new Attribute("Y"));
        Instances x = new Instances("PCO", attributes, instances.numInstances());

        // calculate distance matrix
        for (int j = 0; j < n; j++) {
            for (int i = 0; i < j; i++) {
                double distance = this.distance(instances.instance(i), instances.instance(j));
                d.set(i, j, distance);
                d.set(j, i, distance);
            }
        }

        // create centered matrix G by centering the elements of A
        Matrix A = d.arrayTimes(d).times((double) -1 / 2);
        Matrix B = Matrix.identity(n, n).minus(new Matrix(n, n, 1).times((double) 1 / n));
        G = B.times(A).times(B);

        // eigenvalue decomposition
        EigenvalueDecomposition eig = G.eig();
        Matrix eigenvalues = eig.getD();
        Matrix eigenvectors = eig.getV();

        // output eigenvectors as the principal coordinate axes, and normalise 
        // them by dividing by the square root of their corresponding eigenvalue.
        for (int i = 0; i < n; i++) {
            Instance instance = new Instance(p);
            instance.setValue(X, eigenvectors.get(i, X)
                    / Math.copySign(Math.sqrt(Math.abs(eigenvalues.get(X, X))), eigenvalues.get(X, X)));
            instance.setValue(Y, eigenvectors.get(i, Y)
                    / Math.copySign(Math.sqrt(Math.abs(eigenvalues.get(Y, Y))), eigenvalues.get(Y, Y)));
            x.add(instance);
        }

        return x;
    }

    protected double distance(Instance inst1, Instance inst2) {
        double distance = Math.sqrt(1 - DistanceLib.distance(distanceMeasure, inst1, inst2));
        return distance;
    }

    public DistanceMeasure getDistanceMeasure() {
        return distanceMeasure;
    }

    public void setDistanceMeasure(DistanceMeasure distanceMeasure) {
        this.distanceMeasure = distanceMeasure;
    }

}