@mytskine/curve-fitting
v1.2.0
Published
Curve fitting with the Levenberg-Marquardt algorithm
Downloads
21
Maintainers
Readme
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.