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.statistics;
031
032import Jama.Matrix;
033
034/**
035 * Class to compute the mean and covariance of some given data.
036 * 
037 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
038 * 
039 */
040public class MeanAndCovariance {
041        /**
042         * The mean vector (1xN)
043         */
044        public final Matrix mean;
045
046        /**
047         * The covariance matrix (NxN)
048         */
049        public final Matrix covar;
050
051        /**
052         * Construct a new {@link MeanAndCovariance} containing the mean vector and
053         * covariance matrix of the given data (each row is a data point)
054         * 
055         * @param samples
056         *            the data
057         */
058        public MeanAndCovariance(float[][] samples)
059        {
060                final int nsamples = samples.length;
061                final int ndims = samples[0].length;
062
063                mean = new Matrix(1, ndims);
064                covar = new Matrix(ndims, ndims);
065
066                // mean
067                for (int j = 0; j < nsamples; j++) {
068                        for (int i = 0; i < ndims; i++) {
069                                mean.set(0, i, mean.get(0, i) + samples[j][i]);
070                        }
071                }
072                for (int i = 0; i < ndims; i++) {
073                        mean.set(0, i, mean.get(0, i) / nsamples);
074                }
075
076                // covar
077                for (int i = 0; i < ndims; i++) {
078                        for (int j = 0; j < ndims; j++) {
079                                double qij = 0;
080
081                                for (int k = 0; k < nsamples; k++) {
082                                        qij += (samples[k][i] - mean.get(0, i)) * (samples[k][j] - mean.get(0, j));
083                                }
084
085                                covar.set(i, j, qij / (nsamples - 1));
086                        }
087                }
088        }
089
090        /**
091         * Construct a new {@link MeanAndCovariance} containing the mean vector and
092         * covariance matrix of the given data (each row is a data point)
093         * 
094         * @param samples
095         *            the data
096         */
097        public MeanAndCovariance(double[][] samples)
098        {
099                final int nsamples = samples.length;
100                final int ndims = samples[0].length;
101
102                mean = new Matrix(1, ndims);
103                covar = new Matrix(ndims, ndims);
104
105                // mean
106                for (int j = 0; j < nsamples; j++) {
107                        for (int i = 0; i < ndims; i++) {
108                                mean.set(0, i, mean.get(0, i) + samples[j][i]);
109                        }
110                }
111                for (int i = 0; i < ndims; i++) {
112                        mean.set(0, i, mean.get(0, i) / nsamples);
113                }
114
115                // covar
116                for (int i = 0; i < ndims; i++) {
117                        for (int j = 0; j < ndims; j++) {
118                                double qij = 0;
119
120                                for (int k = 0; k < nsamples; k++) {
121                                        qij += (samples[k][i] - mean.get(0, i)) * (samples[k][j] - mean.get(0, j));
122                                }
123
124                                covar.set(i, j, qij / (nsamples - 1));
125                        }
126                }
127        }
128
129        /**
130         * Construct a new {@link MeanAndCovariance} containing the mean vector and
131         * covariance matrix of the given data (each row is a data point)
132         * 
133         * @param samples
134         *            the data
135         */
136        public MeanAndCovariance(Matrix samples) {
137                this(samples.getArray());
138        }
139
140        /**
141         * Get the mean vector
142         * 
143         * @return the mean vector
144         */
145        public Matrix getMean() {
146                return mean;
147        }
148
149        /**
150         * Get the covariance matrix
151         * 
152         * @return the covariance matrix
153         */
154        public Matrix getCovariance() {
155                return covar;
156        }
157
158        /**
159         * Get the mean of the data
160         * 
161         * @param samples
162         *            the data
163         * @return the mean
164         */
165        public static Matrix computeMean(float[][] samples) {
166                return new MeanAndCovariance(samples).mean;
167        }
168
169        /**
170         * Get the covariance of the data
171         * 
172         * @param samples
173         *            the data
174         * @return the covariance matrix
175         */
176        public static Matrix computeCovariance(float[][] samples) {
177                return new MeanAndCovariance(samples).covar;
178        }
179
180        /**
181         * Get the mean of the data
182         * 
183         * @param samples
184         *            the data
185         * @return the mean
186         */
187        public static Matrix computeMean(double[][] samples) {
188                return new MeanAndCovariance(samples).mean;
189        }
190
191        /**
192         * Get the covariance of the data
193         * 
194         * @param samples
195         *            the data
196         * @return the covariance matrix
197         */
198        public static Matrix computeCovariance(double[][] samples) {
199                return new MeanAndCovariance(samples).covar;
200        }
201
202        /**
203         * Get the mean of the data
204         * 
205         * @param samples
206         *            the data
207         * @return the mean
208         */
209        public static Matrix computeMean(Matrix samples) {
210                return new MeanAndCovariance(samples).mean;
211        }
212
213        /**
214         * Get the covariance of the data
215         * 
216         * @param samples
217         *            the data
218         * @return the covariance matrix
219         */
220        public static Matrix computeCovariance(Matrix samples) {
221                return new MeanAndCovariance(samples).covar;
222        }
223}