diff --git a/lib/node_modules/@stdlib/ml/incr/binary-classification/lib/model.js b/lib/node_modules/@stdlib/ml/incr/binary-classification/lib/model.js index 69f543905fd3..84de66a3f841 100644 --- a/lib/node_modules/@stdlib/ml/incr/binary-classification/lib/model.js +++ b/lib/node_modules/@stdlib/ml/incr/binary-classification/lib/model.js @@ -341,8 +341,8 @@ setReadOnly( Model.prototype, '_modifiedHuberLoss', function modifiedHuber( x, y d = y * this._dot( x.data, x.strides[ 0 ], x.offset ); if ( d < -1.0 ) { this._add( x, 4.0*eta*y ); - } else { - this._add( x, eta*( y-(d*y) ) ); + } else if ( d < 1.0 ) { + this._add( x, 2.0*eta*( y-(d*y) ) ); } return this; }); diff --git a/lib/node_modules/@stdlib/ml/incr/binary-classification/test/test.model.js b/lib/node_modules/@stdlib/ml/incr/binary-classification/test/test.model.js index 29a2bfcdb5be..2b336a846e8f 100644 --- a/lib/node_modules/@stdlib/ml/incr/binary-classification/test/test.model.js +++ b/lib/node_modules/@stdlib/ml/incr/binary-classification/test/test.model.js @@ -21,6 +21,8 @@ // MODULES // var tape = require( 'tape' ); +var array = require( '@stdlib/ndarray/array' ); +var Float64Array = require( '@stdlib/array/float64' ); var Model = require( './../lib/model.js' ); @@ -32,4 +34,41 @@ tape( 'main export is a function', function test( t ) { t.end(); }); -// TODO: add tests +tape( 'the function supports modified Huber loss', function test( t ) { + var expected; + var model; + var opts; + var eta; + var x; + + eta = 0.1; + opts = { + 'lambda': 0.0, + 'learningRate': [ 'constant', eta ], + 'loss': 'modifiedHuber', + 'intercept': false + }; + x = array( new Float64Array( [ 1.0 ] ) ); + + // Case 1: `-1 <= y*f(x) < 1` (quadratically smoothed region): + model = new Model( 1, opts ); + model._weights[ 0 ] = 0.3; // eslint-disable-line no-underscore-dangle + model.update( x, 1 ); + expected = 0.3 + ( 2.0*eta*( 1.0-(0.3*1.0) ) ); + t.strictEqual( model._weights[ 0 ], expected, 'returns expected value' ); // eslint-disable-line no-underscore-dangle + + // Case 2: `y*f(x) >= 1`, where the gradient is zero and the weights are unchanged: + model = new Model( 1, opts ); + model._weights[ 0 ] = 2.0; // eslint-disable-line no-underscore-dangle + model.update( x, 1 ); + t.strictEqual( model._weights[ 0 ], 2.0, 'returns expected value' ); // eslint-disable-line no-underscore-dangle + + // Case 3: `y*f(x) < -1`: + model = new Model( 1, opts ); + model._weights[ 0 ] = -2.0; // eslint-disable-line no-underscore-dangle + model.update( x, 1 ); + expected = -2.0 + ( 4.0*eta*1.0 ); + t.strictEqual( model._weights[ 0 ], expected, 'returns expected value' ); // eslint-disable-line no-underscore-dangle + + t.end(); +});