/* * LatentFactorModelPrecisionGibbsOperator.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.inference.operators; import dr.inference.distribution.DistributionLikelihood; import dr.inference.model.*; import dr.math.MathUtils; import dr.math.distributions.GammaDistribution; /** * Created by max on 6/12/14. */ public class LatentFactorModelPrecisionGibbsOperator extends SimpleMCMCOperator implements GibbsOperator { // private double[] FacXLoad; // private double[] residual; private LatentFactorModel LFM; private GammaDistribution prior; private boolean randomScan; private double shape; double pathWeight=1.0; final Parameter missingIndicator; public LatentFactorModelPrecisionGibbsOperator(LatentFactorModel LFM, DistributionLikelihood prior, double weight, boolean randomScan) { setWeight(weight); this.LFM = LFM; this.prior = (GammaDistribution) prior.getDistribution(); this.randomScan = randomScan; this.missingIndicator = LFM.getMissingIndicator(); // FacXLoad=new double[LFM.getFactors().getColumnDimension()]; // residual=new double[LFM.getFactors().getColumnDimension()]; // setShape(); } private double getShape(int i){ return this.prior.getShape() + LFM.getRowCount(i) * .5 * pathWeight; } private void setPrecision(int i) { MatrixParameterInterface factors = LFM.getFactors(); MatrixParameterInterface loadings = LFM.getLoadings(); DiagonalMatrix precision = (DiagonalMatrix) LFM.getColumnPrecision(); MatrixParameterInterface data = LFM.getScaledData(); double di = 0; for (int j = 0; j < factors.getColumnDimension(); j++) { double sum = 0; if(missingIndicator == null || missingIndicator.getParameterValue(j * LFM.getScaledData().getRowDimension() + i) != 1) { for (int k = 0; k < factors.getRowDimension(); k++) { sum += factors.getParameterValue(k, j) * loadings.getParameterValue(i, k); } double temp = data.getParameterValue(i, j) - sum; di += temp * temp; } // FacXLoad[j]=sum; // residual[j]=data.getParameterValue(i,j)-FacXLoad[j]; // } // double sum=0; // for (int j = 0; j <factors.getColumnDimension() ; j++) { // sum+=residual[j]*residual[j]; } double scale = 1.0 / (1.0 / prior.getScale() + pathWeight * di * .5); double nextPrecision = GammaDistribution.nextGamma(getShape(i), scale); precision.setParameterValueQuietly(i, nextPrecision); } public void setPathParameter(double beta) { pathWeight=beta; } @Override public int getStepCount() { return 0; } @Override public String getPerformanceSuggestion() { return "Only works for diagonal column precision matrices for a LatentFactorModel with a gamma prior"; } @Override public String getOperatorName() { return "Latent Factor Model Precision Gibbs Operator"; } @Override public double doOperation() { if (!randomScan) for (int i = 0; i < LFM.getColumnPrecision().getColumnDimension(); i++) { if (LFM.getContinuous().getParameterValue(i) != 0) setPrecision(i); } else { int i = MathUtils.nextInt(LFM.getColumnPrecision().getColumnDimension()); while (LFM.getContinuous().getParameterValue(i) == 0) i = MathUtils.nextInt(LFM.getColumnPrecision().getColumnDimension()); setPrecision(i); } LFM.getColumnPrecision().getParameter(0).fireParameterChangedEvent(); return 0; } }