1.2.0 • Published 2 months ago

@mytskine/curve-fitting v1.2.0

Weekly downloads
-
License
gpl-3.0
Repository
gitlab
Last release
2 months ago

Curve fitting

Given some points in R×R and a parametered function f_p : R → R, find an optimal set of parameters so that f "fits" the points.

E.g. given some points (x_i, y_i) and the model function f(p1, p2)(x) = p1 * x² + p2, find p=p1, p2 so that the least squares error Σ (f(p)(x_i) - y_i)² is minimal.

The only algorithm available in this library is Levenberg-Marquardt. It is suitable for non-linear least-square approximation. See <doc/Levenberg-Marquardt.md> for implementation details. Other algorithms may be implemented later.

For examples and benchmarks : https://mytskine.gitlab.io/curve-fitting-comparison/

Usage

Loading the library

In a JS web code, load build/web/curve-fitting.js. This file is in each release and in the dist branch. You can build the latest version yourself from the master branch.

In a JS Node code, require build/node/curve-fitting.js.

In both cases, an alternative is to import the module @mytskine/curve-fitting.

In a TypeScript code, you can import src/main.ts.

Practical examples

The parameters and the result are documented alongside the code. The default values should cover most needs.

Web (declares a global variable CurveFitting)

<script src="web/curve-fitting.js"></script>
<script>
const data = {
    x: [-5, -1.0, 1, 4, 5],
    y: [28.7, 3.2, 3.1, 18.8, 29],
};
const modelFunction = ([a, b]) => {
    return (x) => a * x * x + b;
};
const results = CurveFitting.levenbergMarquardt(
    data,
    modelFunction,
    {
        parameters: { initial: [4, 4] }
    }
);
console.log(results);
</script>

Module (web)

<script type="module">
  import {levenbergMarquardt} from './curve-fitting.mjs';
  const result = levenbergMarquardt(…);

With NodeJS, first install the dependency:

npm install --prod "@mytskine/curve-fitting"

Then import the ESM module:

import {levenbergMarquardt} from '@mytskine/curve-fitting';

or require the CommonJS package:

const {levenbergMarquardt} = require('@mytskine/curve-fitting/build/node/curve-fitting');

Then you can run your file with nodejs or bundle for the web…

Why this library?

I tried to use mljs/levenberg-marquardt, which is the only JS curve-fitting lib I could find. It's supposed to apply the Levenberg-Marquardt algorithm.

Most often, it failed with small real-world problems, meaning it could not find acceptable solutions, even for non-linear problems with 1 parameter and 10 points. GnuPlot found solutions in milliseconds with the LM algorithm. Only 3 out of 17 standard NIST problems were solved within a 100% tolerance on the χ².

I tried to fix it. It was better after fixing some bugs (no backstep when ρ is negative, lack of stopping conditions, etc), but it was still far from the expected results.

This implementation does pass the NIST tests (15 with a 1% tolerance and 2 with 3%). See https://mytskine.gitlab.io/curve-fitting-comparison/ for a detailed comparison.

Development

pnpm install
# In terminal 1
pnpm run watch
# In terminal 2
…modify the code
pnpm test

When updating the algorithm, check for regressions in quality or speed:

node build/tests/benchmark.js json > base.json
# Udpate the implementation, then …
node build/tests/benchmark.js compare base.json

Building

Releases and the "dist" branch contain JS builds of this library.

To build it yourself :

pnpm install
pnpm run build

In the commands above, replace pnpm with npm or whatever is your favorite JS package manager.

1.2.0

2 months ago

1.1.0

2 months ago

1.0.1

2 months ago

1.0.0

2 months ago