MetalogParameterEstimator

class MetalogParameterEstimator(val numTerms: Int, val boundedness: MetalogBoundedness, val lowerBound: Double? = null, val upperBound: Double? = null, val useLPFallback: Boolean = true, val ridge: Double = 0.0, name: String? = null) : ParameterEstimatorIfc, MVBSEstimatorIfc, IdentityIfc(source)

Estimates the parameters of a metalog with a fixed number of terms and a fixed boundedness.

Estimation is least squares on cumulative distribution function data, which is what makes the metalog unusual among the families the KSL fits: the quantile function is linear in its coefficients, so no nonlinear optimization is involved.

Two things distinguish this from the other estimators here. Least squares can return coefficients whose quantile function is not strictly increasing, which is not a distribution; when that happens and the fallback is enabled, the fit is retried as a linear program with the monotonicity imposed as constraints, which is valid by construction. And a bound, where the chosen boundedness needs one, is profiled from the data unless supplied, by fitting at each candidate and keeping whichever fits the observations best.

No shift of the data is performed, which is what checkRange being false means here. A metalog represents a lower bound natively: the lower-bounded member is bl + exp(M(y)), so its bound already is the threshold parameter a shift would estimate, and the two are not jointly identifiable. The unbounded member is supported on the whole real line and has no origin to anchor. This is the same treatment the normal, uniform, triangular, and generalized beta estimators receive, and for the same reason — each of those carries its own location or limits.

Nothing about automatic shifting changes what these estimators produce. When the shift applies, PDFModeler.estimateParameters hands the shifted data only to estimators whose checkRange is true, so a metalog fit is identical either way.

The remaining consideration is only wasted work, and it is not specific to this family: the bootstrap for the minimum runs once per call whenever automaticShifting is true, whether or not any estimator in the set can use the result. Fitting only estimators that decline the shift therefore pays for a bootstrap nobody reads. Whether that is worth avoiding depends on the sample size — measured against the twenty metalog fits, the bootstrap is roughly a sixth of their cost at a thousand observations, comparable at ten thousand, and several times their cost beyond about a hundred thousand, since the fits work from a fixed-size resampling grid while the bootstrap grows with the sample. Passing automaticShifting = false is worth it for a metalog-only run on a large sample and is close to irrelevant on a small one. Leave it on when the classical families are in the same set, since they do use it.

What to trust in the result

Trust the fitted distribution. Do not read much into which arity and boundedness produced it.

Fitting the whole family and taking the top-ranked result recovers the underlying distribution well: measured against data generated from known metalogs, the fitted distribution sits a median Kolmogorov distance of about 0.02 to 0.03 from the generating one at a thousand observations, which is inside the sampling noise of the data itself, and the distance falls steadily as the sample grows.

Which member of the family carries that fit is another matter, and is close to arbitrary. The arities nest: a four-term metalog whose fourth coefficient is small is nearly a three-term metalog, and no quantity of data separates them. Boundedness has the same difficulty, since an unbounded metalog and a lower-bounded one whose bound sits far from the data agree everywhere the data lives. In measurements against known generating distributions, the exact generating arity and boundedness came back roughly one time in five, and raising the sample size by a factor of twenty did not systematically improve it.

This is the correct statistical outcome rather than a defect: the candidates really are indistinguishable, and the ranking is choosing among fits that describe the data equally well. It does mean that "the data came from a four-term metalog" is not a conclusion this estimator can support, and that a report naming the winning arity should not be read as identifying one.

See MetalogRecoveryTest for the measurements behind these statements.

Parameters

numTerms

how many metalog terms to fit, between two and six

boundedness

which member of the family to fit

lowerBound

the lower bound to use, or null to profile it from the data

upperBound

the upper bound to use, or null to profile it from the data

useLPFallback

whether to retry an invalid least squares fit as a linear program

ridge

the ridge parameter for the least squares solve

name

an optional name, defaulting to one naming the terms and the boundedness

Constructors

Link copied to clipboard
constructor(numTerms: Int, boundedness: MetalogBoundedness, lowerBound: Double? = null, upperBound: Double? = null, useLPFallback: Boolean = true, ridge: Double = 0.0, name: String? = null)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard
Link copied to clipboard
open override val checkRange: Boolean = false

A metalog carries any lower bound natively, so shifting the data would be redundant and would work against the bound profiling.

Link copied to clipboard
Link copied to clipboard
open override val names: List<String>

The coefficient names followed by whichever bounds this boundedness actually uses. Only bounds that are finite appear, so bootstrapping never has to average an infinity.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
open override val rvType: RVParametersTypeIfc

The type of random variable for which this estimator estimates parameters.

Link copied to clipboard
Link copied to clipboard

Functions

Link copied to clipboard
open override fun estimate(data: DoubleArray): DoubleArray

The estimated values in the order given by the names, or an empty array when the estimation did not succeed.

Link copied to clipboard
open override fun estimateParameters(data: DoubleArray, statistics: StatisticIfc): EstimationResult

Estimates the parameters associated with some distribution. The returned EstimationResult needs to be consistent with the intent of the desired distribution. Note the meaning of the fields associated with EstimationResult