1 /** 2 * Copyright (c) 2011, The University of Southampton and the individual contributors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * * Neither the name of the University of Southampton nor the names of its 16 * contributors may be used to endorse or promote products derived from this 17 * software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.openimaj.math.matrix.algorithm.ica; 31 32 import org.openimaj.math.matrix.MatrixUtils; 33 import org.openimaj.util.pair.IndependentPair; 34 35 import Jama.Matrix; 36 37 public abstract class IndependentComponentAnalysis { 38 public abstract Matrix getSignalToInterferenceMatrix(); 39 40 public abstract Matrix getDemixingMatrix(); 41 42 public abstract Matrix getIndependentComponentMatrix(); 43 44 /** 45 * Estimate the independent components of the given data array. Each row 46 * corresponds to an observation with the number of dimensions equal to the 47 * number of columns. 48 * 49 * @param data 50 * the data 51 */ 52 public void estimateComponents(double[][] data) { 53 estimateComponents(new Matrix(data)); 54 } 55 56 /** 57 * Estimate the independent components of the given data array. Each row 58 * corresponds to an observation with the number of dimensions equal to the 59 * number of columns. 60 * 61 * @param data 62 * the data 63 */ 64 public void estimateComponents(Matrix data) { 65 final IndependentPair<Matrix, double[]> p = computeMeanCentre(data); 66 final Matrix meanCentredX = p.firstObject(); 67 final double[] mean = p.getSecondObject(); 68 69 final IndependentPair<Matrix, Matrix> p2 = decorrelate(meanCentredX); 70 final Matrix Z = p2.firstObject(); 71 final Matrix CC = p2.secondObject(); 72 estimateComponentsWhitened(Z, mean, meanCentredX, CC); 73 } 74 75 private IndependentPair<Matrix, Matrix> decorrelate(Matrix meanCentredX) { 76 final Matrix C = MatrixUtils.covariance(meanCentredX.transpose()); 77 final Matrix CC = MatrixUtils.invSqrtSym(C); 78 return IndependentPair.pair(CC.times(meanCentredX), CC); 79 } 80 81 private IndependentPair<Matrix, double[]> computeMeanCentre(Matrix m) { 82 final double[][] data = m.getArray(); 83 84 final double[] mean = new double[data.length]; 85 86 for (int j = 0; j < data.length; j++) 87 for (int i = 0; i < data[0].length; i++) 88 mean[j] += data[j][i]; 89 90 for (int i = 0; i < data.length; i++) 91 mean[i] /= data[0].length; 92 93 final Matrix mat = new Matrix(data.length, data[0].length); 94 final double[][] matdat = mat.getArray(); 95 96 for (int j = 0; j < data.length; j++) 97 for (int i = 0; i < data[0].length; i++) 98 matdat[j][i] = (data[j][i] - mean[j]); 99 100 return IndependentPair.pair(mat, mean); 101 } 102 103 /** 104 * Estimate the IC's from the given decorrelated (mean-centred and whitened) 105 * data matrix, Z. 106 * 107 * @param Z 108 * the whitened data; one observation per row 109 * @param mean 110 * the mean of each dimension 111 * @param X 112 * the mean-centered data; one observation per row 113 */ 114 protected abstract void estimateComponentsWhitened(Matrix Z, double[] mean, Matrix X, Matrix CC); 115 }