001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.math.matrix.algorithm.ica; 031 032import org.openimaj.math.matrix.MatrixUtils; 033import org.openimaj.util.pair.IndependentPair; 034 035import Jama.Matrix; 036 037public abstract class IndependentComponentAnalysis { 038 public abstract Matrix getSignalToInterferenceMatrix(); 039 040 public abstract Matrix getDemixingMatrix(); 041 042 public abstract Matrix getIndependentComponentMatrix(); 043 044 /** 045 * Estimate the independent components of the given data array. Each row 046 * corresponds to an observation with the number of dimensions equal to the 047 * number of columns. 048 * 049 * @param data 050 * the data 051 */ 052 public void estimateComponents(double[][] data) { 053 estimateComponents(new Matrix(data)); 054 } 055 056 /** 057 * Estimate the independent components of the given data array. Each row 058 * corresponds to an observation with the number of dimensions equal to the 059 * number of columns. 060 * 061 * @param data 062 * the data 063 */ 064 public void estimateComponents(Matrix data) { 065 final IndependentPair<Matrix, double[]> p = computeMeanCentre(data); 066 final Matrix meanCentredX = p.firstObject(); 067 final double[] mean = p.getSecondObject(); 068 069 final IndependentPair<Matrix, Matrix> p2 = decorrelate(meanCentredX); 070 final Matrix Z = p2.firstObject(); 071 final Matrix CC = p2.secondObject(); 072 estimateComponentsWhitened(Z, mean, meanCentredX, CC); 073 } 074 075 private IndependentPair<Matrix, Matrix> decorrelate(Matrix meanCentredX) { 076 final Matrix C = MatrixUtils.covariance(meanCentredX.transpose()); 077 final Matrix CC = MatrixUtils.invSqrtSym(C); 078 return IndependentPair.pair(CC.times(meanCentredX), CC); 079 } 080 081 private IndependentPair<Matrix, double[]> computeMeanCentre(Matrix m) { 082 final double[][] data = m.getArray(); 083 084 final double[] mean = new double[data.length]; 085 086 for (int j = 0; j < data.length; j++) 087 for (int i = 0; i < data[0].length; i++) 088 mean[j] += data[j][i]; 089 090 for (int i = 0; i < data.length; i++) 091 mean[i] /= data[0].length; 092 093 final Matrix mat = new Matrix(data.length, data[0].length); 094 final double[][] matdat = mat.getArray(); 095 096 for (int j = 0; j < data.length; j++) 097 for (int i = 0; i < data[0].length; i++) 098 matdat[j][i] = (data[j][i] - mean[j]); 099 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}