ml-regression-polynomial
Advanced tools
Comparing version 2.2.0 to 3.0.0
289
lib/index.js
@@ -1,132 +0,179 @@ | ||
'use strict'; | ||
var mlMatrix = require('ml-matrix'); | ||
var BaseRegression = require('ml-regression-base'); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var BaseRegression__default = /*#__PURE__*/_interopDefaultLegacy(BaseRegression); | ||
class PolynomialRegression extends BaseRegression__default['default'] { | ||
constructor(x, y, degree) { | ||
super(); | ||
if (x === true) { | ||
this.degree = y.degree; | ||
this.powers = y.powers; | ||
this.coefficients = y.coefficients; | ||
} else { | ||
BaseRegression.checkArrayLength(x, y); | ||
regress(this, x, y, degree); | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
} | ||
_predict(x) { | ||
let y = 0; | ||
for (let k = 0; k < this.powers.length; k++) { | ||
y += this.coefficients[k] * Math.pow(x, this.powers[k]); | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.PolynomialRegression = void 0; | ||
const ml_matrix_1 = require("ml-matrix"); | ||
const ml_regression_base_1 = __importStar(require("ml-regression-base")); | ||
class PolynomialRegression extends ml_regression_base_1.default { | ||
/** | ||
* @param x - independent or explanatory variable | ||
* @param y - dependent or response variable | ||
* @param degree - degree of the polynomial regression, or array of powers to be used. When degree is an array, intercept at zero is forced to false/ignored. | ||
* @example `new PolynomialRegression(x, y, 2)`, in this case, you can pass the option `interceptAtZero`, if you need it. | ||
* @example `new PolynomialRegression(x, y, [1, 3, 5])` | ||
* Each of the degrees corresponds to a column, so if you have them switched, just do: | ||
* @example `new PolynomialRegression(x, y, [3, 1, 5])` | ||
* | ||
* @param options.interceptAtZero - force the polynomial regression so that f(0) = 0 | ||
*/ | ||
constructor(x, y, degree, options = {}) { | ||
super(); | ||
// @ts-expect-error internal use only | ||
if (x === true) { | ||
// @ts-expect-error internal use only | ||
this.degree = y.degree; | ||
// @ts-expect-error internal use only | ||
this.powers = y.powers; | ||
// @ts-expect-error internal use only | ||
this.coefficients = y.coefficients; | ||
} | ||
else { | ||
(0, ml_regression_base_1.checkArrayLength)(x, y); | ||
const result = regress(x, y, degree, options); | ||
this.degree = result.degree; | ||
this.powers = result.powers; | ||
this.coefficients = result.coefficients; | ||
} | ||
} | ||
return y; | ||
} | ||
toJSON() { | ||
return { | ||
name: 'polynomialRegression', | ||
degree: this.degree, | ||
powers: this.powers, | ||
coefficients: this.coefficients, | ||
}; | ||
} | ||
toString(precision) { | ||
return this._toFormula(precision, false); | ||
} | ||
toLaTeX(precision) { | ||
return this._toFormula(precision, true); | ||
} | ||
_toFormula(precision, isLaTeX) { | ||
let sup = '^'; | ||
let closeSup = ''; | ||
let times = ' * '; | ||
if (isLaTeX) { | ||
sup = '^{'; | ||
closeSup = '}'; | ||
times = ''; | ||
_predict(x) { | ||
let y = 0; | ||
for (let k = 0; k < this.powers.length; k++) { | ||
y += this.coefficients[k] * Math.pow(x, this.powers[k]); | ||
} | ||
return y; | ||
} | ||
let fn = ''; | ||
let str = ''; | ||
for (let k = 0; k < this.coefficients.length; k++) { | ||
str = ''; | ||
if (this.coefficients[k] !== 0) { | ||
if (this.powers[k] === 0) { | ||
str = BaseRegression.maybeToPrecision(this.coefficients[k], precision); | ||
} else { | ||
if (this.powers[k] === 1) { | ||
str = `${BaseRegression.maybeToPrecision(this.coefficients[k], precision) + | ||
times}x`; | ||
} else { | ||
str = `${BaseRegression.maybeToPrecision(this.coefficients[k], precision) + | ||
times}x${sup}${this.powers[k]}${closeSup}`; | ||
} | ||
toJSON() { | ||
return { | ||
name: 'polynomialRegression', | ||
degree: this.degree, | ||
powers: this.powers, | ||
coefficients: this.coefficients, | ||
}; | ||
} | ||
toString(precision) { | ||
return this._toFormula(precision, false); | ||
} | ||
toLaTeX(precision) { | ||
return this._toFormula(precision, true); | ||
} | ||
_toFormula(precision, isLaTeX) { | ||
let sup = '^'; | ||
let closeSup = ''; | ||
let times = ' * '; | ||
if (isLaTeX) { | ||
sup = '^{'; | ||
closeSup = '}'; | ||
times = ''; | ||
} | ||
if (this.coefficients[k] > 0 && k !== this.coefficients.length - 1) { | ||
str = ` + ${str}`; | ||
} else if (k !== this.coefficients.length - 1) { | ||
str = ` ${str}`; | ||
let fn = ''; | ||
let str = ''; | ||
for (let k = 0; k < this.coefficients.length; k++) { | ||
str = ''; | ||
if (this.coefficients[k] !== 0) { | ||
if (this.powers[k] === 0) { | ||
str = (0, ml_regression_base_1.maybeToPrecision)(this.coefficients[k], precision); | ||
} | ||
else if (this.powers[k] === 1) { | ||
str = `${(0, ml_regression_base_1.maybeToPrecision)(this.coefficients[k], precision) + times}x`; | ||
} | ||
else { | ||
str = `${(0, ml_regression_base_1.maybeToPrecision)(this.coefficients[k], precision) + times}x${sup}${this.powers[k]}${closeSup}`; | ||
} | ||
if (this.coefficients[k] > 0 && k !== this.coefficients.length - 1) { | ||
str = ` + ${str}`; | ||
} | ||
else if (k !== this.coefficients.length - 1) { | ||
str = ` ${str}`; | ||
} | ||
} | ||
fn = str + fn; | ||
} | ||
} | ||
fn = str + fn; | ||
if (fn.startsWith('+')) { | ||
fn = fn.slice(1); | ||
} | ||
return `f(x) = ${fn}`; | ||
} | ||
if (fn.charAt(0) === '+') { | ||
fn = fn.slice(1); | ||
static load(json) { | ||
if (json.name !== 'polynomialRegression') { | ||
throw new TypeError('not a polynomial regression model'); | ||
} | ||
// @ts-expect-error internal use only | ||
return new PolynomialRegression(true, json); | ||
} | ||
return `f(x) = ${fn}`; | ||
} | ||
static load(json) { | ||
if (json.name !== 'polynomialRegression') { | ||
throw new TypeError('not a polynomial regression model'); | ||
} | ||
return new PolynomialRegression(true, json); | ||
} | ||
} | ||
function regress(pr, x, y, degree) { | ||
const n = x.length; | ||
let powers; | ||
if (Array.isArray(degree)) { | ||
powers = degree; | ||
degree = powers.length; | ||
} else { | ||
degree++; | ||
powers = new Array(degree); | ||
for (let k = 0; k < degree; k++) { | ||
powers[k] = k; | ||
exports.PolynomialRegression = PolynomialRegression; | ||
/** | ||
* Perform a polynomial regression on the given data set. | ||
* This is an internal function. | ||
* @param x - independent or explanatory variable | ||
* @param y - dependent or response variable | ||
* @param degree - degree of the polynomial regression | ||
* @param options.interceptAtZero - force the polynomial regression so that $f(0) = 0$ | ||
*/ | ||
function regress(x, y, degree, options = {}) { | ||
const n = x.length; | ||
let { interceptAtZero = false } = options; | ||
let powers = []; | ||
if (Array.isArray(degree)) { | ||
powers = degree; | ||
interceptAtZero = false; //must be false in this case | ||
} | ||
} | ||
const F = new mlMatrix.Matrix(n, degree); | ||
const Y = new mlMatrix.Matrix([y]); | ||
for (let k = 0; k < degree; k++) { | ||
for (let i = 0; i < n; i++) { | ||
if (powers[k] === 0) { | ||
F.set(i, k, 1); | ||
} else { | ||
F.set(i, k, Math.pow(x[i], powers[k])); | ||
} | ||
else if (typeof degree === 'number') { | ||
if (interceptAtZero) { | ||
powers = new Array(degree); | ||
for (let k = 0; k < degree; k++) { | ||
powers[k] = k + 1; | ||
} | ||
} | ||
else { | ||
powers = new Array(degree + 1); | ||
for (let k = 0; k <= degree; k++) { | ||
powers[k] = k; | ||
} | ||
} | ||
} | ||
} | ||
const FT = new mlMatrix.MatrixTransposeView(F); | ||
const A = FT.mmul(F); | ||
const B = FT.mmul(new mlMatrix.MatrixTransposeView(Y)); | ||
pr.degree = degree - 1; | ||
pr.powers = powers; | ||
pr.coefficients = mlMatrix.solve(A, B).to1DArray(); | ||
const nCoefficients = powers.length; //1 per power, in any case. | ||
const F = new ml_matrix_1.Matrix(n, nCoefficients); | ||
const Y = new ml_matrix_1.Matrix([y]); | ||
for (let k = 0; k < nCoefficients; k++) { | ||
for (let i = 0; i < n; i++) { | ||
if (powers[k] === 0) { | ||
F.set(i, k, 1); | ||
} | ||
else { | ||
F.set(i, k, Math.pow(x[i], powers[k])); | ||
} | ||
} | ||
} | ||
const FT = new ml_matrix_1.MatrixTransposeView(F); | ||
const A = FT.mmul(F); | ||
const B = FT.mmul(new ml_matrix_1.MatrixTransposeView(Y)); | ||
return { | ||
coefficients: (0, ml_matrix_1.solve)(A, B).to1DArray(), | ||
degree: Math.max(...powers), | ||
powers, | ||
}; | ||
} | ||
module.exports = PolynomialRegression; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "ml-regression-polynomial", | ||
"version": "2.2.0", | ||
"version": "3.0.0", | ||
"description": "Polynomial Regression", | ||
"main": "lib/index.js", | ||
"module": "src/index.js", | ||
"types": "./lib/index.d.ts", | ||
"main": "./lib/index.js", | ||
"module": "./lib-esm/index.js", | ||
"files": [ | ||
"src", | ||
"lib", | ||
"src" | ||
"lib-esm" | ||
], | ||
"scripts": { | ||
"compile": "rollup -c", | ||
"check-types": "tsc --noEmit", | ||
"clean": "rimraf lib lib-esm", | ||
"eslint": "eslint src", | ||
"eslint-fix": "npm run eslint -- --fix", | ||
"prepublishOnly": "npm run compile", | ||
"test": "npm run test-coverage && npm run eslint", | ||
"test-only": "jest", | ||
"test-coverage": "jest --coverage" | ||
"prepack": "npm run tsc", | ||
"prettier": "prettier --check src", | ||
"prettier-write": "prettier --write src", | ||
"test": "npm run test-only && npm run eslint && npm run prettier && npm run check-types", | ||
"test-only": "vitest run --coverage", | ||
"tsc": "npm run clean && npm run tsc-cjs && npm run tsc-esm", | ||
"tsc-cjs": "tsc --project tsconfig.cjs.json", | ||
"tsc-esm": "tsc --project tsconfig.esm.json" | ||
}, | ||
@@ -31,20 +38,16 @@ "repository": { | ||
"homepage": "https://github.com/mljs/regression-polynomial#readme", | ||
"jest": { | ||
"testEnvironment": "node" | ||
}, | ||
"devDependencies": { | ||
"@babel/plugin-transform-modules-commonjs": "^7.14.5", | ||
"eslint": "^7.28.0", | ||
"eslint-config-cheminfo": "^5.2.4", | ||
"eslint-plugin-import": "^2.23.4", | ||
"eslint-plugin-jest": "^24.3.6", | ||
"eslint-plugin-prettier": "^3.4.0", | ||
"jest": "^27.0.4", | ||
"prettier": "^2.3.1", | ||
"rollup": "^2.51.1" | ||
"@vitest/coverage-v8": "^0.34.5", | ||
"eslint": "^8.50.0", | ||
"eslint-config-cheminfo-typescript": "^12.0.4", | ||
"prettier": "^3.0.3", | ||
"rimraf": "^5.0.5", | ||
"typescript": "^5.2.2", | ||
"vitest": "^0.34.5" | ||
}, | ||
"dependencies": { | ||
"ml-matrix": "^6.8.0", | ||
"ml-regression-base": "^2.1.3" | ||
"cheminfo-types": "^1.7.2", | ||
"ml-matrix": "^6.10.5", | ||
"ml-regression-base": "^3.0.0" | ||
} | ||
} | ||
} |
# regression-polynomial | ||
[![NPM version][npm-image]][npm-url] | ||
[![build status][travis-image]][travis-url] | ||
[![npm download][download-image]][download-url] | ||
[![build status][ci-image]][ci-url] | ||
[![Test coverage][codecov-image]][codecov-url] | ||
@@ -16,6 +17,8 @@ Polynomial Regression. | ||
```js | ||
import PolynomialRegression from 'ml-regression-polynomial'; | ||
import { PolynomialRegression } from 'ml-regression-polynomial'; | ||
const x = [50, 50, 50, 70, 70, 70, 80, 80, 80, 90, 90, 90, 100, 100, 100]; | ||
const y = [3.3, 2.8, 2.9, 2.3, 2.6, 2.1, 2.5, 2.9, 2.4, 3.0, 3.1, 2.8, 3.3, 3.5, 3.0]; | ||
const y = [ | ||
3.3, 2.8, 2.9, 2.3, 2.6, 2.1, 2.5, 2.9, 2.4, 3.0, 3.1, 2.8, 3.3, 3.5, 3.0, | ||
]; | ||
const degree = 5; // setup the maximum degree of the polynomial | ||
@@ -32,2 +35,25 @@ | ||
## Options | ||
An `interceptAtZero` option is available, to force $f(0) = 0$. Also, a "powers array" can be specified. | ||
- Using `interceptAtZero` | ||
```js | ||
const regression = new PolynomialRegression(x, y, degree, { | ||
interceptAtZero: true, | ||
}); | ||
``` | ||
- Using the powers array | ||
```js | ||
const powers = [0, 1, 2, 3, 4, 5]; | ||
const regression = new PolynomialRegression(x, y, powers); | ||
``` | ||
`powers` could also be `[1,2,3,4,5]`or`[1,3,5]` and so on. | ||
For intercepting at zero using an array, skip the zero in the array (the option `interceptAtZero` is ignored in this case.) | ||
## License | ||
@@ -39,5 +65,7 @@ | ||
[npm-url]: https://npmjs.org/package/ml-regression-polynomial | ||
[travis-image]: https://img.shields.io/travis/mljs/regression-polynomial/master.svg?style=flat-square | ||
[travis-url]: https://travis-ci.org/mljs/regression-polynomial | ||
[download-image]: https://img.shields.io/npm/dm/ml-regression-polynomial.svg?style=flat-square | ||
[download-url]: https://npmjs.org/package/ml-regression-polynomial | ||
[codecov-image]: https://img.shields.io/codecov/c/github/mljs/regression-polynomial.svg | ||
[codecov-url]: https://codecov.io/gh/mljs/regression-polynomial | ||
[ci-image]: https://github.com/mljs/regression-polynomial/workflows/Node.js%20CI/badge.svg?branch=main | ||
[ci-url]: https://github.com/mljs/regression-polynomial/actions?query=workflow%3A%22Node.js+CI%22 |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40530
7
13
668
69
3
2
+ Addedcheminfo-types@^1.7.2
+ Addedcheminfo-types@1.8.1(transitive)
+ Addedml-regression-base@3.0.0(transitive)
- Removedml-regression-base@2.1.6(transitive)
Updatedml-matrix@^6.10.5
Updatedml-regression-base@^3.0.0