package edu.stanford.nlp.classify; import edu.stanford.nlp.optimization.AbstractCachingDiffFunction; import java.util.Arrays; /** * @author jrfinkel */ public class BiasedLogisticObjectiveFunction extends AbstractCachingDiffFunction { private final int numFeatures; private final int[][] data; private final double[][] dataValues; private final int[] labels; protected float[] dataweights = null; private final LogPrior prior; double probCorrect = 0.7; @Override public int domainDimension() { return numFeatures; } @Override protected void calculate(double[] x) { if (dataValues != null) { throw new RuntimeException(); } value = 0.0; Arrays.fill(derivative, 0.0); for (int d = 0; d < data.length; d++) { int[] features = data[d]; double sum = 0; for (int feature1 : features) { sum += x[feature1]; } double expSum, derivativeIncrement; if (dataweights != null) { throw new RuntimeException(); } if (labels[d] == 1) { expSum = Math.exp(-sum); double g = (1 / (1 + expSum)); value -= Math.log(g); derivativeIncrement = (g-1); } else { // expSum = Math.exp(-sum); // double g = (1 / (1 + expSum)); // value -= Math.log(1-g); // derivativeIncrement = (g); // } expSum = Math.exp(-sum); double g = (1 / (1 + expSum)); double e = (1-probCorrect) * g + (probCorrect)*(1 - g); value -= Math.log(e); derivativeIncrement = -(g*(1-g)*(1-2*probCorrect)) / (e); } for (int feature : features) { derivative[feature] += derivativeIncrement; } } value += prior.compute(x, derivative); } protected void calculateRVF(double[] x) { value = 0.0; Arrays.fill(derivative, 0.0); for (int d = 0; d < data.length; d++) { int[] features = data[d]; double[] values = dataValues[d]; double sum = 0; for (int feature1 : features) { sum += x[feature1] * values[feature1]; } double expSum, derivativeIncrement; if (labels[d] == 0) { expSum = Math.exp(sum); derivativeIncrement = 1.0 / (1.0 + (1.0 / expSum)); } else { expSum = Math.exp(-sum); derivativeIncrement = -1.0 / (1.0 + (1.0 / expSum)); } if (dataweights == null) { value += Math.log(1.0 + expSum); } else { value += Math.log(1.0 + expSum) * dataweights[d]; derivativeIncrement *= dataweights[d]; } for (int feature : features) { derivative[feature] += values[feature] * derivativeIncrement; } } value += prior.compute(x, derivative); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, int[] labels) { this(numFeatures, data, labels, new LogPrior(LogPrior.LogPriorType.QUADRATIC)); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, int[] labels, LogPrior prior) { this(numFeatures, data, labels, prior, null); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, int[] labels, float[] dataweights) { this(numFeatures, data, labels, new LogPrior(LogPrior.LogPriorType.QUADRATIC), dataweights); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, int[] labels, LogPrior prior, float[] dataweights) { this(numFeatures, data, null, labels, prior, dataweights); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, double[][] values, int[] labels) { this(numFeatures, data, values, labels, new LogPrior(LogPrior.LogPriorType.QUADRATIC)); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, double[][] values, int[] labels, LogPrior prior) { this(numFeatures, data, values, labels, prior, null); } public BiasedLogisticObjectiveFunction(int numFeatures, int[][] data, double[][] values, int[] labels, LogPrior prior, float[] dataweights) { this.numFeatures = numFeatures; this.data = data; this.labels = labels; this.prior = prior; this.dataweights = dataweights; this.dataValues = values; } }