Skip to content

Latest commit

 

History

23 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Statistical Modelling

Simulation, descriptive statistics and parameter estimation for ten usual probability distributions, in the browser.

Each distribution is presented three ways: its analytical properties, a simulation that draws a pseudo-random sample and estimates the parameters back from it, and an application that does the same for a sample you supply as a file.

Every distribution carries two estimators side by side — one closed form, obtained by the method of moments or by solving the likelihood equations explicitly, and one numerical, obtained by gradient ascent on the log-likelihood. Comparing them is the point of the exercise.

Origin

This project was written during a first-year internship from the ENSIIE, carried out at the CNAM in the department of mathematics and statistics under the supervision of Dariush Ghorbanzadeh. It ran for eight weeks in June and July 2023, on the subject of implementing an application of the gradient descent method.

This is version 2, a 2026 revision. The statistical content is unchanged. The interface was rebuilt, the code reorganised and translated into English, and several defects in the original estimators were fixed. The 2023 version is preserved in the repository history.

Running it

There is no build step and no dependency to install.

npm start          # serves public/ on http://localhost:8080
npm run build      # copies public/ to dist/, which is what gets deployed

npm run build exists only because dist/ is the directory the host publishes; it is a recursive copy, nothing more.

Layout

public/
  index.html                     overview, project context and the catalogue
  distributions/                 ten distributions x three pages
    <slug>-properties.html         the law, its moments, and a density plot
    <slug>-simulation.html         draw a sample, summarise it, estimate from it
    <slug>-application.html        the same, for an imported sample
  assets/
    css/theme.css                the whole design system, one file
    js/inference.js              sampling, statistics and estimators
    js/ui.js                     shared Vue components and the page factory
    js/site.js                   the distribution catalogue and the sidebar
    js/vendor/                   Chart.js, vendored
scripts/
  build.mjs                      public/ -> dist/
  serve.mjs                      development server

Pages are plain HTML. They load Vue 2.7 and MathJax from a pinned CDN, Chart.js from assets/js/vendor/, and share their behaviour through ui.js rather than repeating it. Adding a distribution means adding one entry to the catalogue in site.js and three files to distributions/.

The library

assets/js/inference.js exposes one global, Inference:

Inference.summary(data)                  // count, min, max, mean, variance, skewness, kurtosis
Inference.bins.discrete(data)            // distinct values and their counts
Inference.bins.continuous(data, 24)      // equal-width bins
Inference.sample.normal(mu, sigma, n)    // and one per distribution
Inference.moment.normal(data)            // closed-form estimators
Inference.mle.normal(data)               // gradient ascent on the log-likelihood
Inference.special.gamma(x)               // gamma and digamma functions
Inference.parseSample(text)              // read numbers out of an uploaded file

Every gradient is averaged over the sample, so a learning rate means the same thing whatever the sample size, and each iteration reuses precomputed sufficient statistics instead of re-reading the sample. That makes the estimators O(n + iterations) rather than O(n × iterations) — the 2023 versions re-read the whole sample on every one of their fifty thousand steps.

Sample file format

The application pages accept plain text containing numbers separated by line breaks, spaces, commas or semicolons. Anything that does not parse as a number is skipped.

Corrections made in version 2

The 2023 code had a number of genuine defects, all verified before being changed:

  • LIB.js threw on load. A stray l after a closing brace raised ReferenceError: l is not defined on every page. Function declarations are hoisted, so the library still worked, but every page logged an error.
  • Uniform (continuous) estimation crashed. Five functions were named logLikelihood and two were named gradient; the last declaration won. The uniform estimator called gradient(data, a, b) and reached the Bernoulli version, which returns a number rather than a pair, so destructuring it threw a TypeError.
  • Both uniform estimators now use the exact maximiser. The likelihood of a uniform law is maximised at the edge of the parameter space, where it is not differentiable, so no gradient method converges to it. The estimator is the sample minimum and maximum.
  • The exponential estimator diverged. Its gradient was summed rather than averaged, so the step size grew with the sample: on 3000 observations it returned about −74 000 instead of 2. Averaging fixed it, and the same normalisation was applied throughout, which also fixed gamma and Weibull returning NaN on large samples.
  • The geometric estimator returned 1 − p. The two terms of the derivative were transposed. For a true p = 0.25 it reported 0.74.
  • digamma was wrong, which sent the gamma estimator to a fixed point of the wrong equations — shape 8.8 where the answer was 3. It now uses the standard recurrence and asymptotic expansion, and agrees with reference values to eight decimals.
  • The Weibull gradient used ^ instead of exponentiation. In JavaScript ^ is bitwise exclusive-or, so the term was meaningless. Its second component was also missing a factor of the shape parameter. The ascent also started from a fixed point regardless of the data, and diverged for a true scale above about 6; it now starts from the closed-form estimate, which holds up to a scale of at least 25.
  • The binomial estimator was pulled towards p = 0.5. Its gradient weighted each observation by the binomial coefficient, which does not depend on p and therefore vanishes on differentiation. Since that coefficient peaks at n/2, the estimate was dragged to the middle: a true p = 0.1 came back as 0.24, and p = 0.9 as 0.76. It was correct only at p = 0.5. The same weighting overflowed to infinity for a large number of trials, leaving the estimate stuck at its starting value.
  • Empty samples read as NaN. Statistics now render as an em dash until a sample exists.

Two things were deliberately not changed: the closed-form estimators, and the learning rates and iteration counts of the estimators that already converged.

Deployment

The site is static. npm run build produces dist/, which is what the host serves.

Contact

younes.chriaa02@gmail.com

About

Interactive statistical modeling application for simulating probability distributions, estimators, and gradient descent optimization using Vue.js and Chart.js.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages