hulo.localization.models.obs.GaussianProcessLDPLMeanMulti.java Source code

Java tutorial

Introduction

Here is the source code for hulo.localization.models.obs.GaussianProcessLDPLMeanMulti.java

Source

/*******************************************************************************
 * Copyright (c) 2014, 2015 IBM Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *******************************************************************************/

package hulo.localization.models.obs;

import hulo.localization.utils.ArrayUtils;

import org.apache.commons.math3.analysis.MultivariateFunction;
import org.apache.commons.math3.optim.PointValuePair;

public class GaussianProcessLDPLMeanMulti extends GaussianProcessLDPLMean {

    final int PDIM = 4;
    final double threshFloorDiff = 1e-9;

    double[] lambdas = { 1000.0, 0.001, 1.0, 1.0 };

    double[][] paramsArray = null;

    public GaussianProcessLDPLMeanMulti() {
    }

    public GaussianProcessLDPLMeanMulti(GaussianProcessLDPLMeanMulti gp) {
        super(gp);
        this.lambdas = gp.lambdas;
        this.paramsArray = gp.paramsArray;
    }

    protected void copyParameters(GaussianProcessLDPLMeanMulti gp) {
        this.lambdas = gp.lambdas;
        this.paramsArray = gp.paramsArray;
    }

    public void setStabilizeParameter(double[] lambdas) {
        this.lambdas = lambdas;
    }

    public double[] getStabilizeParameter() {
        return lambdas;
    }

    public double[][] getParamsArray() {
        return this.paramsArray;
    }

    public void setParamsArray(double[][] paramsArray) {
        this.paramsArray = paramsArray;
    }

    double ITUModel(double[] xr, int id) {
        double[] xs = sourceLocs[id];
        return -10.0 * paramsArray[id][0] * Math.log10(distance(xr, xs)) + paramsArray[id][1]
                - lossByFloorDiff(floorDiff(xr, xs), id);
    }

    double lossByFloorDiff(double floorDiff, int id) {
        if (floorDiff < threshFloorDiff) {
            return 0;
        } else {
            return paramsArray[id][2] * floorDiff + paramsArray[id][3];
        }
    }

    @Override
    protected double meanFunc(double x[], int index_y) {
        int id = activeBeaconList[index_y];
        double rssi = ITUModel(x, id);
        return minRssi < rssi ? rssi : minRssi;
    }

    protected double[] transformFeature(double[] xr, int index_y) {
        int id = activeBeaconList[index_y];
        double[] xs = sourceLocs[id];

        double[] feature = new double[PDIM];
        feature[0] = -10.0 * Math.log10(distance(xr, xs));
        feature[1] = 1;

        double eps = 1e-6;
        feature[2] = floorDiff(xr, xs);
        feature[3] = feature[2] > eps ? 1.0 : 0.0;

        return feature;
    }

    @Override
    public GaussianProcessLDPLMeanMulti fit(double[][] X, double[][] Y) {
        int ny = Y[0].length;
        if (paramsArray == null) {
            paramsArray = new double[ny][PDIM];
            for (int i = 0; i < ny; i++) {
                paramsArray[i] = params.clone();
            }
        }
        super.fit(X, Y);
        return this;
    }

    public double looMSEwithStabilize() {
        return looMSE() + stabilizationTerm();
    }

    public double stabilizationTerm() {
        double[] paramsMean = ArrayUtils.mean(paramsArray);

        int np = params.length;
        int ny = paramsArray.length;

        double regu = 0;
        for (int j = 0; j < np; j++) {
            double regu_j = 0;
            for (int i = 0; i < ny; i++) {
                double diff = paramsArray[i][j] - paramsMean[j];
                regu_j += diff * diff;
            }
            regu_j *= lambdas[j] * 1.0 / 2.0;
            regu += regu_j;
        }

        return regu;
    }

    public double looErrorLDPLMultiPart(int k) {
        looUpdateLDPLMulti(k);

        int ny = Y[0].length;
        int count = 0;
        double sum = 0;
        ;
        for (int j = 0; j < ny; j++) {
            if (Y[k][j] > minRssi) {
                double[] feat = transformFeature(X[k], j);
                double ypred = 0;
                for (int i = 0; i < feat.length; i++) {
                    ypred += feat[i] * paramsArray[j][i];
                }
                double diff = Y[k][j] - ypred;
                sum += diff * diff;
                count += 1;
            }
        }
        if (count != 0) {
            sum /= count;
        }
        return sum;
    }

    void looUpdateLDPLMulti(Integer i_lvd) {
        double[] paramsMean = params;

        int ns = Y.length;
        int ny = Y[0].length;
        for (int j = 0; j < ny; j++) {
            double[][] A = new double[2][2];
            double[] b = new double[2];

            A[0][0] = lambdas[0];
            A[1][1] = lambdas[1];
            A[0][1] = 0;
            A[1][0] = 0;
            b[0] = lambdas[0] * paramsMean[0];
            b[1] = lambdas[1] * paramsMean[1];

            for (int i = 0; i < ns; i++) {
                if (Integer.valueOf(i) != i_lvd) {
                    if (Y[i][j] > minRssi) {
                        double[] feat = transformFeature(X[i], j);
                        A[0][0] += feat[0] * feat[0];
                        A[0][1] += feat[0];
                        A[1][0] += feat[0];
                        A[1][1] += feat[1];
                        b[0] += feat[0] * Y[i][j];
                        b[1] += Y[i][j];
                    }
                }
            }

            double det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
            double[][] invA = { { A[1][1] / det, -A[0][1] / det }, { -A[1][0] / det, A[0][0] / det } };

            double Aj = invA[0][0] * b[0] + invA[0][1] * b[1];
            double bj = invA[1][0] * b[0] + invA[1][1] * b[1];

            paramsArray[j][0] = Aj;
            paramsArray[j][1] = bj;
        }

    }

    void looUpdateLDPLMultiFloorDiff(Integer i_lvd) {
        double[] paramsMean = params;

        int ns = Y.length;
        int ny = Y[0].length;
        for (int j = 0; j < ny; j++) {
            double[][] A = new double[2][2];
            double[] b = new double[2];

            A[0][0] = lambdas[2];
            A[1][1] = lambdas[3];
            A[0][1] = 0;
            A[1][0] = 0;
            b[0] = lambdas[2] * paramsMean[2];
            b[1] = lambdas[3] * paramsMean[3];

            for (int i = 0; i < ns; i++) {
                if (Integer.valueOf(i) != i_lvd) {
                    if (Y[i][j] > minRssi) {
                        double[] feat = transformFeature(X[i], j);
                        A[0][0] += feat[2] * feat[2];
                        A[0][1] += feat[2];
                        A[1][0] += feat[2];
                        A[1][1] += feat[3];
                        b[0] += feat[2] * Y[i][j];
                        b[1] += Y[i][j];
                    }
                }
            }

            double det = A[0][0] * A[1][1] - A[0][1] * A[1][0];
            double[][] invA = { { A[1][1] / det, -A[0][1] / det }, { -A[1][0] / det, A[0][0] / det } };

            double Aj = invA[0][0] * b[0] + invA[0][1] * b[1];
            double bj = invA[1][0] * b[0] + invA[1][1] * b[1];

            paramsArray[j][2] = Aj;
            paramsArray[j][3] = bj;
        }
    }

    public void optimizeLDPLMultiHyperParams() {

        final GaussianProcessLDPLMeanMulti gpLDPLMulti = this;

        MultivariateFunction costFunc = new MultivariateFunction() {
            @Override
            public double value(double[] point) {

                double[] params = gpLDPLMulti.getParams();
                params[0] = point[0];
                params[1] = point[1];
                gpLDPLMulti.setParams(params);
                double[] lmdRegu = gpLDPLMulti.getStabilizeParameter();
                lmdRegu[0] = Math.pow(10, point[2]);
                lmdRegu[1] = Math.pow(10, point[3]);
                gpLDPLMulti.setStabilizeParameter(lmdRegu);

                int ns = X.length;
                double aveLOOMSE = 0.0;
                for (int k = 0; k < ns; k++) {
                    gpLDPLMulti.fit(X, Y);
                    double looMSE = gpLDPLMulti.looErrorLDPLMultiPart(k);
                    aveLOOMSE += looMSE / ns;
                }

                final StringBuilder sb = new StringBuilder();
                sb.setLength(0);
                sb.append("optimizeLDPLMultiHyperParams: ");
                sb.append("aveLOOMSE=" + aveLOOMSE + ", ");
                sb.append("n=" + params[0] + ",A=" + params[1] + ", lmdn=" + lmdRegu[0] + ",lmdA=" + lmdRegu[1]);
                sb.append(", ns=" + ns);
                System.out.println(sb.toString());

                return aveLOOMSE;
            }
        };

        double[] pointInit = { params[0], params[1], Math.log10(lambdas[0]), Math.log10(lambdas[1]) };
        double[] dPointInit = { 0.1, 1.0, 0.1, 0.1 };

        PointValuePair pair = GaussianProcessLDPLMean.minimize(costFunc, pointInit, dPointInit);
        double[] point = pair.getPoint();
        double[] params = gpLDPLMulti.getParams();
        params[0] = point[0];
        params[1] = point[1];
        gpLDPLMulti.setParams(params);
        double[] lambdas = gpLDPLMulti.getStabilizeParameter();
        lambdas[0] = Math.pow(10, point[2]);
        lambdas[1] = Math.pow(10, point[3]);
        gpLDPLMulti.setStabilizeParameter(lambdas);

    }

    public void optimizeLDPLMultiParameters() {
        looUpdateLDPLMulti(null);
        System.out.println(toStringParamsArray());
    }

    public String toStringParamsArray() {
        final StringBuilder sb = new StringBuilder();
        sb.setLength(0);
        sb.append("LDPLMulti parameters: ");
        for (int j = 0; j < paramsArray.length; j++) {
            double Aj = paramsArray[j][0];
            double bj = paramsArray[j][1];
            double fa = paramsArray[j][2];
            double fb = paramsArray[j][3];
            sb.append("reassignedId=" + j + ", A=" + Aj + ", b=" + bj + ",fa=" + fa + ",fb=" + fb + ", ");
        }
        sb.append(System.getProperty("line.separator"));

        sb.append("LDPLMulti parameters (statistics): ");

        double[] paramsMean = ArrayUtils.mean(paramsArray);
        double[] paramsVar = ArrayUtils.var(paramsArray);
        double[] paramsMin = ArrayUtils.min(paramsArray);
        double[] paramsMax = ArrayUtils.max(paramsArray);

        sb.append("mean: A=" + paramsMean[0] + ", b=" + paramsMean[1] + ",fa=" + paramsMean[2] + ",fb="
                + paramsMean[3]);
        sb.append(",");
        sb.append("variance: A=" + paramsVar[0] + ", b=" + paramsVar[1] + ",fa=" + paramsVar[2] + ",fb="
                + paramsVar[3]);
        sb.append(",");
        sb.append("min: A=" + paramsMin[0] + ", b=" + paramsMin[1] + ",fa=" + paramsMin[2] + ",fb=" + paramsMin[3]);
        sb.append(",");
        sb.append("max: A=" + paramsMax[0] + ", b=" + paramsMax[1] + ",fa=" + paramsMax[2] + ",fb=" + paramsMax[3]);
        return sb.toString();
    }

}