示例#1
0
  // Note: For small probabilities, product may end up zero due to underflow error. Can circumvent
  // by taking logs.
  @Override
  protected double[] score0(double[] data, double[] preds) {
    double[] nums = new double[_output._levels.length]; // log(p(x,y)) for all levels of y
    assert preds.length
        == (_output._levels.length + 1); // Note: First column of preds is predicted response class

    // Compute joint probability of predictors for every response class
    for (int rlevel = 0; rlevel < _output._levels.length; rlevel++) {
      // Take logs to avoid overflow: p(x,y) = p(x|y)*p(y) -> log(p(x,y)) = log(p(x|y)) + log(p(y))
      nums[rlevel] = Math.log(_output._apriori_raw[rlevel]);

      for (int col = 0; col < _output._ncats; col++) {
        if (Double.isNaN(data[col])) continue; // Skip predictor in joint x_1,...,x_m if NA
        int plevel = (int) data[col];
        double prob =
            plevel < _output._pcond_raw.length
                ? _output._pcond_raw[col][rlevel][plevel]
                : _parms._laplace
                    / ((double) _output._rescnt[rlevel]
                        + _parms._laplace
                            * _output
                                ._domains[col]
                                .length); // Laplace smoothing if predictor level unobserved in
        // training set
        nums[rlevel] +=
            Math.log(
                prob <= _parms._eps_prob
                    ? _parms._min_prob
                    : prob); // log(p(x|y)) = \sum_{j = 1}^m p(x_j|y)
      }

      // For numeric predictors, assume Gaussian distribution with sample mean and variance from
      // model
      for (int col = _output._ncats; col < data.length; col++) {
        if (Double.isNaN(data[col])) continue; // Skip predictor in joint x_1,...,x_m if NA
        double x = data[col];
        double mean =
            Double.isNaN(_output._pcond_raw[col][rlevel][0])
                ? 0
                : _output._pcond_raw[col][rlevel][0];
        double stddev =
            Double.isNaN(_output._pcond_raw[col][rlevel][1])
                ? 1.0
                : (_output._pcond_raw[col][rlevel][1] <= _parms._eps_sdev
                    ? _parms._min_sdev
                    : _output._pcond_raw[col][rlevel][1]);
        // double prob = Math.exp(new NormalDistribution(mean, stddev).density(data[col])); //
        // slower
        double prob =
            Math.exp(-((x - mean) * (x - mean)) / (2. * stddev * stddev))
                / (stddev * Math.sqrt(2. * Math.PI)); // faster
        nums[rlevel] += Math.log(prob <= _parms._eps_prob ? _parms._min_prob : prob);
      }
    }

    // Numerically unstable:
    // p(x,y) = exp(log(p(x,y))), p(x) = \Sum_{r = levels of y} exp(log(p(x,y = r))) -> p(y|x) =
    // p(x,y)/p(x)
    // Instead, we rewrite using a more stable form:
    // p(y|x) = p(x,y)/p(x) = exp(log(p(x,y))) / (\Sum_{r = levels of y} exp(log(p(x,y = r)))
    //        = 1 / ( exp(-log(p(x,y))) * \Sum_{r = levels of y} exp(log(p(x,y = r))) )
    //        = 1 / ( \Sum_{r = levels of y} exp( log(p(x,y = r)) - log(p(x,y)) ))
    for (int i = 0; i < nums.length; i++) {
      double sum = 0;
      for (int j = 0; j < nums.length; j++) sum += Math.exp(nums[j] - nums[i]);
      preds[i + 1] = 1 / sum;
    }

    // Select class with highest conditional probability
    preds[0] = GenModel.getPrediction(preds, _output._priorClassDist, data, defaultThreshold());
    return preds;
  }