You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by td...@apache.org on 2012/11/15 09:19:35 UTC
svn commit: r1409687 -
/mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java
Author: tdunning
Date: Thu Nov 15 08:19:35 2012
New Revision: 1409687
URL: http://svn.apache.org/viewvc?rev=1409687&view=rev
Log:
Improved names for arguments of Multi-normal. No functional changes.
Modified:
mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java
Modified: mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java
URL: http://svn.apache.org/viewvc/mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java?rev=1409687&r1=1409686&r2=1409687&view=diff
==============================================================================
--- mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java (original)
+++ mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java Thu Nov 15 08:19:35 2012
@@ -28,62 +28,91 @@ import java.util.Random;
/**
* Samples from a multi-variate normal distribution.
+ * <p/>
+ * This is done by sampling from several independent unit normal distributions to get a vector u.
+ * The sample value that is returned is then A u + m where A is derived from the covariance matrix
+ * and m is the mean of the result.
+ * <p/>
+ * If \Sigma is the desired covariance matrix, then you can use any value of A such that A' A =
+ * \Sigma. The Cholesky decomposition can be used to compute A if \Sigma is positive definite.
+ * Slightly more expensive is to use the SVD U S V' = \Sigma and then set A = U \sqrt{S}.
+ *
+ * Useful special cases occur when \Sigma is diagonal so that A = \sqrt(\Sigma) or where \Sigma = r I.
+ *
+ * Another special case is where m = 0.
*/
public class MultiNormal implements Sampler<Vector> {
- private final Random gen;
- private final int dimension;
- private final Matrix mean;
- private final Vector offset;
-
- public MultiNormal(Vector diagonal) {
- this(new DiagonalMatrix(diagonal), null);
- }
-
- public MultiNormal(Vector diagonal, Vector offset) {
- this(new DiagonalMatrix(diagonal), offset);
- }
-
- public MultiNormal(Matrix a, Vector offset) {
- this(a, offset, a.columnSize());
- }
-
- public MultiNormal(int dimension) {
- this(null, null, dimension);
- }
-
- public MultiNormal(double radius, Vector mean) {
- this(new DiagonalMatrix(radius, mean.size()), mean);
- }
-
- private MultiNormal(Matrix mean, Vector offset, int dimension) {
- gen = RandomUtils.getRandom();
- this.dimension = dimension;
- this.mean = mean;
- this.offset = offset;
- }
-
- @Override
- public Vector sample() {
- Vector v = new DenseVector(dimension).assign(
- new DoubleFunction() {
- @Override
- public double apply(double ignored) {
- return gen.nextGaussian();
- }
- }
- );
- if (offset != null) {
- return mean.times(v).plus(offset);
- } else {
- if (mean != null) {
- return mean.times(v);
- } else {
- return v;
- }
+ private final Random gen;
+ private final int dimension;
+ private final Matrix scale;
+ private final Vector mean;
+
+ /**
+ * Constructs a sampler with diagonal scale matrix.
+ * @param diagonal The diagonal elements of the scale matrix.
+ */
+ public MultiNormal(Vector diagonal) {
+ this(new DiagonalMatrix(diagonal), null);
+ }
+
+ /**
+ * Constructs a sampler with diagonal scale matrix and (potentially)
+ * non-zero mean.
+ * @param diagonal The scale matrix's principal diagonal.
+ * @param mean The desired mean. Set to null if zero mean is desired.
+ */
+ public MultiNormal(Vector diagonal, Vector mean) {
+ this(new DiagonalMatrix(diagonal), mean);
+ }
+
+ /**
+ * Constructs a sampler with non-trivial scale matrix and mean.
+ */
+ public MultiNormal(Matrix a, Vector mean) {
+ this(a, mean, a.columnSize());
+ }
+
+ public MultiNormal(int dimension) {
+ this(null, null, dimension);
+ }
+
+ public MultiNormal(double radius, Vector mean) {
+ this(new DiagonalMatrix(radius, mean.size()), mean);
+ }
+
+ private MultiNormal(Matrix scale, Vector mean, int dimension) {
+ gen = RandomUtils.getRandom();
+ this.dimension = dimension;
+ this.scale = scale;
+ this.mean = mean;
+ }
+
+ @Override
+ public Vector sample() {
+ Vector v = new DenseVector(dimension).assign(
+ new DoubleFunction() {
+ @Override
+ public double apply(double ignored) {
+ return gen.nextGaussian();
}
- }
-
- public Vector getMean() {
- return offset;
- }
+ }
+ );
+ if (mean != null) {
+ if (scale != null) {
+ return scale.times(v).plus(mean);
+ } else {
+ return v.plus(mean);
+ }
+ } else {
+ if (scale != null) {
+ return scale.times(v);
+ } else {
+ return v;
+ }
+ }
+ }
+
+ public Vector getScale() {
+ return mean;
+ }
}