/******************************************************************************* * Copyright (c) 2012 Michael Kutschke. All rights reserved. This program and the accompanying materials are made * available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: Michael Kutschke - initial API and implementation ******************************************************************************/ package org.eclipse.recommenders.jayes.transformation; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.math.linear.MatrixUtils; import org.eclipse.recommenders.jayes.factor.AbstractFactor; import org.eclipse.recommenders.jayes.util.MathUtils; import com.google.common.primitives.Doubles; /** * Applicable if the conditional probability distribution is, in essence, sparse, but was smoothed (which makes it * non-sparse). The decomposition makes this explicit in the model.<br/> * * <pre> * Example: * { * { 0.99 0.01 } * { 0.01 0.99 } * { 0.01 0.99 } * } * * would decompose to the new basis * * { * { 1 1 } * { 0 1 } * { 1 0 } * } * * and * { * { 0.01 0 1 } * { 0.01 1 0 } * { 0.01 1 0 } * } * </pre> * * <br/> * This works better than {@link LatentDeterministicDecomposition} in cases where the distribution is less close to * being deterministic. A good indicator for when to use it is the size of the dimensions. With large dimensions, it * becomes unlikely that the distributions can be represented by just one basis vector. In that case, * {@link SmoothedFactorDecomposition} works better. * */ public class SmoothedFactorDecomposition extends AbstractDecomposition { @Override protected double[] toLatentSpace(double[] v, List<double[]> best) { double min = Doubles.min(v); double[] latent = new double[v.length + 1]; latent[0] = min; double[] h = new double[v.length]; Arrays.fill(h, min); MathUtils.secureSubtract(v, h, h); System.arraycopy(h, 0, latent, 1, h.length); return latent; } @Override protected List<double[]> getBasis(AbstractFactor f, List<double[]> vectors) { List<double[]> basis = new ArrayList<double[]>(); int d = MathUtils.product(f.getDimensions()) / vectors.size(); double[] ones = new double[d]; Arrays.fill(ones, 1); basis.add(ones); for (double[] e : MatrixUtils.createRealIdentityMatrix(d).getData()) { basis.add(e); } return basis; } }