use of de.lmu.ifi.dbs.elki.math.linearalgebra.SingularValueDecomposition in project elki by elki-project.
the class ClassicMultidimensionalScalingTransformTest method parameters.
/**
* Test with parameters.
*/
@Test
public void parameters() {
int pdim = 2;
String filename = UNITTEST + "transformation-test-1.csv";
ClassicMultidimensionalScalingTransform<DoubleVector, DoubleVector> filter = //
new ELKIBuilder<ClassicMultidimensionalScalingTransform<DoubleVector, DoubleVector>>(ClassicMultidimensionalScalingTransform.class).with(ClassicMultidimensionalScalingTransform.Parameterizer.DIM_ID, //
pdim).with(ClassicMultidimensionalScalingTransform.Parameterizer.DISTANCE_ID, //
EuclideanDistanceFunction.class).build();
MultipleObjectsBundle filteredBundle = readBundle(filename, filter);
// Load the test data again without a filter.
MultipleObjectsBundle unfilteredBundle = readBundle(filename);
int dimu = getFieldDimensionality(unfilteredBundle, 0, TypeUtil.NUMBER_VECTOR_FIELD);
int dimf = getFieldDimensionality(filteredBundle, 0, TypeUtil.NUMBER_VECTOR_FIELD);
assertEquals("Dimensionality not as requested", pdim, dimf);
// Verify that the Euclidean distance between any two points is identical
// before and after the MDS transform is performed - O(n^2)!
// Calculate the covariance matricies of the filtered and unfiltered
// bundles.
CovarianceMatrix cmUnfil = new CovarianceMatrix(dimu);
CovarianceMatrix cmFil = new CovarianceMatrix(dimf);
for (int outer = 0; outer < filteredBundle.dataLength(); outer++) {
DoubleVector dFil_1 = get(filteredBundle, outer, 0, DoubleVector.class);
DoubleVector dUnfil_1 = get(unfilteredBundle, outer, 0, DoubleVector.class);
cmUnfil.put(dUnfil_1);
cmFil.put(dFil_1);
for (int row = outer + 1; row < filteredBundle.dataLength(); row++) {
DoubleVector dFil_2 = get(filteredBundle, row, 0, DoubleVector.class);
DoubleVector dUnfil_2 = get(unfilteredBundle, row, 0, DoubleVector.class);
final double distF = EuclideanDistanceFunction.STATIC.distance(dFil_1, dFil_2);
final double distU = EuclideanDistanceFunction.STATIC.distance(dUnfil_1, dUnfil_2);
assertEquals("Expected same distance", distU, distF, 1e-11);
}
}
// Calculate the SVD of the covariance matrix of the unfiltered data.
// Verify that this SVD represents the diagonals of the covariance matrix of
// the filtered data.
double[][] ncmUnfil = cmUnfil.destroyToPopulationMatrix();
double[][] ncmFil = cmFil.destroyToPopulationMatrix();
SingularValueDecomposition svd = new SingularValueDecomposition(ncmUnfil);
double[] dia = svd.getSingularValues();
for (int ii = 0; ii < dia.length; ii++) {
assertEquals("Unexpected covariance", dia[ii], ncmFil[ii][ii], 1e-11);
}
}
use of de.lmu.ifi.dbs.elki.math.linearalgebra.SingularValueDecomposition in project elki by elki-project.
the class FastMultidimensionalScalingTransformTest method parameters.
/**
* Test with parameters.
*/
@Test
public void parameters() {
int pdim = 2;
String filename = UNITTEST + "transformation-test-1.csv";
FastMultidimensionalScalingTransform<DoubleVector, DoubleVector> filter = //
new ELKIBuilder<FastMultidimensionalScalingTransform<DoubleVector, DoubleVector>>(FastMultidimensionalScalingTransform.class).with(ClassicMultidimensionalScalingTransform.Parameterizer.DIM_ID, //
pdim).with(FastMultidimensionalScalingTransform.Parameterizer.RANDOM_ID, //
0L).with(ClassicMultidimensionalScalingTransform.Parameterizer.DISTANCE_ID, //
EuclideanDistanceFunction.class).build();
MultipleObjectsBundle filteredBundle = readBundle(filename, filter);
// Load the test data again without a filter.
MultipleObjectsBundle unfilteredBundle = readBundle(filename);
int dimu = getFieldDimensionality(unfilteredBundle, 0, TypeUtil.NUMBER_VECTOR_FIELD);
int dimf = getFieldDimensionality(filteredBundle, 0, TypeUtil.NUMBER_VECTOR_FIELD);
assertEquals("Dimensionality not as requested", pdim, dimf);
// Verify that the Euclidean distance between any two points is identical
// before and after the MDS transform is performed - O(n^2)!
// Calculate the covariance matricies of the filtered and unfiltered
// bundles.
CovarianceMatrix cmUnfil = new CovarianceMatrix(dimu);
CovarianceMatrix cmFil = new CovarianceMatrix(dimf);
for (int outer = 0; outer < filteredBundle.dataLength(); outer++) {
DoubleVector dFil_1 = get(filteredBundle, outer, 0, DoubleVector.class);
DoubleVector dUnfil_1 = get(unfilteredBundle, outer, 0, DoubleVector.class);
cmUnfil.put(dUnfil_1);
cmFil.put(dFil_1);
for (int row = outer + 1; row < filteredBundle.dataLength(); row++) {
DoubleVector dFil_2 = get(filteredBundle, row, 0, DoubleVector.class);
DoubleVector dUnfil_2 = get(unfilteredBundle, row, 0, DoubleVector.class);
final double distF = EuclideanDistanceFunction.STATIC.distance(dFil_1, dFil_2);
final double distU = EuclideanDistanceFunction.STATIC.distance(dUnfil_1, dUnfil_2);
assertEquals("Expected same distance", distU, distF, 1e-10);
}
}
// Calculate the SVD of the covariance matrix of the unfiltered data.
// Verify that this SVD represents the diagonals of the covariance matrix of
// the filtered data.
double[][] ncmUnfil = cmUnfil.destroyToPopulationMatrix();
double[][] ncmFil = cmFil.destroyToPopulationMatrix();
SingularValueDecomposition svd = new SingularValueDecomposition(ncmUnfil);
double[] dia = svd.getSingularValues();
for (int ii = 0; ii < dia.length; ii++) {
assertEquals("Unexpected covariance", dia[ii], ncmFil[ii][ii], 1e-8);
}
}
use of de.lmu.ifi.dbs.elki.math.linearalgebra.SingularValueDecomposition in project elki by elki-project.
the class MultidimensionalScalingMSTLayout3DPC method layout.
@Override
public Layout layout(int dim, double[] mat) {
// Find maximum of |cij|
double max = 0;
for (double v : mat) {
v = (v > 0) ? v : -v;
max = (v > max) ? v : max;
}
// Assume that "max - |cij|" is now a distance.
// We use sqrt(v) instead of v*v, since this makes the method
// less aggressive overall, and we are not using euclidean anyway.
double[] means = new double[dim];
double mean = 0.0;
for (int y = 1, o = 0; y < dim; y++) {
for (int x = 0; x < y; x++, o++) {
double v = max - Math.abs(mat[o]);
v = -.5 * FastMath.sqrt(v);
means[x] += v;
means[y] += v;
mean += 2 * v;
}
}
for (int i = 0; i < dim; i++) {
means[i] /= dim;
}
mean /= (dim * dim);
// Build double centered matrix:
double[][] d = new double[dim][dim];
for (int y = 1, o = 0; y < dim; y++) {
d[y][y] = -2 * means[y] + mean;
for (int x = 0; x < y; x++, o++) {
double v = max - Math.abs(mat[o]);
v = -.5 * FastMath.sqrt(v) - means[x] - means[y] + mean;
d[x][y] = d[y][x] = v;
}
}
SingularValueDecomposition svd = new SingularValueDecomposition(d);
double[][] u = svd.getU();
double[] lambda = svd.getSingularValues();
lambda[0] = FastMath.sqrt(Math.abs(lambda[0]));
lambda[1] = FastMath.sqrt(Math.abs(lambda[1]));
Layout l = new Layout();
buildSpanningTree(dim, mat, l);
double maxabs = 0;
for (int i = 0; i < dim; i++) {
Node n = (Node) l.getNode(i);
n.x = u[i][0] * lambda[0];
n.y = u[i][1] * lambda[1];
double v = n.x * n.x + n.y * n.y;
if (v > maxabs) {
maxabs = v;
}
}
maxabs = 1. / FastMath.sqrt(maxabs);
for (int i = 0; i < dim; i++) {
Node n = (Node) l.getNode(i);
n.x *= maxabs;
n.y *= maxabs;
}
return l;
}
use of de.lmu.ifi.dbs.elki.math.linearalgebra.SingularValueDecomposition in project elki by elki-project.
the class ClassicMultidimensionalScalingTransform method filter.
@Override
public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
final int size = objects.dataLength();
if (size == 0) {
return objects;
}
MultipleObjectsBundle bundle = new MultipleObjectsBundle();
for (int r = 0; r < objects.metaLength(); r++) {
@SuppressWarnings("unchecked") SimpleTypeInformation<Object> type = (SimpleTypeInformation<Object>) objects.meta(r);
@SuppressWarnings("unchecked") final List<Object> column = (List<Object>) objects.getColumn(r);
if (!dist.getInputTypeRestriction().isAssignableFromType(type)) {
bundle.appendColumn(type, column);
continue;
}
// Get the replacement type information
@SuppressWarnings("unchecked") final List<I> castColumn = (List<I>) column;
bundle.appendColumn(new VectorFieldTypeInformation<>(factory, tdim), castColumn);
StepProgress prog = LOG.isVerbose() ? new StepProgress("Classic MDS", 2) : null;
// Compute distance matrix.
LOG.beginStep(prog, 1, "Computing distance matrix");
double[][] mat = computeSquaredDistanceMatrix(castColumn, dist);
doubleCenterSymmetric(mat);
// Find eigenvectors.
{
LOG.beginStep(prog, 2, "Computing singular value decomposition");
SingularValueDecomposition svd = new SingularValueDecomposition(mat);
double[][] u = svd.getU();
double[] lambda = svd.getSingularValues();
// Undo squared, unless we were given a squared distance function:
if (!dist.isSquared()) {
for (int i = 0; i < tdim; i++) {
lambda[i] = FastMath.sqrt(Math.abs(lambda[i]));
}
}
double[] buf = new double[tdim];
for (int i = 0; i < size; i++) {
double[] row = u[i];
for (int x = 0; x < buf.length; x++) {
buf[x] = lambda[x] * row[x];
}
column.set(i, factory.newNumberVector(buf));
}
}
LOG.setCompleted(prog);
}
return bundle;
}
Aggregations