Incrementally perform binary classification using stochastic gradient descent (SGD).
We believe in a future in which the web is a preferred environment for numerical computation. To help realize this future, we’ve built stdlib. stdlib is a standard library, with an emphasis on numerical and scientific computation, written in JavaScript (and C) for execution in browsers and in Node.js.
The library is fully decomposable, being architected in such a way that you can swap out and mix and match APIs and functionality to cater to your exact preferences and use cases.
When you use stdlib, you can be absolutely certain that you are using the most thorough, rigorous, well-written, studied, documented, tested, measured, and high-quality code out there.
To join us in bringing numerical computing to the web, get started by checking us out on GitHub, and please consider financially supporting stdlib. We greatly appreciate your continued support!
[![NPM version][npm-image]][npm-url] [![Build Status][test-image]][test-url] [![Coverage Status][coverage-image]][coverage-url]
Incrementally perform binary classification using [stochastic gradient descent][stochastic-gradient-descent] (SGD).
bash
npm install @stdlib/ml-incr-binary-classification
script
tag without installation and bundlers, use the [ES Module][es-module] available on the [esm
][esm-url] branch (see [README][esm-readme]).deno
][deno-url] branch (see [README][deno-readme] for usage intructions).umd
][umd-url] branch (see [README][umd-readme]).javascript
var incrBinaryClassification = require( '@stdlib/ml-incr-binary-classification' );
function
which incrementally performs binary classification using [stochastic gradient descent][stochastic-gradient-descent].javascript
// Create an accumulator for performing binary classification on 3-dimensional data:
var accumulator = incrBinaryClassification( 3 );
options
:boolean
indicating whether to include an intercept. If true
, an element equal to one is implicitly added to each provided feature vector (note, however, that the model does not perform regularization of the intercept term). If false
, the model assumes that feature vectors are already centered. Default: true
.1.0e-4
.['constant', ...]
: constant learning rate function. To set the learning rate, provide a second array element. By default, when the learn rate function is ‘constant’, the learning rate is set to 0.02
.['basic']
: basic learning rate function according to the formula 10/(10+t)
where t
is the current iteration.['invscaling', ...]
: inverse scaling learning rate function according to the formula eta0/pow(t, power_t)
where eta0
is the initial learning rate and power_t
is the exponent controlling how quickly the learning rate decreases. To set the initial learning rate, provide a second array element. By default, the initial learning rate is 0.02
. To set the exponent, provide a third array element. By default, the exponent is 0.5
.['pegasos']
: [Pegasos][@shalevshwartz:2011a] learning rate function according to the formula 1/(lambda*t)
where t
is the current iteration and lambda
is the regularization parameter.['basic']
.hinge
: hinge loss function. Corresponds to a soft-margin linear Support Vector Machine (SVM), which can handle non-linearly separable data.log
: logistic loss function. Corresponds to Logistic Regression.modifiedHuber
: Huber loss function [variant][@zhang:2004a] for classification.perceptron
: hinge loss function without a margin. Corresponds to the original perceptron by Rosenblatt (1957).squaredHinge
: squared hinge loss function SVM (L2-SVM).'log'
.intercept
option to false
:javascript
var array = require( '@stdlib/ndarray-array' );
// Create a model with the intercept term:
var acc = incrBinaryClassification( 2, {
'intercept': true
});
var coefs = acc( array( [ 1.4, 0.5 ] ), 1 );
// returns <ndarray>
var dim = coefs.length;
// returns 3
// Create a model without the intercept term:
acc = incrBinaryClassification( 2, {
'intercept': false
});
coefs = acc( array( [ 1.4, 0.5 ] ), -1 );
// returns <ndarray>
dim = coefs.length;
// returns 2
x
and response value y
(either +1
or -1
), the accumulator function updates a binary classification model; otherwise, the accumulator function returns the current binary classification model coefficients.javascript
var array = require( '@stdlib/ndarray-array' );
// Create an accumulator:
var acc = incrBinaryClassification( 2 );
// Provide data to the accumulator...
var x = array( [ 1.0, 0.0 ] );
var coefs = acc( x, -1 );
// returns <ndarray>
x.set( 0, 0.0 );
x.set( 1, 1.0 );
coefs = acc( x, 1 );
// returns <ndarray>
x.set( 0, 0.5 );
x.set( 1, 1.0 );
coefs = acc( x, 1 );
// returns <ndarray>
coefs = acc();
// returns <ndarray>
X
.javascript
var array = require( '@stdlib/ndarray-array' );
// Create a model with the intercept term:
var acc = incrBinaryClassification( 2 );
// ...
var label = acc.predict( array( [ 0.5, 2.0 ] ) );
// returns <ndarray>
ndarray
][@stdlib/ndarray/ctor] having shape (..., N)
, where N
is the number of features, the returned [ndarray
][@stdlib/ndarray/ctor] has shape (...)
(i.e., the number of dimensions is reduced by one) and data type float64
. For example, if provided a one-dimensional [ndarray
][@stdlib/ndarray/ctor], the method returns a zero-dimensional [ndarray
][@stdlib/ndarray/ctor] whose only element is the predicted response value.type='label'
). In order to return a prediction probability of a +1
response value given either the logistic (log
) or modified Huber (modifiedHuber
) loss functions, set the second argument to 'probability'
.javascript
var array = require( '@stdlib/ndarray-array' );
// Create a model with the intercept term:
var acc = incrBinaryClassification( 2, {
'loss': 'log'
});
// ...
var phat = acc.predict( array( [ 0.5, 2.0 ] ), 'probability' );
// returns <ndarray>
x
, plus the intercept), set the second argument to 'linear'
.javascript
var array = require( '@stdlib/ndarray-array' );
// Create a model with the intercept term:
var acc = incrBinaryClassification( 2, {
'loss': 'log'
});
// ...
var lp = acc.predict( array( [ 0.5, 2.0 ] ), 'linear' );
// returns <ndarray>
x = [x_0, x_1, ...]
and model coefficients c = [c_0, c_1, ...]
, the linear predictor is equal to (x_0*c_0) + (x_1*c_1) + ... + c_intercept
.[0,1]
or [-1,1]
or to transform each feature into z-scores with zero mean and unit variance. One should keep in mind that the same scaling has to be applied to training data in order to obtain accurate predictions.javascript
var normal = require( '@stdlib/random-base-normal' );
var binomial = require( '@stdlib/random-base-binomial' );
var array = require( '@stdlib/ndarray-array' );
var exp = require( '@stdlib/math-base-special-exp' );
var incrBinaryClassification = require( '@stdlib/ml-incr-binary-classification' );
// Create a new accumulator:
var acc = incrBinaryClassification( 2, {
'intercept': true,
'lambda': 1.0e-3,
'loss': 'log'
});
// Incrementally update the classification model...
var phat;
var x;
var i;
for ( i = 0; i < 10000; i++ ) {
x = array( [ normal( 0.0, 1.0 ), normal( 0.0, 1.0 ) ] );
phat = 1.0 / ( 1.0+exp( -( ( 3.0*x.get(0) ) - ( 2.0*x.get(1) ) + 1.0 ) ) );
acc( x, ( binomial( 1, phat ) ) ? 1.0 : -1.0 );
}
// Retrieve model coefficients:
var coefs = acc();
console.log( 'Feature coefficients: %d, %d', coefs.get( 0 ), coefs.get( 1 ) );
console.log( 'Intercept: %d', coefs.get( 2 ) );
// Predict new observations...
x = array( [ [ 0.9, 0.1 ], [ 0.1, 0.9 ], [ 0.9, 0.9 ] ] );
var out = acc.predict( x );
console.log( 'x = [%d, %d]; label = %d', x.get( 0, 0 ), x.get( 0, 1 ), out.get( 0 ) );
console.log( 'x = [%d, %d]; label = %d', x.get( 1, 0 ), x.get( 1, 1 ), out.get( 1 ) );
console.log( 'x = [%d, %d]; label = %d', x.get( 2, 0 ), x.get( 2, 1 ), out.get( 2 ) );
out = acc.predict( x, 'probability' );
console.log( 'x = [%d, %d]; P(y=1|x) = %d', x.get( 0, 0 ), x.get( 0, 1 ), out.get( 0 ) );
console.log( 'x = [%d, %d]; P(y=1|x) = %d', x.get( 1, 0 ), x.get( 1, 1 ), out.get( 1 ) );
console.log( 'x = [%d, %d]; P(y=1|x) = %d', x.get( 2, 0 ), x.get( 2, 1 ), out.get( 2 ) );
out = acc.predict( x, 'linear' );
console.log( 'x = [%d, %d]; lp = %d', x.get( 0, 0 ), x.get( 0, 1 ), out.get( 0 ) );
console.log( 'x = [%d, %d]; lp = %d', x.get( 1, 0 ), x.get( 1, 1 ), out.get( 1 ) );
console.log( 'x = [%d, %d]; lp = %d', x.get( 2, 0 ), x.get( 2, 1 ), out.get( 2 ) );