wink-helpers
Advanced tools
Comparing version 1.4.0 to 1.5.0
{ | ||
"name": "wink-helpers", | ||
"version": "1.4.0", | ||
"description": "Low level helper functions for Javascript array, object and string", | ||
"version": "1.5.0", | ||
"description": "Functions for cross validation, shuffle, cartesian product and more", | ||
"keywords": [ | ||
@@ -17,3 +17,5 @@ "Array", | ||
"Shuffle", | ||
"Random Shuffle" | ||
"Random Shuffle", | ||
"Cross Validation", | ||
"Machine Learning" | ||
], | ||
@@ -41,8 +43,8 @@ "main": "src/wink-helpers.js", | ||
"chai": "^4.1.2", | ||
"coveralls": "^3.0.1", | ||
"coveralls": "^3.0.2", | ||
"docco": "^0.8.0", | ||
"eslint": "^4.19.1", | ||
"istanbul": "^0.4.5", | ||
"eslint": "^5.0.1", | ||
"istanbul": "^1.1.0-alpha.1", | ||
"jshint": "^2.9.5", | ||
"mocha": "^5.1.1", | ||
"mocha": "^5.2.0", | ||
"mocha-lcov-reporter": "^1.3.0" | ||
@@ -49,0 +51,0 @@ }, |
# wink-helpers | ||
Helper functions for Javascript array, object, and string | ||
Functions for cross validation, shuffle, cartesian product and more | ||
@@ -9,3 +9,3 @@ ### [![Build Status](https://api.travis-ci.org/winkjs/wink-helpers.svg?branch=master)](https://travis-ci.org/winkjs/wink-helpers) [![Coverage Status](https://coveralls.io/repos/github/winkjs/wink-helpers/badge.svg?branch=master)](https://coveralls.io/github/winkjs/wink-helpers?branch=master) [![Inline docs](http://inch-ci.org/github/winkjs/wink-helpers.svg?branch=master)](http://inch-ci.org/github/winkjs/wink-helpers) [![devDependencies Status](https://david-dm.org/winkjs/wink-helpers/dev-status.svg)](https://david-dm.org/winkjs/wink-helpers?type=dev) | ||
Perform commonly needed operations of array, object and string using **`wink-helpers`**. It is a part of [wink](http://winkjs.org/) — a growing family of high quality packages for Statistical Analysis, Natural Language Processing and Machine Learning in NodeJS. | ||
Perform cross validation for machine learning, shuffle and many other operations using **`wink-helpers`**. It is a part of [wink](http://winkjs.org/) — a growing family of high quality packages for Statistical Analysis, Natural Language Processing and Machine Learning in NodeJS. | ||
@@ -139,3 +139,11 @@ | ||
#### cross( classLabels ) | ||
Performs cross validation and generates detailed performance metrics along with the confusion matrix. It is a higher order function that returns an object containing `evaluate()`, `metrics()`, and `reset()` functions. The `classLabels` should be an array containing all the class labels that may be predicted. | ||
The `evaluate()` function accepts two parameters viz. `truth` — the actual label and `guess` — the predicted label. It is typically called for every row of validation dataset. The evaluation may fail if `truth` or `guess` value is not a valid `classLabels`; or if guess is equal to `unknown`. | ||
The `metrics()` returns an object containing macro-averaged `avgPrecision`, `avgRecall`, `avgFMeasure` values along with other details such as label-wise recall/precision/f-measure values and the confusion matrix. A value of `null` is returned if no evaluate() has been called before. | ||
The `reset()` re-initializes the current instance for another round of evaluation; the class labels defined at instance creation time are not touched. | ||
## Need Help? | ||
@@ -142,0 +150,0 @@ If you spot a bug and the same has not yet been reported, raise a new [issue](https://github.com/winkjs/wink-helpers/issues) or consider fixing it and sending a pull request. |
@@ -294,2 +294,178 @@ // wink-helpers | ||
// ### cross validation | ||
/** | ||
* | ||
* Creates an instance of cross validator useful for machine learning tasks. | ||
* | ||
* @param {string[]} classLabels - array containing all the class labels. | ||
* @return {methods} object conatining set of API methods for tasks like evalutaion, | ||
* reset and metrics generation. | ||
*/ | ||
helpers.validate.cross = function ( classLabels ) { | ||
// wink's const for unknown predictions! | ||
const unknown = 'unknown'; | ||
// To ensure that metrics is not computed prior to evaluation. | ||
var evaluated = false; | ||
// The confusion matrix. | ||
var cm; | ||
var precision; | ||
var recall; | ||
var fmeasure; | ||
// The class labels is assigned to this variable. | ||
var labels; | ||
// The length of `labels` array. | ||
var labelCount; | ||
var labelsObj = Object.create( null ); | ||
// Returned! | ||
var methods = Object.create( null ); | ||
/** | ||
* | ||
* Resets the current instance for another round of evaluation; the class | ||
* labels defined at instance creation time are not touched. | ||
* | ||
* @return {undefined} nothing! | ||
*/ | ||
var reset = function ( ) { | ||
evaluated = false; | ||
cm = Object.create( null ); | ||
precision = Object.create( null ); | ||
recall = Object.create( null ); | ||
fmeasure = Object.create( null ); | ||
// Initialize confusion matrix and metrics. | ||
for ( let i = 0; i < labelCount; i += 1 ) { | ||
const row = labels[ i ]; | ||
labelsObj[ row ] = true; | ||
cm[ row ] = Object.create( null ); | ||
precision[ row ] = 0; | ||
recall[ row ] = 0; | ||
fmeasure[ row ] = 0; | ||
for ( let j = 0; j < labelCount; j += 1 ) { | ||
const col = labels[ j ]; | ||
cm[ row ][ col ] = 0; | ||
} | ||
} | ||
}; // reset() | ||
/** | ||
* | ||
* Creates an instance of cross validator useful for machine learning tasks. | ||
* | ||
* @param {string} truth - the actual class label. | ||
* @param {string} guess - the predicted class label. | ||
* @return {boolean} returns true if the evaluation is successful. The evaluation | ||
* may fail if `truth` or `guess` is not in the array `classLabels` provided at | ||
* instance creation time; or if guess is equal to `unknown`. | ||
*/ | ||
var evaluate = function ( truth, guess ) { | ||
// If prediction failed then return false! | ||
if ( guess === unknown || !labelsObj[ truth ] || !labelsObj[ guess ] ) return false; | ||
// Update confusion matrix. | ||
if ( guess === truth ) { | ||
cm[ truth ][ guess ] += 1; | ||
} else { | ||
cm[ guess ][ truth ] += 1; | ||
} | ||
evaluated = true; | ||
return true; | ||
}; // evaluate() | ||
/** | ||
* | ||
* It computes a detailed metrics consisting of macro-averaged precision, | ||
* recall and f-measure along with their label-wise values and the confusion | ||
* matrix. | ||
* | ||
* @return {object} object containing macro-averaged `avgPrecision`, `avgRecall`, | ||
* `avgFMeasure` values along with other details such as label-wise values | ||
* and the confusion matrix. A value of `null` is returned if no evaluate() | ||
* has been called before. | ||
*/ | ||
var metrics = function ( ) { | ||
if ( !evaluated ) return null; | ||
// Numerators for every label; they are same for precision & recall both. | ||
var n = Object.create( null ); | ||
// Only denominators differs for precision & recall | ||
var pd = Object.create( null ); | ||
var rd = Object.create( null ); | ||
// `row` and `col` of confusion matrix. | ||
var col, row; | ||
var i, j; | ||
// Macro average values for metrics. | ||
var avgPrecision = 0; | ||
var avgRecall = 0; | ||
var avgFMeasure = 0; | ||
// Compute label-wise numerators & denominators! | ||
for ( i = 0; i < labelCount; i += 1 ) { | ||
row = labels[ i ]; | ||
for ( j = 0; j < labelCount; j += 1 ) { | ||
col = labels[ j ]; | ||
if ( row === col ) { | ||
n[ row ] = cm[ row ][ col ]; | ||
} | ||
pd[ row ] = cm[ row ][ col ] + ( pd[ row ] || 0 ); | ||
rd[ row ] = cm[ col ][ row ] + ( rd[ row ] || 0 ); | ||
} | ||
} | ||
// Ready to compute metrics. | ||
for ( i = 0; i < labelCount; i += 1 ) { | ||
row = labels[ i ]; | ||
precision[ row ] = +( n[ row ] / pd[ row ] ).toFixed( 4 ); | ||
// NaN can occur if a label has not been encountered. | ||
if ( isNaN( precision[ row ] ) ) precision[ row ] = 0; | ||
recall[ row ] = +( n[ row ] / rd[ row ] ).toFixed( 4 ); | ||
if ( isNaN( recall[ row ] ) ) recall[ row ] = 0; | ||
fmeasure[ row ] = +( 2 * precision[ row ] * recall[ row ] / ( precision[ row ] + recall[ row ] ) ).toFixed( 4 ); | ||
if ( isNaN( fmeasure[ row ] ) ) fmeasure[ row ] = 0; | ||
} | ||
// Compute thier averages, note they will be macro avegages. | ||
for ( i = 0; i < labelCount; i += 1 ) { | ||
avgPrecision += ( precision[ labels[ i ] ] / labelCount ); | ||
avgRecall += ( recall[ labels[ i ] ] / labelCount ); | ||
avgFMeasure += ( fmeasure[ labels[ i ] ] / labelCount ); | ||
} | ||
// Return metrics. | ||
return ( | ||
{ | ||
// Macro-averaged metrics. | ||
avgPrecision: +avgPrecision.toFixed( 4 ), | ||
avgRecall: +avgRecall.toFixed( 4 ), | ||
avgFMeasure: +avgFMeasure.toFixed( 4 ), | ||
details: { | ||
// Confusion Matrix. | ||
confusionMatrix: cm, | ||
// Label wise metrics details, from those averages were computed. | ||
precision: precision, | ||
recall: recall, | ||
fmeasure: fmeasure | ||
} | ||
} | ||
); | ||
}; // metrics() | ||
if ( !helpers.validate.isArray( classLabels ) ) { | ||
throw Error( 'cross validate: class labels must be an array.' ); | ||
} | ||
if ( classLabels.length < 2 ) { | ||
throw Error( 'cross validate: at least 2 class labels are required.' ); | ||
} | ||
labels = classLabels; | ||
labelCount = labels.length; | ||
reset(); | ||
methods.reset = reset; | ||
methods.evaluate = evaluate; | ||
methods.metrics = metrics; | ||
return methods; | ||
}; // cross() | ||
// ### Object Helpers | ||
@@ -296,0 +472,0 @@ |
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
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
57279
438
156