Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PUBDEV-8947: aic glm #6672

Merged
merged 69 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
43e409c
HEXDEV-785: implement loglikelihood calculation for all distributions…
syzonyuliia-h2o Mar 30, 2023
f9627e8
HEXDEV-785: refactoring likelihood calculation in GLMWeightsFun - rem…
syzonyuliia-h2o Mar 30, 2023
3542499
HEXDEV-785: add python test on loglikelihood
syzonyuliia-h2o Mar 30, 2023
e02a77e
HEXDEV-785: refactor python test
syzonyuliia-h2o Mar 30, 2023
04469f8
HEXDEV-785: return the check of family for likelihood calculation
syzonyuliia-h2o Mar 30, 2023
a7f0866
Revert "HEXDEV-785: refactoring likelihood calculation in GLMWeightsF…
syzonyuliia-h2o Mar 30, 2023
797b136
PUBDEV-8947: implement AIC calculation using loglikelihood function f…
syzonyuliia-h2o Mar 30, 2023
e3e2e11
HEXDEV-785: refactor log2pi
syzonyuliia Apr 18, 2023
f8a9fb8
HEXDEV-785: review classification families, refactor and fix logarith…
syzonyuliia Apr 19, 2023
496a3b4
HEXDEV-785: add multinomial family
syzonyuliia Apr 19, 2023
d2e80e5
HEXDEV-785: define probabilities when not given on input
syzonyuliia-h2o Apr 25, 2023
81c6ecb
add R unit test to check AIC, loglikelihood comparison to R.
wendycwong Apr 10, 2023
3526c26
HEXDEV-785: Expose likelihood value to model output
syzonyuliia-h2o Apr 26, 2023
6bcd0dd
HEXDEV-785: apply calc_like parameter in GLM
syzonyuliia-h2o Apr 26, 2023
0df2cfa
HEXDEV-785: enable loglikelihood calculation in python and R tests
syzonyuliia-h2o Apr 26, 2023
9bf16d6
HEXDEV-785: limit loglikelihood calculation to the final scoring only
syzonyuliia-h2o Apr 28, 2023
3d31ed9
PUBDEV-8947: implement AIC calculation using loglikelihood function f…
syzonyuliia-h2o Mar 30, 2023
5af5eea
PUBDEV-8947: refactoring docs
syzonyuliia-h2o Mar 30, 2023
1d17232
Merge remote-tracking branch 'origin/PUBDEV-8947-AIC-GLM' into PUBDEV…
syzonyuliia-h2o Apr 28, 2023
7b025bc
PUBDEV-8947: limiting AIC calculation to the final scoring only
syzonyuliia-h2o May 1, 2023
062cd14
HEXDEV-785: generate files with gradlew build
syzonyuliia-h2o May 2, 2023
9608c34
HEXDEV-785: use different likelihood calculations for build and final…
syzonyuliia-h2o May 2, 2023
542d5ef
updating AIC branch with loglikelihood implementation
syzonyuliia-h2o May 2, 2023
bde0f75
PUBDEV-8947: use different AIC calculations for build and final scoring
syzonyuliia-h2o May 2, 2023
952a074
PUBDEV-8947: remove new data from performance in R
syzonyuliia-h2o May 2, 2023
512124a
add Java and R tests.
wendycwong May 2, 2023
8158059
PUBDEV-8947: fix binomial likelihood calculation in java test
syzonyuliia-h2o May 5, 2023
44374d7
PUBDEV-8947: fix failing jenkins test - add likelihood to the list of…
syzonyuliia-h2o May 5, 2023
7da0072
PUBDEV-8947: start working on quasibinomial test
syzonyuliia-h2o May 5, 2023
8307154
PUBDEV-8947: fix pojo test because of the added GLM parameter
syzonyuliia-h2o May 5, 2023
3c4dda7
Revert "PUBDEV-8947: start working on quasibinomial test"
syzonyuliia-h2o May 5, 2023
a8e6e6b
PUBDEV-8947: add tests for all distributions
syzonyuliia-h2o May 5, 2023
53cfb39
PUBDEV-8947: label failing tests as ignored
syzonyuliia-h2o May 5, 2023
f724a20
PUBDEV-8947: fix the AIC tests on quasibinomial and fractionalbinomi…
syzonyuliia-h2o May 9, 2023
9493f40
Merge branch 'master' into HEXDEV-785-loglikelihood-GLM
syzonyuliia-h2o May 10, 2023
58bb5da
HEXDEV-785: update loglikelihood calculation for Tweedie family with …
syzonyuliia-h2o May 10, 2023
69a360f
Merge branch 'HEXDEV-785-loglikelihood-GLM' into PUBDEV-8947-AIC-GLM
syzonyuliia-h2o May 10, 2023
0a80705
PUBDEV-8947: update loglikelihood and AIC test for Tweedie family
syzonyuliia-h2o May 10, 2023
818c899
HEXDEV-785: change likelihood calculation for GenerateWeights task ba…
syzonyuliia-h2o May 10, 2023
36c92f1
HEXDEV-785: set parameters to true to enable estimation of dispersion…
syzonyuliia-h2o May 10, 2023
34c8f9f
Merge branch 'HEXDEV-785-loglikelihood-GLM' into PUBDEV-8947-AIC-GLM
syzonyuliia-h2o May 10, 2023
3c9dc1b
PUBDEV-8947: add java test for gaussian family
syzonyuliia-h2o May 10, 2023
b219910
PUBDEV-8947: formatting - remove exceeding blank line
syzonyuliia-h2o May 10, 2023
0b0184c
Merge branch 'master' into PUBDEV-8947-AIC-GLM
syzonyuliia-h2o May 10, 2023
9f627f5
PUBDEV-8947: fix setting parameters for HGLM
syzonyuliia-h2o May 11, 2023
ac3762a
PUBDEV-8947: fix likelihood calculation in R test
syzonyuliia-h2o May 11, 2023
ccf1171
PUBDEV-8947: tests update for dispersion parameter estimation
syzonyuliia-h2o May 16, 2023
44dc95a
PUBDEV-8947: dispersion parameter estimation changes
syzonyuliia-h2o May 16, 2023
83978fe
Fix leaks in GLM's Negative Binomial estimation
tomasfryda May 17, 2023
985e720
Merge remote-tracking branch 'origin/tomf_PUBDEV-9087_fix_leak_in_neg…
syzonyuliia-h2o May 17, 2023
f4b1a58
PUBDEV-8947: updating reference contents with loglikelihood
syzonyuliia-h2o May 17, 2023
6e5bebf
PUBDEV-8947: optimizing the family filter for the likelihood
syzonyuliia-h2o May 17, 2023
c22d819
PUBDEV-8947: fixing gamma likelihood calculation to use the estimated…
syzonyuliia-h2o May 17, 2023
954c44a
PUBDEV-8947: refactoring
syzonyuliia-h2o May 17, 2023
0092390
PUBDEV-8947: cleaning code in test file
syzonyuliia-h2o May 17, 2023
d2ffc2d
PUBDEV-8947: add cross-validation test
syzonyuliia-h2o May 17, 2023
f3a6c10
PUBDEV-8947: fix comment in api reference
syzonyuliia-h2o May 17, 2023
46196c8
PUBDEV-8947: regenerate files by build
syzonyuliia-h2o May 17, 2023
2fb6269
PUBDEV-8947: add the check to avoid null pointer exception
syzonyuliia-h2o May 17, 2023
7150ced
PUBDEV-8947: edit the CV test for likelihood and aic
syzonyuliia-h2o May 17, 2023
a2e6b0a
PUBDEV-8947: disable regularization for ML
syzonyuliia-h2o May 17, 2023
f81a0bb
PUBDEV-8947: change to init value in tweedie
syzonyuliia-h2o May 17, 2023
10d284b
PUBDEV-8947: set tweedie var power in test
syzonyuliia-h2o May 17, 2023
6e0f169
PUBDEV-8947: set tweedie var power in python test
syzonyuliia-h2o May 17, 2023
4fd816e
PUBDEV-8947: clean redundant value write
syzonyuliia-h2o May 18, 2023
f0be3da
PUBDEV-8947: clean prints
syzonyuliia-h2o May 18, 2023
d8cae61
PUBDEV-8947: optimize binomial likelihood calculation
syzonyuliia-h2o May 18, 2023
650b3bb
PUBDEV-8947: clarify k in negativebinomial formula
syzonyuliia-h2o May 18, 2023
e77e811
PUBDEV-8947: remove irrelevant condition for tweedie
syzonyuliia-h2o May 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions h2o-algos/src/main/java/hex/gam/MetricBuilderGAM.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import water.util.ArrayUtils;
import water.util.MathUtils;

import java.util.Arrays;

import static hex.glm.GLMModel.GLMParameters.Family.*;

public class MetricBuilderGAM extends ModelMetricsSupervised.MetricBuilderSupervised<MetricBuilderGAM> {
Expand Down Expand Up @@ -51,7 +53,7 @@ public double[] perRow(double[] ds, float[] yact, double weight, double offset,
if (weight == 0) return ds;
_metricBuilder.perRow(ds, yact, weight, offset, m); // grab the generic terms
if (_glmf._family.equals(GLMModel.GLMParameters.Family.negativebinomial))
_log_likelihood += m.likelihood(weight, yact[0], ds[0]);
_log_likelihood += m.likelihood(weight, yact[0], ds);
if (!ArrayUtils.hasNaNsOrInfs(ds) && !ArrayUtils.hasNaNsOrInfs(yact)) {
if (_glmf._family.equals(GLMModel.GLMParameters.Family.multinomial) || _glmf._family.equals(GLMModel.GLMParameters.Family.ordinal))
add2(yact[0], ds[0], weight, offset);
Expand Down Expand Up @@ -86,8 +88,10 @@ public void reduce(MetricBuilderGAM other) {
_metricBuilder.reduce(other._metricBuilder);
_residual_deviance += other._residual_deviance;
_null_deviance += other._null_deviance;
if (_glmf._family.equals(negativebinomial))
if (Arrays.asList(gaussian, binomial, quasibinomial, fractionalbinomial,
poisson, negativebinomial, gamma, tweedie).contains(_glmf._family)) {
_log_likelihood += other._log_likelihood;
}
_nobs += other._nobs;
syzonyuliia marked this conversation as resolved.
Show resolved Hide resolved
_aic2 += other._aic2;
_wcount += other._wcount;
Expand Down Expand Up @@ -157,24 +161,24 @@ public ModelMetrics makeModelMetrics(Model m, Frame f, Frame adaptedFrame, Frame
}
mm = new ModelMetricsBinomialGLM(m, f, mm._nobs, mm._MSE, _domain, metricsBinomial._sigma,
metricsBinomial._auc, metricsBinomial._logloss, residualDeviance(), _null_deviance, _aic, nullDOF(),
resDOF(), gl, _customMetric);
resDOF(), gl, _customMetric, _log_likelihood);
} else if (_glmf._family.equals(multinomial)) {
ModelMetricsMultinomial metricsMultinomial = (ModelMetricsMultinomial) mm;
mm = new ModelMetricsBinomialGLM.ModelMetricsMultinomialGLM(m, f, metricsMultinomial._nobs,
metricsMultinomial._MSE, metricsMultinomial._domain, metricsMultinomial._sigma, metricsMultinomial._cm,
metricsMultinomial._hit_ratios, metricsMultinomial._logloss, residualDeviance(),_null_deviance, _aic,
nullDOF(), resDOF(), metricsMultinomial._auc, _customMetric);
nullDOF(), resDOF(), metricsMultinomial._auc, _customMetric, _log_likelihood);
} else if (_glmf._family == GLMModel.GLMParameters.Family.ordinal) { // ordinal should have a different resDOF()
ModelMetricsOrdinal metricsOrdinal = (ModelMetricsOrdinal) mm;
mm = new ModelMetricsBinomialGLM.ModelMetricsOrdinalGLM(m, f, metricsOrdinal._nobs, metricsOrdinal._MSE,
metricsOrdinal._domain, metricsOrdinal._sigma, metricsOrdinal._cm, metricsOrdinal._hit_ratios,
metricsOrdinal._logloss, residualDeviance(), _null_deviance, _aic, nullDOF(), resDOF(), _customMetric);
metricsOrdinal._logloss, residualDeviance(), _null_deviance, _aic, nullDOF(), resDOF(), _customMetric, _log_likelihood);
} else {
ModelMetricsRegression metricsRegression = (ModelMetricsRegression) mm;
mm = new ModelMetricsRegressionGLM(m, f, metricsRegression._nobs, metricsRegression._MSE,
metricsRegression._sigma, metricsRegression._mean_absolute_error,
metricsRegression._root_mean_squared_log_error, residualDeviance(),
residualDeviance() / _wcount, _null_deviance, _aic, nullDOF(), resDOF(), _customMetric);
residualDeviance() / _wcount, _null_deviance, _aic, nullDOF(), resDOF(), _customMetric, _log_likelihood);
}
return gamM.addModelMetrics(mm);
}
Expand Down
8 changes: 4 additions & 4 deletions h2o-algos/src/main/java/hex/generic/GenericModelOutput.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ auc, binomial._logloss, convertTable(binomial._gains_lift_table),
convertTable(binomial._thresholds_and_metric_scores), convertTable(binomial._max_criteria_and_metric_scores),
convertTable(binomial._confusion_matrix), glmBinomial._nullDegreesOfFreedom, glmBinomial._residualDegreesOfFreedom,
glmBinomial._resDev, glmBinomial._nullDev, glmBinomial._AIC, convertTable(modelAttributesGLM._coefficients_table),
glmBinomial._r2, glmBinomial._description);
glmBinomial._r2, glmBinomial._description, glmBinomial._loglikelihood);
} else {
return new ModelMetricsBinomialGeneric(null, null, mojoMetrics._nobs, mojoMetrics._MSE,
_domains[_domains.length - 1], binomial._sigma,
Expand All @@ -126,7 +126,7 @@ glmMultinomial._logloss, customMetric(mojoMetrics),
glmMultinomial._mean_per_class_error, glmMultinomial._nullDegreesOfFreedom, glmMultinomial._residualDegreesOfFreedom,
glmMultinomial._resDev, glmMultinomial._nullDev, glmMultinomial._AIC, convertTable(modelAttributesGLM._coefficients_table),
glmMultinomial._r2, convertTable(glmMultinomial._multinomial_auc), convertTable(glmMultinomial._multinomial_aucpr),
MultinomialAucType.valueOf((String)modelAttributes.getParameterValueByName("auc_type")), glmMultinomial._description);
MultinomialAucType.valueOf((String)modelAttributes.getParameterValueByName("auc_type")), glmMultinomial._description, glmMultinomial._loglikelihood);
} else {
final MojoModelMetricsMultinomial multinomial = (MojoModelMetricsMultinomial) mojoMetrics;
return new ModelMetricsMultinomialGeneric(null, null, mojoMetrics._nobs, mojoMetrics._MSE,
Expand All @@ -147,7 +147,7 @@ multinomial._mean_per_class_error, multinomial._r2, convertTable(multinomial._mu
regressionGLM._sigma, regressionGLM._mae, regressionGLM._root_mean_squared_log_error, regressionGLM._mean_residual_deviance,
customMetric(regressionGLM), regressionGLM._r2,
regressionGLM._nullDegreesOfFreedom, regressionGLM._residualDegreesOfFreedom, regressionGLM._resDev,
regressionGLM._nullDev, regressionGLM._AIC, convertTable(modelAttributesGLM._coefficients_table));
regressionGLM._nullDev, regressionGLM._AIC, regressionGLM._loglikelihood, convertTable(modelAttributesGLM._coefficients_table));
} else {
MojoModelMetricsRegression metricsRegression = (MojoModelMetricsRegression) mojoMetrics;

Expand All @@ -174,7 +174,7 @@ multinomial._mean_per_class_error, multinomial._r2, convertTable(multinomial._mu
ordinalMetrics._domain, ordinalMetrics._sigma, convertTable(ordinalMetrics._cm), ordinalMetrics._hit_ratios,
ordinalMetrics._logloss, customMetric(ordinalMetrics),
ordinalMetrics._r2, ordinalMetrics._nullDegreesOfFreedom, ordinalMetrics._residualDegreesOfFreedom, ordinalMetrics._resDev,
ordinalMetrics._nullDev, ordinalMetrics._AIC, convertTable(modelAttributesGLM._coefficients_table),
ordinalMetrics._nullDev, ordinalMetrics._AIC, ordinalMetrics._loglikelihood, convertTable(modelAttributesGLM._coefficients_table),
convertTable(ordinalMetrics._hit_ratio_table), ordinalMetrics._mean_per_class_error, ordinalMetrics._description);
} else {
MojoModelMetricsOrdinal ordinalMetrics = (MojoModelMetricsOrdinal) mojoMetrics;
Expand Down
11 changes: 5 additions & 6 deletions h2o-algos/src/main/java/hex/glm/DispersionUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -264,15 +264,13 @@ public void reduce(CalculateInitialTheta mrt) {
}
};

public static double estimateNegBinomialDispersionMomentMethod(GLMModel model, double[] beta, DataInfo dinfo, Vec weights, Vec response) {
DispersionTask.GenPrediction gPred = new DispersionTask.GenPrediction(beta, model, dinfo).doAll(
1, Vec.T_NUM, dinfo._adaptedFrame);
Vec mu = gPred.outputFrame(Key.make(), new String[]{"prediction"}, null).vec(0);
public static double estimateNegBinomialDispersionMomentMethod(GLMModel model, double[] beta, DataInfo dinfo, Vec weights, Vec response, Vec mu) {
class MomentMethodThetaEstimation extends MRTask<MomentMethodThetaEstimation> {
double _muSqSum;
double _sSqSum;
double _muSum;
double _wSum;

@Override
public void map(Chunk[] cs) {
// mu, y, w
Expand All @@ -292,10 +290,11 @@ public void reduce(MomentMethodThetaEstimation mrt) {
_muSum += mrt._muSum;
_wSum += mrt._wSum;
}
};
}
;
MomentMethodThetaEstimation mm = new MomentMethodThetaEstimation().doAll(mu, response, weights);

return mm._muSqSum/(mm._sSqSum - mm._muSum/mm._wSum);
return mm._muSqSum / (mm._sSqSum - mm._muSum / mm._wSum);
}


Expand Down
131 changes: 82 additions & 49 deletions h2o-algos/src/main/java/hex/glm/GLM.java
Original file line number Diff line number Diff line change
Expand Up @@ -1281,6 +1281,29 @@ public void init(boolean expensive) {
if (_parms._fix_tweedie_variance_power && !_parms._fix_dispersion_parameter)
_tweedieDispersionOnly = true;

// likelihood calculation for gaussian, gamma, negativebinomial and tweedie families requires dispersion parameter estimation
// _dispersion_parameter_method: gaussian - pearson (default); gamma, negativebinomial, tweedie - ml.
if(!_parms._HGLM && _parms._calc_like) {
switch (_parms._family) {
case gaussian:
_parms._compute_p_values = true;
_parms._remove_collinear_columns = true;
break;
case gamma:
case negativebinomial:
_parms._compute_p_values = true;
_parms._remove_collinear_columns = true;
case tweedie:
// dispersion value estimation for tweedie family does not require
// parameters compute_p_values and remove_collinear_columns
_parms._dispersion_parameter_method = ml;
// disable regularization as ML is supported only without regularization
_parms._lambda = new double[] {0.0};
default:
// other families does not require dispersion parameter estimation
}
}

if (_parms.hasCheckpoint()) {
if (!Family.gaussian.equals(_parms._family)) // Gaussian it not iterative and therefore don't care
_checkPointFirstIter = true; // mark the first iteration during iteration process of training
Expand Down Expand Up @@ -2446,62 +2469,67 @@ private boolean updateNegativeBinomialDispersion(int iterCnt, double[] betaCnd,
double delta;
double theta;
boolean converged = false;
if (iterCnt == 1) {
theta = estimateNegBinomialDispersionMomentMethod(_model, betaCnd, _dinfo, weights, response);
} else {
theta = _parms._theta;
try {
Scope.enter();
DispersionTask.GenPrediction gPred = new DispersionTask.GenPrediction(betaCnd, _model, _dinfo).doAll(
1, Vec.T_NUM, _dinfo._adaptedFrame);
Vec mu = gPred.outputFrame(Key.make(), new String[]{"prediction"}, null).vec(0);

NegativeBinomialGradientAndHessian nbGrad = new NegativeBinomialGradientAndHessian(theta).doAll(mu, response, weights);
delta = _parms._dispersion_learning_rate * nbGrad._grad / nbGrad._hess;
double bestLLH = Math.max(-previousNLLH, nbGrad._llh);
double bestTheta = theta;
Vec mu = Scope.track(gPred.outputFrame(Key.make(), new String[]{"prediction"}, null)).vec(0);

delta = Double.isFinite(delta) ? delta : 1; // NaN can occur in extreme datasets so try to get out of this neighborhood just by linesearch

// Golden section search for the optimal size of delta
// Set lowerbound to -10 or lowest value that will keep theta > 0 which ever is bigger
// Negative value here helps with datasets where we use to diverge, I'm not sure yet if it's caused by some
// numerical issues or if the likelihood can get multimodal for some cases.
double lowerBound = (theta + 10 * delta < 0) ? (1 - 1e-15) * theta / delta : -10;
double upperBound = (theta - 1e3 * delta < 0) ? (1 - 1e-15) * theta / delta : 1e3;
double d = upperBound - lowerBound;

for (int i = 0; i < _parms._max_iterations_dispersion; i++) {
d *= 0.618; // division by golden ratio
final double lowerBoundProposal = upperBound - d;
final double upperBoundProposal = lowerBound + d;
NegativeBinomialGradientAndHessian nbLower = new NegativeBinomialGradientAndHessian(theta - lowerBoundProposal * delta).doAll(mu, response, weights);
NegativeBinomialGradientAndHessian nbUpper = new NegativeBinomialGradientAndHessian(theta - upperBoundProposal * delta).doAll(mu, response, weights);

if (nbLower._llh >= nbUpper._llh) {
upperBound = upperBoundProposal;
if (nbLower._llh > bestLLH) {
bestLLH = nbLower._llh;
bestTheta = nbLower._theta;
if (iterCnt == 1) {
theta = estimateNegBinomialDispersionMomentMethod(_model, betaCnd, _dinfo, weights, response, mu);
} else {
theta = _parms._theta;
NegativeBinomialGradientAndHessian nbGrad = new NegativeBinomialGradientAndHessian(theta).doAll(mu, response, weights);
delta = _parms._dispersion_learning_rate * nbGrad._grad / nbGrad._hess;
double bestLLH = Math.max(-previousNLLH, nbGrad._llh);
double bestTheta = theta;

delta = Double.isFinite(delta) ? delta : 1; // NaN can occur in extreme datasets so try to get out of this neighborhood just by linesearch

// Golden section search for the optimal size of delta
// Set lowerbound to -10 or lowest value that will keep theta > 0 which ever is bigger
// Negative value here helps with datasets where we use to diverge, I'm not sure yet if it's caused by some
// numerical issues or if the likelihood can get multimodal for some cases.
double lowerBound = (theta + 10 * delta < 0) ? (1 - 1e-15) * theta / delta : -10;
double upperBound = (theta - 1e3 * delta < 0) ? (1 - 1e-15) * theta / delta : 1e3;
double d = upperBound - lowerBound;

for (int i = 0; i < _parms._max_iterations_dispersion; i++) {
d *= 0.618; // division by golden ratio
final double lowerBoundProposal = upperBound - d;
final double upperBoundProposal = lowerBound + d;
NegativeBinomialGradientAndHessian nbLower = new NegativeBinomialGradientAndHessian(theta - lowerBoundProposal * delta).doAll(mu, response, weights);
NegativeBinomialGradientAndHessian nbUpper = new NegativeBinomialGradientAndHessian(theta - upperBoundProposal * delta).doAll(mu, response, weights);

if (nbLower._llh >= nbUpper._llh) {
upperBound = upperBoundProposal;
if (nbLower._llh > bestLLH) {
bestLLH = nbLower._llh;
bestTheta = nbLower._theta;
}
} else {
lowerBound = lowerBoundProposal;
if (nbUpper._llh > bestLLH) {
bestLLH = nbUpper._llh;
bestTheta = nbUpper._theta;
}
}
} else {
lowerBound = lowerBoundProposal;
if (nbUpper._llh > bestLLH) {
bestLLH = nbUpper._llh;
bestTheta = nbUpper._theta;
if (Math.abs((upperBoundProposal - lowerBoundProposal) * Math.max(1, delta / Math.max(_parms._theta, bestTheta))) < _parms._dispersion_epsilon || _job.stop_requested()) {
break;
}
}
if (Math.abs((upperBoundProposal - lowerBoundProposal) * Math.max(1, delta / Math.max(_parms._theta, bestTheta))) < _parms._dispersion_epsilon || _job.stop_requested()) {
break;
}

theta = bestTheta;
converged = (nbGrad._llh + previousNLLH) <= _parms._objective_epsilon || !Double.isFinite(theta);
}
delta = _parms._theta - theta;
converged = converged && (Math.abs(delta) / Math.max(_parms._theta, theta) < _parms._dispersion_epsilon);

theta = bestTheta;
converged = (nbGrad._llh + previousNLLH) <= _parms._objective_epsilon || !Double.isFinite(theta);
updateTheta(theta);
return converged;
} finally {
Scope.exit();
}
delta = _parms._theta - theta;
converged = converged && (Math.abs(delta) / Math.max(_parms._theta, theta) < _parms._dispersion_epsilon);

updateTheta(theta);
return converged;
}

private void fitLBFGS() {
Expand Down Expand Up @@ -2773,7 +2801,7 @@ else if (gaussian.equals(_parms._family) && Link.identity.equals(_parms._link))
}
}

if (_parms._compute_p_values) { // compute p-values, standard error, estimate dispersion parameters...
if (_parms._compute_p_values) { // compute p-values, standard error, estimate dispersion parameters...
double se = _parms._init_dispersion_parameter;
boolean seEst = false;
double[] beta = _state.beta(); // standardized if _parms._standardize=true, original otherwise
Expand Down Expand Up @@ -2802,6 +2830,8 @@ else if (gaussian.equals(_parms._family) && Link.identity.equals(_parms._link))
se = estimateTweedieDispersionOnly(_parms, _model, _job, beta, _state.activeData());
}
}
// save estimation to the _params, so it is available for params.likelihood computation
_parms._dispersion_estimated = se;
}
double[] zvalues = MemoryManager.malloc8d(_state.activeData().fullN() + 1);
syzonyuliia marked this conversation as resolved.
Show resolved Hide resolved
// double[][] inv = cholInv(); // from non-standardized predictors
Expand Down Expand Up @@ -3457,8 +3487,11 @@ private void doCompute() {
_model.setVcov(_vcov);
_model.update(_job._key);
}
if (!_parms._HGLM) // no need to do for HGLM
if (!_parms._HGLM) { // no need to do for HGLM
_model._finalScoring = true; // enables likelihood calculation while scoring
scoreAndUpdateModel();
_model._finalScoring = false; // avoid calculating likelihood in case of further updates
}

if (dfbetas.equals(_parms._influence))
genRID();
Expand Down
Loading