class HashTable { constructor(options = {}) { if (options instanceof HashTable) { this.table = options.table.slice(); this.values = options.values.slice(); this.state = options.state.slice(); this.minLoadFactor = options.minLoadFactor; this.maxLoadFactor = options.maxLoadFactor; this.distinct = options.distinct; this.freeEntries = options.freeEntries; this.lowWaterMark = options.lowWaterMark; this.highWaterMark = options.maxLoadFactor; return; } const initialCapacity = options.initialCapacity === undefined ? defaultInitialCapacity : options.initialCapacity; if (initialCapacity < 0) { throw new RangeError(`initial capacity must not be less than zero: ${initialCapacity}`); } const minLoadFactor = options.minLoadFactor === undefined ? defaultMinLoadFactor : options.minLoadFactor; const maxLoadFactor = options.maxLoadFactor === undefined ? defaultMaxLoadFactor : options.maxLoadFactor; if (minLoadFactor < 0 || minLoadFactor >= 1) { throw new RangeError(`invalid minLoadFactor: ${minLoadFactor}`); } if (maxLoadFactor <= 0 || maxLoadFactor >= 1) { throw new RangeError(`invalid maxLoadFactor: ${maxLoadFactor}`); } if (minLoadFactor >= maxLoadFactor) { throw new RangeError(`minLoadFactor (${minLoadFactor}) must be smaller than maxLoadFactor (${maxLoadFactor})`); } let capacity = initialCapacity; // User wants to put at least capacity elements. We need to choose the size based on the maxLoadFactor to // avoid the need to rehash before this capacity is reached. // actualCapacity * maxLoadFactor >= capacity capacity = (capacity / maxLoadFactor) | 0; capacity = nextPrime(capacity); if (capacity === 0) capacity = 1; this.table = newArray(capacity, 0); this.values = newArray(capacity, 0); this.state = newArray(capacity, 0); this.minLoadFactor = minLoadFactor; if (capacity === largestPrime) { this.maxLoadFactor = 1; } else { this.maxLoadFactor = maxLoadFactor; } this.distinct = 0; this.freeEntries = capacity; this.lowWaterMark = 0; this.highWaterMark = chooseHighWaterMark(capacity, this.maxLoadFactor); } clone() { return new HashTable(this); } get size() { return this.distinct; } get(key) { const i = this.indexOfKey(key); if (i < 0) return 0; return this.values[i]; } set(key, value) { let i = this.indexOfInsertion(key); if (i < 0) { i = -i - 1; this.values[i] = value; return false; } if (this.distinct > this.highWaterMark) { const newCapacity = chooseGrowCapacity(this.distinct + 1, this.minLoadFactor, this.maxLoadFactor); this.rehash(newCapacity); return this.set(key, value); } this.table[i] = key; this.values[i] = value; if (this.state[i] === FREE) this.freeEntries--; this.state[i] = FULL; this.distinct++; if (this.freeEntries < 1) { const newCapacity = chooseGrowCapacity(this.distinct + 1, this.minLoadFactor, this.maxLoadFactor); this.rehash(newCapacity); } return true; } remove(key, noRehash) { const i = this.indexOfKey(key); if (i < 0) return false; this.state[i] = REMOVED; this.distinct--; if (!noRehash) this.maybeShrinkCapacity(); return true; } delete(key, noRehash) { const i = this.indexOfKey(key); if (i < 0) return false; this.state[i] = FREE; this.distinct--; if (!noRehash) this.maybeShrinkCapacity(); return true; } maybeShrinkCapacity() { if (this.distinct < this.lowWater ...
n/a
class SparseMatrix { constructor(rows, columns, options = {}) { if (rows instanceof SparseMatrix) { // clone const other = rows; this._init(other.rows, other.columns, other.elements.clone(), other.threshold); return; } if (Array.isArray(rows)) { const matrix = rows; rows = matrix.length; options = columns || {}; columns = matrix[0].length; this._init(rows, columns, new HashTable(options), options.threshold); for (var i = 0; i < rows; i++) { for (var j = 0; j < columns; j++) { var value = matrix[i][j]; if (this.threshold && Math.abs(value) < this.threshold) value = 0; if (value !== 0) { this.elements.set(i * columns + j, matrix[i][j]); } } } } else { this._init(rows, columns, new HashTable(options), options.threshold); } } _init(rows, columns, elements, threshold) { this.rows = rows; this.columns = columns; this.elements = elements; this.threshold = threshold || 0; } static eye(rows = 1, columns = rows) { const min = Math.min(rows, columns); const matrix = new SparseMatrix(rows, columns, {initialCapacity: min}); for (var i = 0; i < min; i++) { matrix.set(i, i, 1); } return matrix; } clone() { return new SparseMatrix(this); } to2DArray() { const copy = new Array(this.rows); for (var i = 0; i < this.rows; i++) { copy[i] = new Array(this.columns); for (var j = 0; j < this.columns; j++) { copy[i][j] = this.get(i, j); } } return copy; } isSquare() { return this.rows === this.columns; } isSymmetric() { if (!this.isSquare()) return false; var symmetric = true; this.forEachNonZero((i, j, v) => { if (this.get(j, i) !== v) { symmetric = false; return false; } return v; }); return symmetric; } get cardinality() { return this.elements.size; } get size() { return this.rows * this.columns; } get(row, column) { return this.elements.get(row * this.columns + column); } set(row, column, value) { if (this.threshold && Math.abs(value) < this.threshold) value = 0; if (value === 0) { this.elements.remove(row * this.columns + column); } else { this.elements.set(row * this.columns + column, value); } return this; } mmul(other) { if (this.columns !== other.rows) console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.'); const m = this.rows; const p = other.columns; const result = new SparseMatrix(m, p); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { if (j === k) { result.set(i, l, result.get(i, l) + v1 * v2); } return v2; }); return v1; }); return result; } kroneckerProduct(other) { const m = this.rows; const n = this.columns; const p = other.rows; const q = other.columns; const result = new SparseMatrix(m * p, n * q, { initialCapacity: this.cardinality * other.cardinality }); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { result.set(p * i + k, q * j + l, v1 * v2); return v2; }); return v1; }); return result; } forEachNonZero(callback) { this.elements.forEachPair((key, value) => { const i = (k ...
n/a
class Matrix extends abstractMatrix(Array) {
constructor(nRows, nColumns) {
var i;
if (arguments.length === 1 && typeof nRows === 'number') {
return new Array(nRows);
}
if (Matrix.isMatrix(nRows)) {
return nRows.clone();
} else if (Number.isInteger(nRows) && nRows > 0) { // Create an empty matrix
super(nRows);
if (Number.isInteger(nColumns) && nColumns > 0) {
for (i = 0; i < nRows; i++) {
this[i] = new Array(nColumns);
}
} else {
throw new TypeError('nColumns must be a positive integer');
}
} else if (Array.isArray(nRows)) { // Copy the values from the 2D array
const matrix = nRows;
nRows = matrix.length;
nColumns = matrix[0].length;
if (typeof nColumns !== 'number' || nColumns === 0) {
throw new TypeError('Data must be a 2D array with at least one element');
}
super(nRows);
for (i = 0; i < nRows; i++) {
if (matrix[i].length !== nColumns) {
throw new RangeError('Inconsistent array dimensions');
}
this[i] = [].concat(matrix[i]);
}
} else {
throw new TypeError('First argument must be a positive number or an array');
}
this.rows = nRows;
this.columns = nColumns;
return this;
}
set(rowIndex, columnIndex, value) {
this[rowIndex][columnIndex] = value;
return this;
}
get(rowIndex, columnIndex) {
return this[rowIndex][columnIndex];
}
/**
* Creates an exact and independent copy of the matrix
* @return {Matrix}
*/
clone() {
var newMatrix = new this.constructor[Symbol.species](this.rows, this.columns);
for (var row = 0; row < this.rows; row++) {
for (var column = 0; column < this.columns; column++) {
newMatrix.set(row, column, this.get(row, column));
}
}
return newMatrix;
}
/**
* Removes a row from the given index
* @param {number} index - Row index
* @return {Matrix} this
*/
removeRow(index) {
util.checkRowIndex(this, index);
if (this.rows === 1) {
throw new RangeError('A matrix cannot have less than one row');
}
this.splice(index, 1);
this.rows -= 1;
return this;
}
/**
* Adds a row at the given index
* @param {number} [index = this.rows] - Row index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addRow(index, array) {
if (array === undefined) {
array = index;
index = this.rows;
}
util.checkRowIndex(this, index, true);
array = util.checkRowVector(this, array, true);
this.splice(index, 0, array);
this.rows += 1;
return this;
}
/**
* Removes a column from the given index
* @param {number} index - Column index
* @return {Matrix} this
*/
removeColumn(index) {
util.checkColumnIndex(this, index);
if (this.columns === 1) {
throw new RangeError('A matrix cannot have less than one column');
}
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 1);
}
this.columns -= 1;
return this;
}
/**
* Adds a column at the given index
* @param {number} [index = this.columns] - Column index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addColumn(index, array) {
if (typeof array === 'undefined') {
array = index;
index = this.columns;
}
util.checkColumnIndex(this, index, true);
array = util.checkColumnVector(this, array);
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 0, array[i]);
} ...
n/a
function padArray(data, options) { options = extend({}, defaultOptions, options); if (Array.isArray(data)) { if (Array.isArray(data[0])) return matrixCase(data, options); else return arrayCase(data, options); } else throw new TypeError('data should be an array'); }
n/a
function KNN(reload, model) { if(reload) { this.kdtree = model.kdtree; this.k = model.k; this.classes = model.classes; } }
n/a
function NaiveBayes(reload, model) { if(reload) { this.means = model.means; this.calculateProbabilities = model.calculateProbabilities; } }
n/a
class PLS {
constructor(X, Y) {
if (X === true) {
const model = Y;
this.meanX = model.meanX;
this.stdDevX = model.stdDevX;
this.meanY = model.meanY;
this.stdDevY = model.stdDevY;
this.PBQ = Matrix.checkMatrix(model.PBQ);
this.R2X = model.R2X;
} else {
if (X.length !== Y.length)
throw new RangeError('The number of X rows must be equal to the number of Y rows');
const resultX = Utils.featureNormalize(X);
this.X = resultX.result;
this.meanX = resultX.means;
this.stdDevX = resultX.std;
const resultY = Utils.featureNormalize(Y);
this.Y = resultY.result;
this.meanY = resultY.means;
this.stdDevY = resultY.std;
}
}
/**
* Fits the model with the given data and predictions, in this function is calculated the
* following outputs:
*
* T - Score matrix of X
* P - Loading matrix of X
* U - Score matrix of Y
* Q - Loading matrix of Y
* B - Matrix of regression coefficient
* W - Weight matrix of X
*
* @param {Object} options - recieves the latentVectors and the tolerance of each step of the PLS
*/
train(options) {
if(options === undefined) options = {};
var latentVectors = options.latentVectors;
if (latentVectors === undefined) {
latentVectors = Math.min(this.X.length - 1, this.X[0].length);
}
var tolerance = options.tolerance;
if (tolerance === undefined) {
tolerance = 1e-5;
}
var X = this.X;
var Y = this.Y;
var rx = X.rows;
var cx = X.columns;
var ry = Y.rows;
var cy = Y.columns;
var ssqXcal = X.clone().mul(X).sum(); // for the r²
var sumOfSquaresY = Y.clone().mul(Y).sum();
var n = latentVectors; //Math.max(cx, cy); // components of the pls
var T = Matrix.zeros(rx, n);
var P = Matrix.zeros(cx, n);
var U = Matrix.zeros(ry, n);
var Q = Matrix.zeros(cy, n);
var B = Matrix.zeros(n, n);
var W = P.clone();
var k = 0;
while(Utils.norm(Y) > tolerance && k < n) {
var transposeX = X.transpose();
var transposeY = Y.transpose();
var tIndex = maxSumColIndex(X.clone().mulM(X));
var uIndex = maxSumColIndex(Y.clone().mulM(Y));
var t1 = X.getColumnVector(tIndex);
var u = Y.getColumnVector(uIndex);
var t = Matrix.zeros(rx, 1);
while(Utils.norm(t1.clone().sub(t)) > tolerance) {
var w = transposeX.mmul(u);
w.div(Utils.norm(w));
t = t1;
t1 = X.mmul(w);
var q = transposeY.mmul(t1);
q.div(Utils.norm(q));
u = Y.mmul(q);
}
t = t1;
var num = transposeX.mmul(t);
var den = (t.transpose().mmul(t))[0][0];
var p = num.div(den);
var pnorm = Utils.norm(p);
p.div(pnorm);
t.mul(pnorm);
w.mul(pnorm);
num = u.transpose().mmul(t);
den = (t.transpose().mmul(t))[0][0];
var b = (num.div(den))[0][0];
X.sub(t.mmul(p.transpose()));
Y.sub(t.clone().mul(b).mmul(q.transpose()));
T.setColumn(k, t);
P.setColumn(k, p);
U.setColumn(k, u);
Q.setColumn(k, q);
W.setColumn(k, w);
B[k][k] = b;
k++;
}
k--;
T = T.subMatrix(0, T.rows - 1, 0, k);
P = P.subMatrix(0, P.rows - 1, 0, k);
U = U.subMatrix(0, U.rows - 1, 0, k);
Q = Q.subMatrix(0, Q.rows - 1, 0, k);
W = W.subMatrix(0, W.rows - 1, 0, k);
B = B.subMatrix(0, k, 0, k);
// TODO: review of R2Y
//this.R2Y = t.transpose().mmul(t).mul(q[k][0]*q[k][0]).divS(ssqYcal)[0][0]; ...
n/a
function SVM(options) { this.options = Object.assign({}, defaultOptions, options); this.kernel = new Kernel(this.options.kernel, this.options.kernelOptions); this.b = 0; }
n/a
binarySearch = function (haystack, needle, comparator, low, high) {
var mid, cmp;
if(low === undefined)
low = 0;
else {
low = low|0;
if(low < 0 || low >= haystack.length)
throw new RangeError("invalid lower bound");
}
if(high === undefined)
high = haystack.length - 1;
else {
high = high|0;
if(high < low || high >= haystack.length)
throw new RangeError("invalid upper bound");
}
while(low <= high) {
/* Note that "(low + high) >>> 1" may overflow, and results in a typecast
* to double (which gives the wrong results). */
mid = low + (high - low >> 1);
cmp = +comparator(haystack[mid], needle, mid, haystack);
/* Too low. */
if(cmp < 0.0)
low = mid + 1;
/* Too high. */
else if(cmp > 0.0)
high = mid - 1;
/* Key found. */
else
return mid;
}
/* Key not found. */
return ~low;
}
n/a
function SOM(x, y, options, reload) { this.x = x; this.y = y; options = options || {}; this.options = {}; for (var i in defaultOptions) { if (options.hasOwnProperty(i)) { this.options[i] = options[i]; } else { this.options[i] = defaultOptions[i]; } } if (typeof this.options.fields === 'number') { this.numWeights = this.options.fields; } else if (Array.isArray(this.options.fields)) { this.numWeights = this.options.fields.length; var converters = getConverters(this.options.fields); this.extractor = converters.extractor; this.creator = converters.creator; } else { throw new Error('Invalid fields definition'); } if (this.options.gridType === 'rect') { this.nodeType = NodeSquare; this.gridDim = { x: x, y: y }; } else { this.nodeType = NodeHexagonal; var hx = this.x - Math.floor(this.y / 2); this.gridDim = { x: hx, y: this.y, z: -(0 - hx - this.y) }; } this.torus = this.options.torus; this.distanceMethod = this.torus ? 'getDistanceTorus' : 'getDistance'; this.distance = this.options.distance; this.maxDistance = getMaxDistance(this.distance, this.numWeights); if (reload === true) { // For model loading this.done = true; return; } if (!(x > 0 && y > 0)) { throw new Error('x and y must be positive'); } this.times = { findBMU: 0, adjust: 0 }; this.randomizer = this.options.randomizer; this.iterationCount = 0; this.iterations = this.options.iterations; this.startLearningRate = this.learningRate = this.options.learningRate; this.mapRadius = Math.floor(Math.max(x, y) / 2); this.algorithmMethod = this.options.method; this._initNodes(); this.done = false; }
n/a
function SNV(data) { var mean = Stat.mean(data); var std = Stat.standardDeviation(data); var result = data.slice(); for (var i = 0; i < data.length; i++) { result[i] = (result[i] - mean) / std; } return result; }
n/a
function applyDotProduct(firstVector, secondVector) { var largestVector, smallestVector; if(firstVector.length <= secondVector.length) { smallestVector = firstVector; largestVector = secondVector; } else { smallestVector = secondVector; largestVector = firstVector; } var difference = largestVector.length - smallestVector.length + 1; var dotProductApplied = new Array(difference); for (var i = 0; i < difference; ++i) { var sum = 0; for (var j = 0; j < smallestVector.length; ++j) { sum += smallestVector[j] * largestVector[i + j]; } dotProductApplied[i] = sum; } return dotProductApplied; }
n/a
function coordArrayToCoordMatrix(array, dimensions) { if(array.length % dimensions !== 0) { throw new RangeError('Dimensions number must be accordance with the size of the array.'); } var coordinatesArray = new Array(dimensions); var points = array.length / dimensions; for (var i = 0; i < coordinatesArray.length; i++) { coordinatesArray[i] = new Array(points); } for(i = 0; i < array.length; i += dimensions) { for(var j = 0; j < dimensions; ++j) { var currentPoint = Math.floor(i / dimensions); coordinatesArray[j][currentPoint] = array[i + j]; } } return coordinatesArray; }
n/a
function coordArrayToPoints(array, dimensions) { if(array.length % dimensions !== 0) { throw new RangeError('Dimensions number must be accordance with the size of the array.'); } var length = array.length / dimensions; var pointsArr = new Array(length); var k = 0; for(var i = 0; i < array.length; i += dimensions) { var point = new Array(dimensions); for(var j = 0; j < dimensions; ++j) { point[j] = array[i + j]; } pointsArr[k] = point; k++; } return pointsArr; }
n/a
function coordMatrixToCoordArray(coordMatrix) { var coodinatesArray = new Array(coordMatrix.length * coordMatrix[0].length); var k = 0; for(var i = 0; i < coordMatrix[0].length; ++i) { for(var j = 0; j < coordMatrix.length; ++j) { coodinatesArray[k] = coordMatrix[j][i]; ++k; } } return coodinatesArray; }
n/a
function transpose(matrix) { var resultMatrix = new Array(matrix[0].length); for(var i = 0; i < resultMatrix.length; ++i) { resultMatrix[i] = new Array(matrix.length); } for (i = 0; i < matrix.length; ++i) { for(var j = 0; j < matrix[0].length; ++j) { resultMatrix[j][i] = matrix[i][j]; } } return resultMatrix; }
n/a
function getEquallySpacedData(x, y, options) { if (x.length>1 && x[0]>x[1]) { x=x.slice().reverse(); y=y.slice().reverse(); } var xLength = x.length; if(xLength !== y.length) throw new RangeError("the x and y vector doesn't have the same size."); if (options === undefined) options = {}; var from = options.from === undefined ? x[0] : options.from if (isNaN(from) || !isFinite(from)) { throw new RangeError("'From' value must be a number"); } var to = options.to === undefined ? x[x.length - 1] : options.to; if (isNaN(to) || !isFinite(to)) { throw new RangeError("'To' value must be a number"); } var reverse = from > to; if(reverse) { var temp = from; from = to; to = temp; } var numberOfPoints = options.numberOfPoints === undefined ? 100 : options.numberOfPoints; if (isNaN(numberOfPoints) || !isFinite(numberOfPoints)) { throw new RangeError("'Number of points' value must be a number"); } if(numberOfPoints < 1) throw new RangeError("the number of point must be higher than 1"); var algorithm = options.variant === "slot" ? "slot" : "smooth"; // default value: smooth var output = algorithm === "slot" ? getEquallySpacedSlot(x, y, from, to, numberOfPoints) : getEquallySpacedSmooth(x, y, from , to, numberOfPoints); return reverse ? output.reverse() : output; }
n/a
function pointsToCoordArray(points) { var coodinatesArray = new Array(points.length * points[0].length); var k = 0; for(var i = 0; i < points.length; ++i) { for(var j = 0; j < points[0].length; ++j) { coodinatesArray[k] = points[i][j]; ++k; } } return coodinatesArray; }
n/a
function transpose(matrix) { var resultMatrix = new Array(matrix[0].length); for(var i = 0; i < resultMatrix.length; ++i) { resultMatrix[i] = new Array(matrix.length); } for (i = 0; i < matrix.length; ++i) { for(var j = 0; j < matrix[0].length; ++j) { resultMatrix[j][i] = matrix[i][j]; } } return resultMatrix; }
n/a
function scale(input, options){ var y; if(options.inPlace){ y = input; } else{ y = new Array(input.length); } const max = options.max; const min = options.min; if(typeof max === "number"){ if(typeof min === "number"){ var minMax = Stat.minMax(input); var factor = (max - min)/(minMax.max-minMax.min); for(var i=0;i< y.length;i++){ y[i]=(input[i]-minMax.min)*factor+min; } } else{ var currentMin = Stat.max(input); var factor = max/currentMin; for(var i=0;i< y.length;i++){ y[i] = input[i]*factor; } } } else{ if(typeof min === "number"){ var currentMin = Stat.min(input); var factor = min/currentMin; for(var i=0;i< y.length;i++){ y[i] = input[i]*factor; } } } return y; }
n/a
function and(arr1, arr2) { var ans = new Array(arr1.length); for (var i = 0; i < arr1.length; i++) ans[i] = arr1[i] & arr2[i]; return ans; }
n/a
function count(arr) { var c = 0; for (var i = 0; i < arr.length; i++) { c += eightBits[arr[i] & 0xff] + eightBits[(arr[i] >> 8) & 0xff] + eightBits[(arr[i] >> 16) & 0xff] + eightBits[(arr[i] >> 24) & 0xff]; } return c; }
n/a
function getBit(arr, n) { var index = n >> 5; // Same as Math.floor(n/32) var mask = 1 << (31 - n % 32); return Boolean(arr[index] & mask); }
n/a
function not(arr) { var ans = new Array(arr.length); for (var i = 0; i < ans.length; i++) ans[i] = ~arr[i]; return ans; }
n/a
function or(arr1, arr2) { var ans = new Array(arr1.length); for (var i = 0; i < arr1.length; i++) ans[i] = arr1[i] | arr2[i]; return ans; }
n/a
function parseBinaryString(str) { var len = str.length / 32; var ans = new Array(len); for (var i = 0; i < len; i++) { ans[i] = parseInt(str.substr(i*32, 32), 2) | 0; } return ans; }
n/a
function parseHexString(str) { var len = str.length / 8; var ans = new Array(len); for (var i = 0; i < len; i++) { ans[i] = parseInt(str.substr(i*8, 8), 16) | 0; } return ans; }
n/a
function setBit(arr, n, val) { var index = n >> 5; // Same as Math.floor(n/32) var mask = 1 << (31 - n % 32); if (val) arr[index] = mask | arr[index]; else arr[index] = ~mask & arr[index]; return arr; }
n/a
function toBinaryString(arr) { var str = ''; for (var i = 0; i < arr.length; i++) { var obj = (arr[i] >>> 0).toString(2); str += '00000000000000000000000000000000'.substr(obj.length) + obj; } return str; }
n/a
function toDebug(arr) { var binary = toBinaryString(arr); var str = ''; for (var i = 0; i < arr.length; i++) { str += '0000'.substr((i * 32).toString(16).length) + (i * 32).toString(16) + ':'; for (var j = 0; j < 32; j += 4) { str += ' ' + binary.substr(i * 32 + j, 4); } if (i < arr.length - 1) str += '\n'; } return str }
n/a
function toHexString(arr) { var str = ''; for (var i = 0; i < arr.length; i++) { var obj = (arr[i] >>> 0).toString(16); str += '00000000'.substr(obj.length) + obj; } return str; }
n/a
function xor(arr1, arr2) { var ans = new Array(arr1.length); for (var i = 0; i < arr1.length; i++) ans[i] = arr1[i] ^ arr2[i]; return ans; }
n/a
function kmeans(data, K, options) { options = Object.assign({}, defaultOptions, options); if (K <= 0 || K > data.length || !Number.isInteger(K)) { throw new Error('K should be a positive integer bigger than the number of points'); } var centers; if (Array.isArray(options.initialization)) { if (options.initialization.length !== K) { throw new Error('The initial centers should have the same length as K'); } else { centers = options.initialization; } } else { switch (options.initialization) { case 'random': centers = init.random(data, K); break; case 'mostDistant': centers = init.mostDistant(data, K, utils.calculateDistanceMatrix(data, options.distanceFunction)); break; default: throw new Error('Unknown initialization method: "' + options.initialization + '"'); } } // infinite loop until convergence if (options.maxIterations === 0) { options.maxIterations = Number.MAX_VALUE; } var clusterID = new Array(data.length); if (options.withIterations) { return kmeansGenerator(centers, data, clusterID, K, options); } else { var converged = false; var stepNumber = 0; var stepResult; while (!converged && (stepNumber < options.maxIterations)) { stepResult = step(centers, data, clusterID, K, options, ++stepNumber); converged = stepResult.converged; centers = stepResult.centroids; } return stepResult.computeInformation(data); } }
n/a
function agnes(data, options) { options = Object.assign({}, defaultOptions, options); var len = data.length; var distance = data;//If source if (!options.isDistanceMatrix) { distance = distanceMatrix(data, options.disFunc); } // allows to use a string or a given function if (typeof options.kind === 'string') { switch (options.kind) { case 'single': options.kind = simpleLink; break; case 'complete': options.kind = completeLink; break; case 'average': options.kind = averageLink; break; case 'centroid': options.kind = centroidLink; break; case 'ward': options.kind = wardLink; break; default: throw new RangeError('Unknown kind of similarity'); } } else if (typeof options.kind !== 'function') { throw new TypeError('Undefined kind of similarity'); } var list = new Array(len); for (var i = 0; i < distance.length; i++) { list[i] = new ClusterLeaf(i); } var min = 10e5, d = {}, dis = 0; while (list.length > 1) { // calculates the minimum distance d = {}; min = 10e5; for (var j = 0; j < list.length; j++) { for (var k = j + 1; k < list.length; k++) { var fdistance, sdistance; if (list[j] instanceof ClusterLeaf) { fdistance = [list[j].index]; } else { fdistance = new Array(list[j].index.length); for (var e = 0; e < fdistance.length; e++) { fdistance[e] = list[j].index[e].index; } } if (list[k] instanceof ClusterLeaf) { sdistance = [list[k].index]; } else { sdistance = new Array(list[k].index.length); for (var f = 0; f < sdistance.length; f++) { sdistance[f] = list[k].index[f].index; } } dis = options.kind(fdistance, sdistance, distance).toFixed(4); if (dis in d) { d[dis].push([list[j], list[k]]); } else { d[dis] = [[list[j], list[k]]]; } min = Math.min(dis, min); } } // cluster dots var dmin = d[min.toFixed(4)]; var clustered = new Array(dmin.length); var aux, count = 0; while (dmin.length > 0) { aux = dmin.shift(); for (var q = 0; q < dmin.length; q++) { var int = dmin[q].filter(function (n) { //noinspection JSReferencingMutableVariableFromClosure return aux.indexOf(n) !== -1; }); if (int.length > 0) { var diff = dmin[q].filter(function (n) { //noinspection JSReferencingMutableVariableFromClosure return aux.indexOf(n) === -1; }); aux = aux.concat(diff); dmin.splice(q--, 1); } } clustered[count++] = aux; } clustered.length = count; for (var ii = 0; ii < clustered.length; ii++) { var obj = new Cluster(); obj.children = clustered[ii].concat(); obj.distance = min; obj.index = new Array(len); var indCount = 0; for (var jj = 0; jj < clustered[ii].length; jj++) { if (clustered[ii][jj] instanceof ClusterLeaf) { obj.index[indCount++] = clustered[ii][jj]; } else { indCount += clustered[ii][jj].index.length; obj.index = clustered[ii][jj].index.concat(obj.index); } ...
n/a
function diana(data, options) { options = Object.assign({}, defaultOptions, options); if (typeof options.kind === 'string') { switch (options.kind) { case 'single': options.kind = simpleLink; break; case 'complete': options.kind = completeLink; break; case 'average': options.kind = averageLink; break; case 'centroid': options.kind = centroidLink; break; case 'ward': options.kind = wardLink; break; default: throw new RangeError('Unknown kind of similarity'); } } else if (typeof options.kind !== 'function') { throw new TypeError('Undefined kind of similarity'); } var tree = new Cluster(); tree.children = new Array(data.length); tree.index = new Array(data.length); for (var ind = 0; ind < data.length; ind++) { tree.children[ind] = new ClusterLeaf(ind); tree.index[ind] = new ClusterLeaf(ind); } tree.distance = intrDist(tree.index, data, options.dist); var m, M, clId, dist, rebel; var list = [tree]; while (list.length > 0) { M = 0; clId = 0; for (var i = 0; i < list.length; i++) { m = 0; for (var j = 0; j < list[i].length; j++) { for (var l = (j + 1); l < list[i].length; l++) { m = Math.max(options.dist(data[list[i].index[j].index], data[list[i].index[l].index]), m); } } if (m > M) { M = m; clId = i; } } M = 0; if (list[clId].index.length === 2) { list[clId].children = [list[clId].index[0], list[clId].index[1]]; list[clId].distance = options.dist(data[list[clId].index[0].index], data[list[clId].index[1].index]); } else if (list[clId].index.length === 3) { list[clId].children = [list[clId].index[0], list[clId].index[1], list[clId].index[2]]; var d = [ options.dist(data[list[clId].index[0].index], data[list[clId].index[1].index]), options.dist(data[list[clId].index[1].index], data[list[clId].index[2].index]) ]; list[clId].distance = (d[0] + d[1]) / 2; } else { var C = new Cluster(); var sG = new Cluster(); var splitting = [new Array(list[clId].index.length), []]; for (var spl = 0; spl < splitting[0].length; spl++) { splitting[0][spl] = spl; } for (var ii = 0; ii < splitting[0].length; ii++) { dist = 0; for (var jj = 0; jj < splitting[0].length; jj++) { if (ii !== jj) { dist += options.dist(data[list[clId].index[splitting[0][jj]].index], data[list[clId].index[splitting[0][ ii]].index]); } } dist /= (splitting[0].length - 1); if (dist > M) { M = dist; rebel = ii; } } splitting[1] = [rebel]; splitting[0].splice(rebel, 1); dist = diff(splitting, data, options.dist); while (dist.d > 0) { splitting[1].push(splitting[0][dist.p]); splitting[0].splice(dist.p, 1); dist = diff(splitting, data, options.dist); } var fData = new Array(splitting[0].length); C.index = new Array(splitting[0].length); for (var e = 0; e < fData.length; e++) { fData[e] = data[list[clId].index[splitting[0][e]].index]; C.index[e] = list[clId].index[splitting[0][e]]; C.children[e] = list[clId].index[splitting[0][e]]; } var sData = new Array(splitting[1].length); sG.index = new Array(splitting[1].lengt ...
n/a
function distanceMatrix(data, distanceFn) { const length = data.length; let result = Array.from({length}).map(() => Array.from({length})); // Compute upper distance matrix for (let i = 0; i < length; i++) { for (let j = 0; j <= i; j++) { result[i][j] = distanceFn(data[i], data[j]); } } // Copy to lower distance matrix for (let i = 0; i < length; i++) { for (let j = i + 1; j < length; j++) { result[i][j] = result[j][i]; } } return result; }
n/a
class Kernel { constructor(type, options) { this.kernelType = type; if (type === 'linear') return; if (typeof type === 'string') { type = type.toLowerCase(); var KernelConstructor = kernelType[type]; if (KernelConstructor) { this.kernelFunction = new KernelConstructor(options); } else { throw new Error('unsupported kernel type: ' + type); } } else if (typeof type === 'object' && typeof type.compute === 'function') { this.kernelFunction = type; } else { throw new TypeError('first argument must be a valid kernel type or instance'); } } compute(inputs, landmarks) { if (landmarks === undefined) { landmarks = inputs; } if (this.kernelType === 'linear') { var matrix = new Matrix(inputs); return matrix.mmul(new Matrix(landmarks).transposeView()); } const kernelMatrix = new Matrix(inputs.length, landmarks.length); var i, j; if (inputs === landmarks) { // fast path, matrix is symmetric for (i = 0; i < inputs.length; i++) { for (j = i; j < inputs.length; j++) { kernelMatrix[i][j] = kernelMatrix[j][i] = this.kernelFunction.compute(inputs[i], inputs[j]); } } } else { for (i = 0; i < inputs.length; i++) { for (j = 0; j < landmarks.length; j++) { kernelMatrix[i][j] = this.kernelFunction.compute(inputs[i], landmarks[j]); } } } return kernelMatrix; } }
n/a
class Matrix extends abstractMatrix(Array) {
constructor(nRows, nColumns) {
var i;
if (arguments.length === 1 && typeof nRows === 'number') {
return new Array(nRows);
}
if (Matrix.isMatrix(nRows)) {
return nRows.clone();
} else if (Number.isInteger(nRows) && nRows > 0) { // Create an empty matrix
super(nRows);
if (Number.isInteger(nColumns) && nColumns > 0) {
for (i = 0; i < nRows; i++) {
this[i] = new Array(nColumns);
}
} else {
throw new TypeError('nColumns must be a positive integer');
}
} else if (Array.isArray(nRows)) { // Copy the values from the 2D array
const matrix = nRows;
nRows = matrix.length;
nColumns = matrix[0].length;
if (typeof nColumns !== 'number' || nColumns === 0) {
throw new TypeError('Data must be a 2D array with at least one element');
}
super(nRows);
for (i = 0; i < nRows; i++) {
if (matrix[i].length !== nColumns) {
throw new RangeError('Inconsistent array dimensions');
}
this[i] = [].concat(matrix[i]);
}
} else {
throw new TypeError('First argument must be a positive number or an array');
}
this.rows = nRows;
this.columns = nColumns;
return this;
}
set(rowIndex, columnIndex, value) {
this[rowIndex][columnIndex] = value;
return this;
}
get(rowIndex, columnIndex) {
return this[rowIndex][columnIndex];
}
/**
* Creates an exact and independent copy of the matrix
* @return {Matrix}
*/
clone() {
var newMatrix = new this.constructor[Symbol.species](this.rows, this.columns);
for (var row = 0; row < this.rows; row++) {
for (var column = 0; column < this.columns; column++) {
newMatrix.set(row, column, this.get(row, column));
}
}
return newMatrix;
}
/**
* Removes a row from the given index
* @param {number} index - Row index
* @return {Matrix} this
*/
removeRow(index) {
util.checkRowIndex(this, index);
if (this.rows === 1) {
throw new RangeError('A matrix cannot have less than one row');
}
this.splice(index, 1);
this.rows -= 1;
return this;
}
/**
* Adds a row at the given index
* @param {number} [index = this.rows] - Row index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addRow(index, array) {
if (array === undefined) {
array = index;
index = this.rows;
}
util.checkRowIndex(this, index, true);
array = util.checkRowVector(this, array, true);
this.splice(index, 0, array);
this.rows += 1;
return this;
}
/**
* Removes a column from the given index
* @param {number} index - Column index
* @return {Matrix} this
*/
removeColumn(index) {
util.checkColumnIndex(this, index);
if (this.columns === 1) {
throw new RangeError('A matrix cannot have less than one column');
}
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 1);
}
this.columns -= 1;
return this;
}
/**
* Adds a column at the given index
* @param {number} [index = this.columns] - Column index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addColumn(index, array) {
if (typeof array === 'undefined') {
array = index;
index = this.columns;
}
util.checkColumnIndex(this, index, true);
array = util.checkColumnVector(this, array);
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 0, array[i]);
} ...
n/a
function SavitzkyGolay(data, h, options) { options = extend({}, defaultOptions, options); if ((options.windowSize % 2 === 0) || (options.windowSize < 5) || !(Number.isInteger(options.windowSize))) throw new RangeError('Invalid window size (should be odd and at least 5 integer number)'); if ((options.derivative < 0) || !(Number.isInteger(options.derivative))) throw new RangeError('Derivative should be a positive integer'); if ((options.polynomial < 1) || !(Number.isInteger(options.polynomial))) throw new RangeError('Polynomial should be a positive integer'); var C, norm; var step = Math.floor(options.windowSize / 2); if (options.pad === 'pre') { data = padArray(data, {size: step, value: options.padValue}); } var ans = new Array(data.length - 2*step); if ((options.windowSize === 5) && (options.polynomial === 2) && ((options.derivative === 1) || (options.derivative === 2))) { if (options.derivative === 1) { C = [-2,-1,0,1,2]; norm = 10; } else { C = [2, -1, -2, -1, 2]; norm = 7; } } else { var J = Matrix.ones(options.windowSize, options.polynomial + 1); var inic = -(options.windowSize - 1) / 2; for (var i = 0; i < J.length; i++) { for (var j = 0; j < J[i].length; j++) { if ((inic + 1 !== 0) || (j !== 0)) J[i][j] = Math.pow((inic + i), j); } } var Jtranspose = J.transposeView(); var Jinv = (Jtranspose.mmul(J)).inverse(); C = Jinv.mmul(Jtranspose); C = C[options.derivative]; norm = 1; } var det = norm * Math.pow(h, options.derivative); for (var k = step; k < (data.length - step); k++) { var d = 0; for (var l = 0; l < C.length; l++) d += C[l] * data[l + k - step] / det; ans[k - step] = d; } if (options.pad === 'post') { ans = padArray(ans, {size: step, value: options.padValue}); } return ans; }
n/a
function SavitzkyGolay(data, h, options) { options = extend({}, defaultOptions, options); if ((options.windowSize % 2 === 0) || (options.windowSize < 5) || !(Number.isInteger(options.windowSize))) throw new RangeError('Invalid window size (should be odd and at least 5 integer number)') if (options.windowSize>data.length) throw new RangeError('Window size is higher than the data length '+options.windowSize+">"+data.length); if ((options.derivative < 0) || !(Number.isInteger(options.derivative))) throw new RangeError('Derivative should be a positive integer'); if ((options.polynomial < 1) || !(Number.isInteger(options.polynomial))) throw new RangeError('Polynomial should be a positive integer'); if (options.polynomial >= 6) console.warn('You should not use polynomial grade higher than 5 if you are' + ' not sure that your data arises from such a model. Possible polynomial oscillation problems'); var windowSize = options.windowSize; var half = Math.floor(windowSize/2); var np = data.length; var ans = new Array(np); var weights = fullWeights(windowSize,options.polynomial,options.derivative); var hs = 0; var constantH = true; if( Object.prototype.toString.call( h ) === '[object Array]' ) { constantH = false; } else{ hs = Math.pow(h, options.derivative); } //console.log("Constant h: "+constantH); //For the borders for(var i=0;i<half;i++){ var wg1=weights[half-i-1]; var wg2=weights[half+i+1]; var d1 = 0,d2=0; for (var l = 0; l < windowSize; l++){ d1 += wg1[l] * data[l]; d2 += wg2[l] * data[np-windowSize+l-1]; } if(constantH){ ans[half-i-1] = d1/hs; ans[np-half+i] = d2/hs; } else{ hs = getHs(h,half-i-1,half, options.derivative); ans[half-i-1] = d1/hs; hs = getHs(h,np-half+i,half, options.derivative); ans[np-half+i] = d2/hs; } } //For the internal points var wg = weights[half]; for(var i=windowSize;i<np+1;i++){ var d = 0; for (var l = 0; l < windowSize; l++) d += wg[l] * data[l+i-windowSize]; if(!constantH) hs = getHs(h,i-half-1,half, options.derivative); ans[i-half-1] = d/hs; } return ans; }
n/a
class SparseMatrix { constructor(rows, columns, options = {}) { if (rows instanceof SparseMatrix) { // clone const other = rows; this._init(other.rows, other.columns, other.elements.clone(), other.threshold); return; } if (Array.isArray(rows)) { const matrix = rows; rows = matrix.length; options = columns || {}; columns = matrix[0].length; this._init(rows, columns, new HashTable(options), options.threshold); for (var i = 0; i < rows; i++) { for (var j = 0; j < columns; j++) { var value = matrix[i][j]; if (this.threshold && Math.abs(value) < this.threshold) value = 0; if (value !== 0) { this.elements.set(i * columns + j, matrix[i][j]); } } } } else { this._init(rows, columns, new HashTable(options), options.threshold); } } _init(rows, columns, elements, threshold) { this.rows = rows; this.columns = columns; this.elements = elements; this.threshold = threshold || 0; } static eye(rows = 1, columns = rows) { const min = Math.min(rows, columns); const matrix = new SparseMatrix(rows, columns, {initialCapacity: min}); for (var i = 0; i < min; i++) { matrix.set(i, i, 1); } return matrix; } clone() { return new SparseMatrix(this); } to2DArray() { const copy = new Array(this.rows); for (var i = 0; i < this.rows; i++) { copy[i] = new Array(this.columns); for (var j = 0; j < this.columns; j++) { copy[i][j] = this.get(i, j); } } return copy; } isSquare() { return this.rows === this.columns; } isSymmetric() { if (!this.isSquare()) return false; var symmetric = true; this.forEachNonZero((i, j, v) => { if (this.get(j, i) !== v) { symmetric = false; return false; } return v; }); return symmetric; } get cardinality() { return this.elements.size; } get size() { return this.rows * this.columns; } get(row, column) { return this.elements.get(row * this.columns + column); } set(row, column, value) { if (this.threshold && Math.abs(value) < this.threshold) value = 0; if (value === 0) { this.elements.remove(row * this.columns + column); } else { this.elements.set(row * this.columns + column, value); } return this; } mmul(other) { if (this.columns !== other.rows) console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.'); const m = this.rows; const p = other.columns; const result = new SparseMatrix(m, p); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { if (j === k) { result.set(i, l, result.get(i, l) + v1 * v2); } return v2; }); return v1; }); return result; } kroneckerProduct(other) { const m = this.rows; const n = this.columns; const p = other.rows; const q = other.columns; const result = new SparseMatrix(m * p, n * q, { initialCapacity: this.cardinality * other.cardinality }); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { result.set(p * i + k, q * j + l, v1 * v2); return v2; }); return v1; }); return result; } forEachNonZero(callback) { this.elements.forEachPair((key, value) => { const i = (k ...
n/a
function optimizeGaussianSum(xy, group, opts){ var xy2 = parseData(xy); if(xy2===null||xy2[0].rows<3){ return null; //Cannot run an optimization with less than 3 points } var t = xy2[0]; var y_data = xy2[1]; var maxY = xy2[2]; var nbPoints = t.rows,i; var weight = new Matrix(nbPoints,1);//[nbPoints / math.sqrt(y_data.dot(y_data))]; var k = nbPoints / math.sqrt(y_data.dot(y_data)); for(i=0;i<nbPoints;i++){ weight[i][0]=k;///(y_data[i][0]); //weight[i][0]=k*(2-y_data[i][0]); } var opts=Object.create(opts || [ 3, 100, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 2 ]); //var opts=[ 3, 100, 1e-5, 1e-6, 1e-6, 1e-6, 1e-6, 11, 9, 1 ]; var consts = [ ];// optional vector of constants var nL = group.length; var p_init = new Matrix(nL*3,1); var p_min = new Matrix(nL*3,1); var p_max = new Matrix(nL*3,1); var dx = new Matrix(nL*3,1); var dt = Math.abs(t[0][0]-t[1][0]); for( i=0;i<nL;i++){ p_init[i][0] = group[i].x; p_init[i+nL][0] = group[i].y/maxY; p_init[i+2*nL][0] = group[i].width; p_min[i][0] = group[i].x-dt; p_min[i+nL][0] = group[i].y*0.8/maxY; p_min[i+2*nL][0] = group[i].width/2; p_max[i][0] = group[i].x+dt; p_max[i+nL][0] = group[i].y*1.2/maxY; p_max[i+2*nL][0] = group[i].width*2; dx[i][0] = -dt/1000; dx[i+nL][0] = -1e-3; dx[i+2*nL][0] = -dt/1000; } //console.log(t); var p_fit = LM.optimize(sumOfLorentzians,p_init,t,y_data,weight,dx,p_min,p_max,consts,opts); p_fit = p_fit.p; //Put back the result in the correct format var result = new Array(nL); for( i=0;i<nL;i++){ result[i]=[p_fit[i],[p_fit[i+nL][0]*maxY],p_fit[i+2*nL]]; } return result; }
n/a
function optimizeGaussianTrain(xy, group, opts){ var xy2 = parseData(xy); //console.log(xy2[0].rows); if(xy2===null||xy2[0].rows<3){ return null; //Cannot run an optimization with less than 3 points } var t = xy2[0]; var y_data = xy2[1]; var maxY = xy2[2]; var currentIndex = 0; var nbPoints = t.length; var nextX; var tI, yI, maxY; var result=[], current; for(var i=0; i<group.length;i++){ nextX = group[i].x-group[i].width*1.5; //console.log(group[i]); while(t[currentIndex++]<nextX&¤tIndex<nbPoints); nextX = group[i].x+group[i].width*1.5; tI = []; yI = []; while(t[currentIndex]<=nextX&¤tIndex<nbPoints){ tI.push(t[currentIndex][0]); yI.push(y_data[currentIndex][0]*maxY); currentIndex++; } current=optimizeSingleGaussian([tI, yI], group[i], opts); if(current){ result.push({"x":current[0][0],"y":current[1][0],"width":current[2][0],"opt":true}); } else{ result.push({"x":group[i].x,"y":group[i].y,"width":group[i].width,"opt":false}); } } return result; }
n/a
function optimizeLorentzianSum(xy, group, opts){ var xy2 = parseData(xy); if(xy2===null||xy2[0].rows<3){ return null; //Cannot run an optimization with less than 3 points } var t = xy2[0]; var y_data = xy2[1]; var maxY = xy2[2]; var nbPoints = t.rows, i; var weight = [nbPoints / math.sqrt(y_data.dot(y_data))]; var opts=Object.create(opts || [ 3, 100, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 1 ]); var consts = [ ];// optional vector of constants var nL = group.length; var p_init = new Matrix(nL*3,1); var p_min = new Matrix(nL*3,1); var p_max = new Matrix(nL*3,1); var dx = new Matrix(nL*3,1); var dt = Math.abs(t[0][0]-t[1][0]); for( i=0;i<nL;i++){ p_init[i][0] = group[i].x; p_init[i+nL][0] = 1; p_init[i+2*nL][0] = group[i].width; p_min[i][0] = group[i].x-dt;//-group[i].width/4; p_min[i+nL][0] = 0; p_min[i+2*nL][0] = group[i].width/4; p_max[i][0] = group[i].x+dt;//+group[i].width/4; p_max[i+nL][0] = 1.5; p_max[i+2*nL][0] = group[i].width*4; dx[i][0] = -dt/1000; dx[i+nL][0] = -1e-3; dx[i+2*nL][0] = -dt/1000; } var dx = -Math.abs(t[0][0]-t[1][0])/10000; var p_fit = LM.optimize(sumOfLorentzians, p_init, t, y_data, weight, dx, p_min, p_max, consts, opts); p_fit=p_fit.p; //Put back the result in the correct format var result = new Array(nL); for( i=0;i<nL;i++){ result[i]=[p_fit[i],[p_fit[i+nL][0]*maxY],p_fit[i+2*nL]]; } return result; }
n/a
function optimizeLorentzianTrain(xy, group, opts){ var xy2 = parseData(xy); //console.log(xy2[0].rows); if(xy2===null||xy2[0].rows<3){ return null; //Cannot run an optimization with less than 3 points } var t = xy2[0]; var y_data = xy2[1]; var maxY = xy2[2]; var currentIndex = 0; var nbPoints = t.length; var nextX; var tI, yI, maxY; var result=[], current; for(var i=0; i<group.length;i++){ nextX = group[i].x-group[i].width*1.5; //console.log(group[i]); while(t[currentIndex++]<nextX&¤tIndex<nbPoints); nextX = group[i].x+group[i].width*1.5; tI = []; yI = []; while(t[currentIndex]<=nextX&¤tIndex<nbPoints){ tI.push(t[currentIndex][0]); yI.push(y_data[currentIndex][0]*maxY); currentIndex++; } current=optimizeSingleLorentzian([tI, yI], group[i], opts); if(current){ result.push({"x":current[0][0],"y":current[1][0],"width":current[2][0],"opt":true}); } else{ result.push({"x":group[i].x,"y":group[i].y,"width":group[i].width,"opt":false}); } } return result; }
n/a
function optimizeSingleGaussian(xy, peak, opts) { opts = opts || {}; var xy2 = parseData(xy, opts.percentage||0); if(xy2===null||xy2[0].rows<3){ return null; //Cannot run an optimization with less than 3 points } var t = xy2[0]; var y_data = xy2[1]; var maxY = xy2[2]; var nbPoints = t.rows, i; var weight = [nbPoints / Math.sqrt(y_data.dot(y_data))]; var opts=Object.create(opts.LMOptions || [ 3, 100, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 1 ]); //var opts = [ 3, 100, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 1 ]; var consts = [ ]; // optional vector of constants var dt = Math.abs(t[0][0]-t[1][0]); var dx = new Matrix([[-dt/10000],[-1e-3],[-dt/10000]]);//-Math.abs(t[0][0]-t[1][0])/100; var dx = new Matrix([[-Math.abs(t[0][0]-t[1][0])/1000],[-1e-3],[-peak.width/1000]]); var p_init = new Matrix([[peak.x],[1],[peak.width]]); var p_min = new Matrix([[peak.x-dt],[0.75],[peak.width/4]]); var p_max = new Matrix([[peak.x+dt],[1.25],[peak.width*4]]); //var p_min = new Matrix([[peak.x-peak.width/4],[0.75],[peak.width/3]]); //var p_max = new Matrix([[peak.x+peak.width/4],[1.25],[peak.width*3]]); var p_fit = LM.optimize(singleGaussian,p_init,t,y_data,weight,dx,p_min,p_max,consts,opts); p_fit = p_fit.p; return [p_fit[0],[p_fit[1][0]*maxY],p_fit[2]]; }
n/a
function optimizeSingleLorentzian(xy, peak, opts) { opts = opts || {}; var xy2 = parseData(xy, opts.percentage||0); if(xy2===null||xy2[0].rows<3){ return null; //Cannot run an optimization with less than 3 points } var t = xy2[0]; var y_data = xy2[1]; var maxY = xy2[2]; var nbPoints = t.rows, i; var weight = [nbPoints / Math.sqrt(y_data.dot(y_data))]; var opts=Object.create(opts.LMOptions || [ 3, 100, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 1 ]); //var opts = [ 3, 100, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 1 ]; var consts = [ ]; var dt = Math.abs(t[0][0]-t[1][0]);// optional vector of constants var dx = new Matrix([[-dt/10000],[-1e-3],[-dt/10000]]);//-Math.abs(t[0][0]-t[1][0])/100; var p_init = new Matrix([[peak.x],[1],[peak.width]]); var p_min = new Matrix([[peak.x-dt],[0.75],[peak.width/4]]); var p_max = new Matrix([[peak.x+dt],[1.25],[peak.width*4]]); var p_fit = LM.optimize(singleLorentzian,p_init,t,y_data,weight,dx,p_min,p_max,consts,opts); p_fit = p_fit.p; return [p_fit[0],[p_fit[1][0]*maxY],p_fit[2]]; }
n/a
function singleGaussian(t, p, c){ var factor2 = p[2][0]*p[2][0]/2; var rows = t.rows; var result = new Matrix(t.rows, t.columns); for(var i=0;i<rows;i++){ result[i][0]=p[1][0]*Math.exp(-(t[i][0]-p[0][0])*(t[i][0]-p[0][0])/factor2); } return result; }
n/a
function singleLorentzian(t, p, c){ var factor = p[1][0]*Math.pow(p[2][0]/2,2); var rows = t.rows; var result = new Matrix(t.rows, t.columns); for(var i=0;i<rows;i++){ result[i][0]=factor/(Math.pow(t[i][0]-p[0][0],2)+Math.pow(p[2][0]/2,2)); } return result; }
n/a
class Matrix extends abstractMatrix(Array) {
constructor(nRows, nColumns) {
var i;
if (arguments.length === 1 && typeof nRows === 'number') {
return new Array(nRows);
}
if (Matrix.isMatrix(nRows)) {
return nRows.clone();
} else if (Number.isInteger(nRows) && nRows > 0) { // Create an empty matrix
super(nRows);
if (Number.isInteger(nColumns) && nColumns > 0) {
for (i = 0; i < nRows; i++) {
this[i] = new Array(nColumns);
}
} else {
throw new TypeError('nColumns must be a positive integer');
}
} else if (Array.isArray(nRows)) { // Copy the values from the 2D array
const matrix = nRows;
nRows = matrix.length;
nColumns = matrix[0].length;
if (typeof nColumns !== 'number' || nColumns === 0) {
throw new TypeError('Data must be a 2D array with at least one element');
}
super(nRows);
for (i = 0; i < nRows; i++) {
if (matrix[i].length !== nColumns) {
throw new RangeError('Inconsistent array dimensions');
}
this[i] = [].concat(matrix[i]);
}
} else {
throw new TypeError('First argument must be a positive number or an array');
}
this.rows = nRows;
this.columns = nColumns;
return this;
}
set(rowIndex, columnIndex, value) {
this[rowIndex][columnIndex] = value;
return this;
}
get(rowIndex, columnIndex) {
return this[rowIndex][columnIndex];
}
/**
* Creates an exact and independent copy of the matrix
* @return {Matrix}
*/
clone() {
var newMatrix = new this.constructor[Symbol.species](this.rows, this.columns);
for (var row = 0; row < this.rows; row++) {
for (var column = 0; column < this.columns; column++) {
newMatrix.set(row, column, this.get(row, column));
}
}
return newMatrix;
}
/**
* Removes a row from the given index
* @param {number} index - Row index
* @return {Matrix} this
*/
removeRow(index) {
util.checkRowIndex(this, index);
if (this.rows === 1) {
throw new RangeError('A matrix cannot have less than one row');
}
this.splice(index, 1);
this.rows -= 1;
return this;
}
/**
* Adds a row at the given index
* @param {number} [index = this.rows] - Row index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addRow(index, array) {
if (array === undefined) {
array = index;
index = this.rows;
}
util.checkRowIndex(this, index, true);
array = util.checkRowVector(this, array, true);
this.splice(index, 0, array);
this.rows += 1;
return this;
}
/**
* Removes a column from the given index
* @param {number} index - Column index
* @return {Matrix} this
*/
removeColumn(index) {
util.checkColumnIndex(this, index);
if (this.columns === 1) {
throw new RangeError('A matrix cannot have less than one column');
}
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 1);
}
this.columns -= 1;
return this;
}
/**
* Adds a column at the given index
* @param {number} [index = this.columns] - Column index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addColumn(index, array) {
if (typeof array === 'undefined') {
array = index;
index = this.columns;
}
util.checkColumnIndex(this, index, true);
array = util.checkColumnVector(this, array);
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 0, array[i]);
} ...
n/a
lm_Broyden_J = function (p_old, y_old, J, p, y){ // J = lm_Broyden_J(p_old,y_old,J,p,y) // carry out a rank-1 update to the Jacobian matrix using Broyden's equation //---------- INPUT VARIABLES ------- // p_old = previous set of parameters // y_old = model evaluation at previous set of parameters, y_hat(t;p_old) // J = current version of the Jacobian matrix // p = current set of parameters // y = model evaluation at current set of parameters, y_hat(t;p) //---------- OUTPUT VARIABLES ------- // J = rank-1 update to Jacobian Matrix J(i,j)=dy(i)/dp(j) i=1:n; j=1:m //console.log(p+" X "+ p_old) var h = math.subtract(p, p_old); //console.log("hhh "+h); var h_t = math.transpose(h); h_t.div(math.multiply(h_t,h)); //console.log(h_t); //J = J + ( y - y_old - J*h )*h' / (h'*h); // Broyden rank-1 update eq'n J = math.add(J, math.multiply(math.subtract(y, math.add(y_old,math.multiply(J,h))),h_t)); return J; // endfunction # ---------------------------------------------- LM_Broyden_J }
n/a
lm_FD_J = function (func, t, p, y, dp, c) { // J = lm_FD_J(func,t,p,y,{dp},{c}) // // partial derivatives (Jacobian) dy/dp for use with lm.m // computed via Finite Differences // Requires n or 2n function evaluations, n = number of nonzero values of dp // -------- INPUT VARIABLES --------- // func = function of independent variables, 't', and parameters, 'p', // returning the simulated model: y_hat = func(t,p,c) // t = m-vector of independent variables (used as arg to func) // p = n-vector of current parameter values // y = func(t,p,c) n-vector initialised by user before each call to lm_FD_J // dp = fractional increment of p for numerical derivatives // dp(j)>0 central differences calculated // dp(j)<0 one sided differences calculated // dp(j)=0 sets corresponding partials to zero; i.e. holds p(j) fixed // Default: 0.001; // c = optional vector of constants passed to y_hat = func(t,p,c) //---------- OUTPUT VARIABLES ------- // J = Jacobian Matrix J(i,j)=dy(i)/dp(j) i=1:n; j=1:m // Henri Gavin, Dept. Civil & Environ. Engineering, Duke Univ. November 2005 // modified from: ftp://fly.cnuce.cnr.it/pub/software/octave/leasqr/ // Press, et al., Numerical Recipes, Cambridge Univ. Press, 1992, Chapter 15. var m = y.length; // number of data points var n = p.length; // number of parameters dp = dp || math.multiply( Matrix.ones(n, 1), 0.001); var ps = p.clone();//JSON.parse(JSON.stringify(p)); //var ps = $.extend(true, [], p); var J = new Matrix(m,n), del =new Array(n); // initialize Jacobian to Zero for (var j = 0;j < n; j++) { //console.log(j+" "+dp[j]+" "+p[j]+" "+ps[j]+" "+del[j]); del[j] = dp[j]*(1+Math.abs(p[j][0])); // parameter perturbation p[j] = [ps[j][0]+del[j]]; // perturb parameter p(j) //console.log(j+" "+dp[j]+" "+p[j]+" "+ps[j]+" "+del[j]); if (del[j] != 0){ y1 = func(t, p, c); //func_calls = func_calls + 1; if (dp[j][0] < 0) { // backwards difference //J(:,j) = math.dotDivide(math.subtract(y1, y),del[j]);//. / del[j]; //console.log(del[j]); //console.log(y); var column = math.dotDivide(math.subtract(y1, y),del[j]); for(var k=0;k< m;k++){ J[k][j]=column[k][0]; } //console.log(column); } else{ p[j][0] = ps[j][0] - del[j]; //J(:,j) = (y1 - feval(func, t, p, c)). / (2. * del[j]); var column = math.dotDivide(math.subtract(y1,func(t,p,c)),2*del[j]); for(var k=0;k< m;k++){ J[k][j]=column[k][0]; } } // central difference, additional func call } p[j] = ps[j]; // restore p(j) } //console.log("lm_FD_J: "+ JSON.stringify(J)); return J; }
n/a
lm_matx = function (func, t, p_old, y_old, dX2, J, p, y_dat, weight_sq, dp, c, iteration){ // [JtWJ,JtWdy,Chi_sq,y_hat,J] = this.lm_matx(func,t,p_old,y_old,dX2,J,p,y_dat,weight_sq,{da},{c}) // // Evaluate the linearized fitting matrix, JtWJ, and vector JtWdy, // and calculate the Chi-squared error function, Chi_sq // Used by Levenberg-Marquard algorithm, lm.m // -------- INPUT VARIABLES --------- // func = function ofpn independent variables, p, and m parameters, p, // returning the simulated model: y_hat = func(t,p,c) // t = m-vectors or matrix of independent variables (used as arg to func) // p_old = n-vector of previous parameter values // y_old = m-vector of previous model ... y_old = y_hat(t;p_old); // dX2 = previous change in Chi-squared criteria // J = m-by-n Jacobian of model, y_hat, with respect to parameters, p // p = n-vector of current parameter values // y_dat = n-vector of data to be fit by func(t,p,c) // weight_sq = square of the weighting vector for least squares fit ... // inverse of the standard measurement errors // dp = fractional increment of 'p' for numerical derivatives // dp(j)>0 central differences calculated // dp(j)<0 one sided differences calculated // dp(j)=0 sets corresponding partials to zero; i.e. holds p(j) fixed // Default: 0.001; // c = optional vector of constants passed to y_hat = func(t,p,c) //---------- OUTPUT VARIABLES ------- // JtWJ = linearized Hessian matrix (inverse of covariance matrix) // JtWdy = linearized fitting vector // Chi_sq = Chi-squared criteria: weighted sum of the squared residuals WSSR // y_hat = model evaluated with parameters 'p' // J = m-by-n Jacobian of model, y_hat, with respect to parameters, p // Henri Gavin, Dept. Civil & Environ. Engineering, Duke Univ. November 2005 // modified from: ftp://fly.cnuce.cnr.it/pub/software/octave/leasqr/ // Press, et al., Numerical Recipes, Cambridge Univ. Press, 1992, Chapter 15. var Npnt = y_dat.length; // number of data points var Npar = p.length; // number of parameters dp = dp || 0.001; //var JtWJ = new Matrix.zeros(Npar); //var JtWdy = new Matrix.zeros(Npar,1); var y_hat = func(t,p,c); // evaluate model using parameters 'p' //func_calls = func_calls + 1; //console.log(J); if ( (iteration%(2*Npar))==0 || dX2 > 0 ) { //console.log("Par"); J = this.lm_FD_J(func, t, p, y_hat, dp, c); // finite difference } else{ //console.log("ImPar"); J = this.lm_Broyden_J(p_old, y_old, J, p, y_hat); // rank-1 update } //console.log(y_dat); //console.log(y_hat); var delta_y = math.subtract(y_dat, y_hat); // residual error between model and data //console.log(delta_y[0][0]); //console.log(delta_y.rows+" "+delta_y.columns+" "+JSON.stringify(weight_sq)); //var Chi_sq = delta_y' * ( delta_y .* weight_sq ); // Chi-squared error criteria var Chi_sq = math.multiply(math.transpose(delta_y),math.dotMultiply(delta_y,weight_sq)); //JtWJ = J' * ( J .* ( weight_sq * ones(1,Npar) ) ); var Jt = math.transpose(J); //console.log(weight_sq); var JtWJ = math.multiply(Jt, math.dotMultiply(J,math.multiply(weight_sq, Matrix.ones(1,Npar)))); //JtWdy = J' * ( weight_sq .* delta_y ); var JtWdy = math.multiply(Jt, math.dotMultiply(weight_sq,delta_y)); return {JtWJ:JtWJ,JtWdy:JtWdy,Chi_sq:Chi_sq,y_hat:y_hat,J:J}; // endfunction # ------------------------------------------------------ LM_MATX }
n/a
optimize = function (func, p, t, y_dat, weight, dp, p_min, p_max, c, opts){ var tensor_parameter = 0; // set to 1 of parameter is a tensor var iteration = 0; // iteration counter //func_calls = 0; // running count of function evaluations if((typeof p[0])!="object"){ for(var i=0;i< p.length;i++){ p[i]=[p[i]]; } } //p = p(:); y_dat = y_dat(:); // make column vectors var i,k; var eps = 2^-52; var Npar = p.length;//length(p); // number of parameters var Npnt = y_dat.length;//length(y_dat); // number of data points var p_old = Matrix.zeros(Npar,1); // previous set of parameters var y_old = Matrix.zeros(Npnt,1); // previous model, y_old = y_hat(t;p_old) var X2 = 1e-2/eps; // a really big initial Chi-sq value var X2_old = 1e-2/eps; // a really big initial Chi-sq value var J = Matrix.zeros(Npnt,Npar); if (t.length != y_dat.length) { console.log('lm.m error: the length of t must equal the length of y_dat'); length_t = t.length; length_y_dat = y_dat.length; var X2 = 0, corr = 0, sigma_p = 0, sigma_y = 0, R_sq = 0, cvg_hist = 0; if (!tensor_parameter) { return; } } weight = weight||Math.sqrt((Npnt-Npar+1)/(math.multiply(math.transpose(y_dat),y_dat))); dp = dp || 0.001; p_min = p_min || math.multiply(Math.abs(p),-100); p_max = p_max || math.multiply(Math.abs(p),100); c = c || 1; // Algorithmic Paramters //prnt MaxIter eps1 eps2 epx3 eps4 lam0 lamUP lamDN UpdateType opts = opts ||[ 3,10*Npar, 1e-3, 1e-3, 1e-3, 1e-2, 1e-2, 11, 9, 1 ]; var prnt = opts[0]; // >1 intermediate results; >2 plots var MaxIter = opts[1]; // maximum number of iterations var epsilon_1 = opts[2]; // convergence tolerance for gradient var epsilon_2 = opts[3]; // convergence tolerance for parameter var epsilon_3 = opts[4]; // convergence tolerance for Chi-square var epsilon_4 = opts[5]; // determines acceptance of a L-M step var lambda_0 = opts[6]; // initial value of damping paramter, lambda var lambda_UP_fac = opts[7]; // factor for increasing lambda var lambda_DN_fac = opts[8]; // factor for decreasing lambda var Update_Type = opts[9]; // 1: Levenberg-Marquardt lambda update // 2: Quadratic update // 3: Nielsen's lambda update equations if ( tensor_parameter && prnt == 3 ) prnt = 2; if(!dp.length || dp.length == 1){ var dp_array = new Array(Npar); for(var i=0;i<Npar;i++) dp_array[i]=[dp]; dp=dp_array; } // indices of the parameters to be fit var idx = []; for(i=0;i<dp.length;i++){ if(dp[i][0]!=0){ idx.push(i); } } var Nfit = idx.length; // number of parameters to fit var stop = false; // termination flag var weight_sq = null; //console.log(weight); if ( !weight.length || weight.length < Npnt ) { // squared weighting vector //weight_sq = ( weight(1)*ones(Npnt,1) ).^2; //console.log("weight[0] "+typeof weight[0]); var tmp = math.multiply(Matrix.ones(Npnt,1),weight[0]); weight_sq = math.dotMultiply(tmp,tmp); } else{ //weight_sq = (weight(:)).^2; weight_sq = math.dotMultiply(weight,weight); } // initialize Jacobian with finite difference calculation //console.log("J "+weight_sq); var result = this.lm_matx(func,t,p_old,y_old,1,J,p,y_dat,weight_sq,dp,c); var JtWJ = result.JtWJ,JtWdy=result.JtWdy,X2=result.Chi_sq,y_hat=result.y_hat,J=result.J; //[JtWJ,JtWdy,X2,y_hat,J] = this.lm_matx(func,t,p_old,y_old,1,J,p,y_dat,weight_sq,dp,c); //console.log(JtWJ); if ( Math.max(Math.abs(JtWdy)) < epsilon_1 ){ console.log(' *** Your Initial Guess is Extremely Close to Optimal ***') console.log(' *** epsilon_1 = ', epsilon_1); stop = true; } switch(Update_Type){ case 1: // Marquardt: init'l lambda lambda = lamb ...
n/a
function additiveSymmetric(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += ((a[i] - b[i]) * (a[i] - b[i]) * (a[i] + b[i])) / (a[i] * b[i]); } return 2 * d; }
n/a
function avg(a, b) { var ii = a.length, max = 0, ans = 0, aux = 0; for (var i = 0; i < ii ; i++) { aux = Math.abs(a[i] - b[i]); ans += aux; if (max < aux) { max = aux; } } return (max + ans) / 2; }
n/a
function bhattacharyya(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.sqrt(a[i] * b[i]); } return - Math.log(ans); }
n/a
function canberra(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.abs(a[i] - b[i]) / (a[i] + b[i]); } return ans; }
n/a
function chebyshev(a, b) { var ii = a.length, max = 0, aux = 0; for (var i = 0; i < ii ; i++) { aux = Math.abs(a[i] - b[i]); if (max < aux) { max = aux; } } return max; }
n/a
function clark(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += Math.sqrt(((a[i] - b[i]) * (a[i] - b[i])) / ((a[i] + b[i]) * (a[i] + b[i]))); } return 2 * d; }
n/a
function czekanowskiDistance(a, b) { return 1 - czekanowskiSimilarity(a, b); }
n/a
function dice(a, b) { var ii = a.length, p = 0, q1 = 0, q2 = 0; for (var i = 0; i < ii ; i++) { p += a[i] * a[i]; q1 += b[i] * b[i]; q2 += (a[i] - b[i]) * (a[i] - b[i]); } return q2 / (p + q1); }
n/a
function divergence(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += ((a[i] - b[i]) * (a[i] - b[i])) / ((a[i] + b[i]) * (a[i] + b[i])); } return 2 * d; }
n/a
function euclidean(p, q) { return Math.sqrt(squaredEuclidean(p, q)); }
n/a
function fidelity(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.sqrt(a[i] * b[i]); } return ans; }
n/a
function gower(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.abs(a[i] - b[i]); } return ans / ii; }
n/a
function harmonicMean(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += (a[i] * b[i]) / (a[i] + b[i]); } return 2 * ans; }
n/a
function hellinger(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.sqrt(a[i] * b[i]); } return 2 * Math.sqrt(1 - ans); }
n/a
function innerProduct(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += a[i] * b[i]; } return ans; }
n/a
function intersection(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.min(a[i], b[i]); } return 1 - ans; }
n/a
function jaccard(a, b) { var ii = a.length, p1 = 0, p2 = 0, q1 = 0, q2 = 0; for (var i = 0; i < ii ; i++) { p1 += a[i] * b[i]; p2 += a[i] * a[i]; q1 += b[i] * b[i]; q2 += (a[i] - b[i]) * (a[i] - b[i]); } return q2 / (p2 + q1 - p1); }
n/a
function jeffreys(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += (a[i] - b[i]) * Math.log(a[i] / b[i]); } return ans; }
n/a
function jensenDifference(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += ((a[i] * Math.log(a[i]) + b[i] * Math.log(b[i])) / 2) - ((a[i] + b[i]) / 2) * Math.log((a[i] + b[i]) / 2); } return ans; }
n/a
function jensenShannon(a, b) { var ii = a.length, p = 0, q = 0; for (var i = 0; i < ii ; i++) { p += a[i] * Math.log(2 * a[i] / (a[i] + b[i])); q += b[i] * Math.log(2 * b[i] / (a[i] + b[i])); } return (p + q) / 2; }
n/a
function kdivergence(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += a[i] * Math.log(2 * a[i] / (a[i] + b[i])); } return ans; }
n/a
function kulczynski(a, b) { var ii = a.length, up = 0, down = 0; for (var i = 0; i < ii ; i++) { up += Math.abs(a[i] - b[i]); down += Math.min(a[i],b[i]); } return up / down; }
n/a
function kullbackLeibler(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += a[i] * Math.log(a[i] / b[i]); } return ans; }
n/a
function kumarHassebrook(a, b) { var ii = a.length, p = 0, p2 = 0, q2 = 0; for (var i = 0; i < ii ; i++) { p += a[i] * b[i]; p2 += a[i] * a[i]; q2 += b[i] * b[i]; } return p / (p2 + q2 - p); }
n/a
function kumarJohnson(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.pow(a[i] * a[i] - b[i] * b[i],2) / (2 * Math.pow(a[i] * b[i],1.5)); } return ans; }
n/a
function lorentzian(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.log(Math.abs(a[i] - b[i]) + 1); } return ans; }
n/a
function manhattan(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += Math.abs(a[i] - b[i]); } return d; }
n/a
function matusita(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += Math.sqrt(a[i] * b[i]); } return Math.sqrt(2 - 2 * ans); }
n/a
function minkowski(a, b, p) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += Math.pow(Math.abs(a[i] - b[i]),p); } return Math.pow(d,(1/p)); }
n/a
function motyka(a, b) { var ii = a.length, up = 0, down = 0; for (var i = 0; i < ii ; i++) { up += Math.min(a[i], b[i]); down += a[i] + b[i]; } return 1 - (up / down); }
n/a
function neyman(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += ((a[i] - b[i]) * (a[i] - b[i])) / a[i]; } return d; }
n/a
function pearson(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += ((a[i] - b[i]) * (a[i] - b[i])) / b[i]; } return d; }
n/a
function probabilisticSymmetric(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += ((a[i] - b[i]) * (a[i] - b[i])) / (a[i] + b[i]); } return 2 * d; }
n/a
function ruzicka(a, b) { var ii = a.length, up = 0, down = 0; for (var i = 0; i < ii ; i++) { up += Math.min(a[i],b[i]); down += Math.max(a[i],b[i]); } return up / down; }
n/a
function soergel(a, b) { var ii = a.length, up = 0, down = 0; for (var i = 0; i < ii ; i++) { up += Math.abs(a[i] - b[i]); down += Math.max(a[i],b[i]); } return up / down; }
n/a
function sorensen(a, b) { var ii = a.length, up = 0, down = 0; for (var i = 0; i < ii ; i++) { up += Math.abs(a[i] - b[i]); down += a[i] + b[i]; } return up / down; }
n/a
function squared(a, b) { var i = 0, ii = a.length, d = 0; for (; i < ii; i++) { d += ((a[i] - b[i]) * (a[i] - b[i])) / (a[i] + b[i]); } return d; }
n/a
function squaredChord(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += (Math.sqrt(a[i]) - Math.sqrt(b[i])) * (Math.sqrt(a[i]) - Math.sqrt(b[i])); } return ans; }
n/a
function squaredEuclidean(p, q) { var d = 0; for (var i = 0; i < p.length; i++) { d += (p[i] - q[i]) * (p[i] - q[i]); } return d; }
n/a
function taneja(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += (a[i] + b[i]) / 2 * Math.log((a[i] + b[i]) / (2 * Math.sqrt(a[i] * b[i]))); } return ans; }
n/a
function tanimoto(a, b, bitvector) { if (bitvector) return 1 - tanimotoS(a, b, bitvector); else { var ii = a.length, p = 0, q = 0, m = 0; for (var i = 0; i < ii ; i++) { p += a[i]; q += b[i]; m += Math.min(a[i],b[i]); } return (p + q - 2 * m) / (p + q - m); } }
n/a
function topsoe(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += a[i] * Math.log(2 * a[i] / (a[i] + b[i])) + b[i] * Math.log(2 * b[i] / (a[i] + b[i])); } return ans; }
n/a
function waveHedges(a, b) { var ii = a.length, ans = 0; for (var i = 0; i < ii ; i++) { ans += 1 - (Math.min(a[i], b[i]) / Math.max(a[i], b[i])); } return ans; }
n/a
function cosine(a, b) { var ii = a.length, p = 0, p2 = 0, q2 = 0; for (var i = 0; i < ii ; i++) { p += a[i] * b[i]; p2 += a[i] * a[i]; q2 += b[i] * b[i]; } return p / (Math.sqrt(p2) * Math.sqrt(q2)); }
n/a
function czekanowskiSimilarity(a, b) { var up = 0; var down = 0; for (var i = 0; i < a.length; i++) { up += Math.min(a[i], b[i]); down += a[i] + b[i]; } return 2 * up / down; }
n/a
function dice(a, b) { return 1 - diceD(a,b); }
n/a
function intersection(a, b) { return 1 - intersectionD(a,b); }
n/a
function jaccard(a, b) { return 1 - jaccardD(a, b); }
n/a
function kulczynski(a, b) { return 1 / kulczynskiD(a, b); }
n/a
function motyka(a, b) { return 1 - motykaD(a,b); }
n/a
function pearson(a, b) { var avgA=stat.mean(a); var avgB=stat.mean(b); var newA=new Array(a.length); var newB=new Array(b.length); for (var i=0; i<newA.length; i++) { newA[i]=a[i]-avgA; newB[i]=b[i]-avgB; } return cosine(newA, newB); }
n/a
function squaredChord(a, b) { return 1 - squaredChordD(a, b); }
n/a
function tanimoto(a, b, bitvector) { if (bitvector) { var inter = 0, union = 0; for (var j = 0; j < a.length; j++) { inter += a[j] && b[j]; union += a[j] || b[j]; } if (union === 0) return 1; return inter / union; } else { var ii = a.length, p = 0, q = 0, m = 0; for (var i = 0; i < ii ; i++) { p += a[i]; q += b[i]; m += Math.min(a[i],b[i]); } return 1 - (p + q - 2 * m) / (p + q - m); } }
n/a
class SparseMatrix { constructor(rows, columns, options = {}) { if (rows instanceof SparseMatrix) { // clone const other = rows; this._init(other.rows, other.columns, other.elements.clone(), other.threshold); return; } if (Array.isArray(rows)) { const matrix = rows; rows = matrix.length; options = columns || {}; columns = matrix[0].length; this._init(rows, columns, new HashTable(options), options.threshold); for (var i = 0; i < rows; i++) { for (var j = 0; j < columns; j++) { var value = matrix[i][j]; if (this.threshold && Math.abs(value) < this.threshold) value = 0; if (value !== 0) { this.elements.set(i * columns + j, matrix[i][j]); } } } } else { this._init(rows, columns, new HashTable(options), options.threshold); } } _init(rows, columns, elements, threshold) { this.rows = rows; this.columns = columns; this.elements = elements; this.threshold = threshold || 0; } static eye(rows = 1, columns = rows) { const min = Math.min(rows, columns); const matrix = new SparseMatrix(rows, columns, {initialCapacity: min}); for (var i = 0; i < min; i++) { matrix.set(i, i, 1); } return matrix; } clone() { return new SparseMatrix(this); } to2DArray() { const copy = new Array(this.rows); for (var i = 0; i < this.rows; i++) { copy[i] = new Array(this.columns); for (var j = 0; j < this.columns; j++) { copy[i][j] = this.get(i, j); } } return copy; } isSquare() { return this.rows === this.columns; } isSymmetric() { if (!this.isSquare()) return false; var symmetric = true; this.forEachNonZero((i, j, v) => { if (this.get(j, i) !== v) { symmetric = false; return false; } return v; }); return symmetric; } get cardinality() { return this.elements.size; } get size() { return this.rows * this.columns; } get(row, column) { return this.elements.get(row * this.columns + column); } set(row, column, value) { if (this.threshold && Math.abs(value) < this.threshold) value = 0; if (value === 0) { this.elements.remove(row * this.columns + column); } else { this.elements.set(row * this.columns + column, value); } return this; } mmul(other) { if (this.columns !== other.rows) console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.'); const m = this.rows; const p = other.columns; const result = new SparseMatrix(m, p); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { if (j === k) { result.set(i, l, result.get(i, l) + v1 * v2); } return v2; }); return v1; }); return result; } kroneckerProduct(other) { const m = this.rows; const n = this.columns; const p = other.rows; const q = other.columns; const result = new SparseMatrix(m * p, n * q, { initialCapacity: this.cardinality * other.cardinality }); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { result.set(p * i + k, q * j + l, v1 * v2); return v2; }); return v1; }); return result; } forEachNonZero(callback) { this.elements.forEachPair((key, value) => { const i = (k ...
n/a
function abs(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.abs(); }
n/a
function acos(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.acos(); }
n/a
function acosh(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.acosh(); }
n/a
function add(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.add(value); }
n/a
function and(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.and(value); }
n/a
function asin(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.asin(); }
n/a
function asinh(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.asinh(); }
n/a
function atan(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.atan(); }
n/a
function atanh(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.atanh(); }
n/a
function cbrt(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.cbrt(); }
n/a
function ceil(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.ceil(); }
n/a
function clz32(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.clz32(); }
n/a
function cos(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.cos(); }
n/a
function cosh(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.cosh(); }
n/a
function div(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.div(value); }
n/a
function divide(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.divide(value); }
n/a
function exp(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.exp(); }
n/a
function expm1(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.expm1(); }
n/a
function floor(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.floor(); }
n/a
function fround(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.fround(); }
n/a
eye(rows = 1, columns = rows) { const min = Math.min(rows, columns); const matrix = new SparseMatrix(rows, columns, {initialCapacity: min}); for (var i = 0; i < min; i++) { matrix.set(i, i, 1); } return matrix; }
n/a
function leftShift(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.leftShift(value); }
n/a
function log(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.log(); }
...
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/mljs/ml.git"
},
"scripts": {
"build": "cheminfo build --root ML",
"test": "node -p \"void(require('./'));console.log(
x27;OK')\""
},
"version": "2.0.0"
}
...
function log10(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.log10(); }
n/a
function log1p(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.log1p(); }
n/a
function log2(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.log2(); }
n/a
function mod(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.mod(value); }
n/a
function modulus(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.modulus(value); }
n/a
function mul(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.mul(value); }
n/a
function multiply(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.multiply(value); }
n/a
function not(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.not(); }
n/a
function or(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.or(value); }
n/a
function rightShift(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.rightShift(value); }
n/a
function round(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.round(); }
n/a
function sign(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.sign(); }
n/a
function signPropagatingRightShift(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.signPropagatingRightShift(value); }
n/a
function sin(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.sin(); }
n/a
function sinh(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.sinh(); }
n/a
function sqrt(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.sqrt(); }
n/a
function sub(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.sub(value); }
n/a
function subtract(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.subtract(value); }
n/a
function tan(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.tan(); }
n/a
function tanh(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.tanh(); }
n/a
function trunc(matrix) { var newMatrix = new SparseMatrix(matrix); return newMatrix.trunc(); }
n/a
function xor(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.xor(value); }
n/a
function zeroFillRightShift(matrix, value) { var newMatrix = new SparseMatrix(matrix); return newMatrix.zeroFillRightShift(value); }
n/a
function abs() { this.forEachNonZero((i, j, v) => Math.abs(v)); return this; }
n/a
function acos() { this.forEachNonZero((i, j, v) => Math.acos(v)); return this; }
n/a
function acosh() { this.forEachNonZero((i, j, v) => Math.acosh(v)); return this; }
n/a
function add(value) { if (typeof value === 'number') return this.addS(value); return this.addM(value); }
n/a
function addMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) + v); return v; }); return this; }
n/a
function addSS(value) { this.forEachNonZero((i, j, v) => v + value); return this; }
n/a
function and(value) { if (typeof value === 'number') return this.andS(value); return this.andM(value); }
n/a
function andMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) & v); return v; }); return this; }
n/a
function andSS(value) { this.forEachNonZero((i, j, v) => v & value); return this; }
n/a
function asin() { this.forEachNonZero((i, j, v) => Math.asin(v)); return this; }
n/a
function asinh() { this.forEachNonZero((i, j, v) => Math.asinh(v)); return this; }
n/a
function atan() { this.forEachNonZero((i, j, v) => Math.atan(v)); return this; }
n/a
function atanh() { this.forEachNonZero((i, j, v) => Math.atanh(v)); return this; }
n/a
function cbrt() { this.forEachNonZero((i, j, v) => Math.cbrt(v)); return this; }
n/a
function ceil() { this.forEachNonZero((i, j, v) => Math.ceil(v)); return this; }
n/a
function clz32() { this.forEachNonZero((i, j, v) => Math.clz32(v)); return this; }
n/a
function cos() { this.forEachNonZero((i, j, v) => Math.cos(v)); return this; }
n/a
function cosh() { this.forEachNonZero((i, j, v) => Math.cosh(v)); return this; }
n/a
function div(value) { if (typeof value === 'number') return this.divS(value); return this.divM(value); }
n/a
function divMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) / v); return v; }); return this; }
n/a
function divSS(value) { this.forEachNonZero((i, j, v) => v / value); return this; }
n/a
function divide(value) { if (typeof value === 'number') return this.divideS(value); return this.divideM(value); }
n/a
function divideMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) / v); return v; }); return this; }
n/a
function divideSS(value) { this.forEachNonZero((i, j, v) => v / value); return this; }
n/a
function exp() { this.forEachNonZero((i, j, v) => Math.exp(v)); return this; }
n/a
function expm1() { this.forEachNonZero((i, j, v) => Math.expm1(v)); return this; }
n/a
function floor() { this.forEachNonZero((i, j, v) => Math.floor(v)); return this; }
n/a
function fround() { this.forEachNonZero((i, j, v) => Math.fround(v)); return this; }
n/a
function leftShift(value) { if (typeof value === 'number') return this.leftShiftS(value); return this.leftShiftM(value); }
n/a
function leftShiftMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) << v); return v; }); return this; }
n/a
function leftShiftSS(value) { this.forEachNonZero((i, j, v) => v << value); return this; }
n/a
function log() { this.forEachNonZero((i, j, v) => Math.log(v)); return this; }
...
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/mljs/ml.git"
},
"scripts": {
"build": "cheminfo build --root ML",
"test": "node -p \"void(require('./'));console.log(
x27;OK')\""
},
"version": "2.0.0"
}
...
function log10() { this.forEachNonZero((i, j, v) => Math.log10(v)); return this; }
n/a
function log1p() { this.forEachNonZero((i, j, v) => Math.log1p(v)); return this; }
n/a
function log2() { this.forEachNonZero((i, j, v) => Math.log2(v)); return this; }
n/a
function mod(value) { if (typeof value === 'number') return this.modS(value); return this.modM(value); }
n/a
function modMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) % v); return v; }); return this; }
n/a
function modSS(value) { this.forEachNonZero((i, j, v) => v % value); return this; }
n/a
function modulus(value) { if (typeof value === 'number') return this.modulusS(value); return this.modulusM(value); }
n/a
function modulusMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) % v); return v; }); return this; }
n/a
function modulusSS(value) { this.forEachNonZero((i, j, v) => v % value); return this; }
n/a
function mul(value) { if (typeof value === 'number') return this.mulS(value); return this.mulM(value); }
n/a
function mulMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) * v); return v; }); return this; }
n/a
function mulSS(value) { this.forEachNonZero((i, j, v) => v * value); return this; }
n/a
function multiply(value) { if (typeof value === 'number') return this.multiplyS(value); return this.multiplyM(value); }
n/a
function multiplyMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) * v); return v; }); return this; }
n/a
function multiplySS(value) { this.forEachNonZero((i, j, v) => v * value); return this; }
n/a
function not() { this.forEachNonZero((i, j, v) => ~(v)); return this; }
n/a
function or(value) { if (typeof value === 'number') return this.orS(value); return this.orM(value); }
n/a
function orMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) | v); return v; }); return this; }
n/a
function orSS(value) { this.forEachNonZero((i, j, v) => v | value); return this; }
n/a
function rightShift(value) { if (typeof value === 'number') return this.rightShiftS(value); return this.rightShiftM(value); }
n/a
function rightShiftMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) >>> v); return v; }); return this; }
n/a
function rightShiftSS(value) { this.forEachNonZero((i, j, v) => v >>> value); return this; }
n/a
function round() { this.forEachNonZero((i, j, v) => Math.round(v)); return this; }
n/a
function sign() { this.forEachNonZero((i, j, v) => Math.sign(v)); return this; }
n/a
function signPropagatingRightShift(value) { if (typeof value === 'number') return this.signPropagatingRightShiftS(value); return this.signPropagatingRightShiftM(value); }
n/a
function signPropagatingRightShiftMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) >> v); return v; }); return this; }
n/a
function signPropagatingRightShiftSS(value) { this.forEachNonZero((i, j, v) => v >> value); return this; }
n/a
function sin() { this.forEachNonZero((i, j, v) => Math.sin(v)); return this; }
n/a
function sinh() { this.forEachNonZero((i, j, v) => Math.sinh(v)); return this; }
n/a
function sqrt() { this.forEachNonZero((i, j, v) => Math.sqrt(v)); return this; }
n/a
function sub(value) { if (typeof value === 'number') return this.subS(value); return this.subM(value); }
n/a
function subMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) - v); return v; }); return this; }
n/a
function subSS(value) { this.forEachNonZero((i, j, v) => v - value); return this; }
n/a
function subtract(value) { if (typeof value === 'number') return this.subtractS(value); return this.subtractM(value); }
n/a
function subtractMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) - v); return v; }); return this; }
n/a
function subtractSS(value) { this.forEachNonZero((i, j, v) => v - value); return this; }
n/a
function tan() { this.forEachNonZero((i, j, v) => Math.tan(v)); return this; }
n/a
function tanh() { this.forEachNonZero((i, j, v) => Math.tanh(v)); return this; }
n/a
kroneckerProduct(other) { const m = this.rows; const n = this.columns; const p = other.rows; const q = other.columns; const result = new SparseMatrix(m * p, n * q, { initialCapacity: this.cardinality * other.cardinality }); this.forEachNonZero((i, j, v1) => { other.forEachNonZero((k, l, v2) => { result.set(p * i + k, q * j + l, v1 * v2); return v2; }); return v1; }); return result; }
n/a
function trunc() { this.forEachNonZero((i, j, v) => Math.trunc(v)); return this; }
n/a
function xor(value) { if (typeof value === 'number') return this.xorS(value); return this.xorM(value); }
n/a
function xorMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) ^ v); return v; }); return this; }
n/a
function xorSS(value) { this.forEachNonZero((i, j, v) => v ^ value); return this; }
n/a
function zeroFillRightShift(value) { if (typeof value === 'number') return this.zeroFillRightShiftS(value); return this.zeroFillRightShiftM(value); }
n/a
function zeroFillRightShiftMM(matrix) { matrix.forEachNonZero((i, j, v) => { this.set(i, j, this.get(i, j) >>> v); return v; }); return this; }
n/a
function zeroFillRightShiftSS(value) { this.forEachNonZero((i, j, v) => v >>> value); return this; }
n/a
class Matrix extends abstractMatrix(Array) {
constructor(nRows, nColumns) {
var i;
if (arguments.length === 1 && typeof nRows === 'number') {
return new Array(nRows);
}
if (Matrix.isMatrix(nRows)) {
return nRows.clone();
} else if (Number.isInteger(nRows) && nRows > 0) { // Create an empty matrix
super(nRows);
if (Number.isInteger(nColumns) && nColumns > 0) {
for (i = 0; i < nRows; i++) {
this[i] = new Array(nColumns);
}
} else {
throw new TypeError('nColumns must be a positive integer');
}
} else if (Array.isArray(nRows)) { // Copy the values from the 2D array
const matrix = nRows;
nRows = matrix.length;
nColumns = matrix[0].length;
if (typeof nColumns !== 'number' || nColumns === 0) {
throw new TypeError('Data must be a 2D array with at least one element');
}
super(nRows);
for (i = 0; i < nRows; i++) {
if (matrix[i].length !== nColumns) {
throw new RangeError('Inconsistent array dimensions');
}
this[i] = [].concat(matrix[i]);
}
} else {
throw new TypeError('First argument must be a positive number or an array');
}
this.rows = nRows;
this.columns = nColumns;
return this;
}
set(rowIndex, columnIndex, value) {
this[rowIndex][columnIndex] = value;
return this;
}
get(rowIndex, columnIndex) {
return this[rowIndex][columnIndex];
}
/**
* Creates an exact and independent copy of the matrix
* @return {Matrix}
*/
clone() {
var newMatrix = new this.constructor[Symbol.species](this.rows, this.columns);
for (var row = 0; row < this.rows; row++) {
for (var column = 0; column < this.columns; column++) {
newMatrix.set(row, column, this.get(row, column));
}
}
return newMatrix;
}
/**
* Removes a row from the given index
* @param {number} index - Row index
* @return {Matrix} this
*/
removeRow(index) {
util.checkRowIndex(this, index);
if (this.rows === 1) {
throw new RangeError('A matrix cannot have less than one row');
}
this.splice(index, 1);
this.rows -= 1;
return this;
}
/**
* Adds a row at the given index
* @param {number} [index = this.rows] - Row index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addRow(index, array) {
if (array === undefined) {
array = index;
index = this.rows;
}
util.checkRowIndex(this, index, true);
array = util.checkRowVector(this, array, true);
this.splice(index, 0, array);
this.rows += 1;
return this;
}
/**
* Removes a column from the given index
* @param {number} index - Column index
* @return {Matrix} this
*/
removeColumn(index) {
util.checkColumnIndex(this, index);
if (this.columns === 1) {
throw new RangeError('A matrix cannot have less than one column');
}
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 1);
}
this.columns -= 1;
return this;
}
/**
* Adds a column at the given index
* @param {number} [index = this.columns] - Column index
* @param {Array|Matrix} array - Array or vector
* @return {Matrix} this
*/
addColumn(index, array) {
if (typeof array === 'undefined') {
array = index;
index = this.columns;
}
util.checkColumnIndex(this, index, true);
array = util.checkColumnVector(this, array);
for (var i = 0; i < this.rows; i++) {
this[i].splice(index, 0, array[i]);
} ...
n/a
function abstractMatrix(superCtor) {
if (superCtor === undefined) superCtor = Object;
/**
* Real matrix
* @class Matrix
* @param {number|Array|Matrix} nRows - Number of rows of the new matrix,
* 2D array containing the data or Matrix instance to clone
* @param {number} [nColumns] - Number of columns of the new matrix
*/
class Matrix extends superCtor {
static get [Symbol.species]() {
return this;
}
/**
* Constructs a Matrix with the chosen dimensions from a 1D array
* @param {number} newRows - Number of rows
* @param {number} newColumns - Number of columns
* @param {Array} newData - A 1D array containing data for the matrix
* @return {Matrix} - The new matrix
*/
static from1DArray(newRows, newColumns, newData) {
var length = newRows * newColumns;
if (length !== newData.length) {
throw new RangeError('Data length does not match given dimensions');
}
var newMatrix = new this(newRows, newColumns);
for (var row = 0; row < newRows; row++) {
for (var column = 0; column < newColumns; column++) {
newMatrix.set(row, column, newData[row * newColumns + column]);
}
}
return newMatrix;
}
/**
* Creates a row vector, a matrix with only one row.
* @param {Array} newData - A 1D array containing data for the vector
* @return {Matrix} - The new matrix
*/
static rowVector(newData) {
var vector = new this(1, newData.length);
for (var i = 0; i < newData.length; i++) {
vector.set(0, i, newData[i]);
}
return vector;
}
/**
* Creates a column vector, a matrix with only one column.
* @param {Array} newData - A 1D array containing data for the vector
* @return {Matrix} - The new matrix
*/
static columnVector(newData) {
var vector = new this(newData.length, 1);
for (var i = 0; i < newData.length; i++) {
vector.set(i, 0, newData[i]);
}
return vector;
}
/**
* Creates an empty matrix with the given dimensions. Values will be undefined. Same as using new Matrix(rows, columns).
* @param {number} rows - Number of rows
* @param {number} columns - Number of columns
* @return {Matrix} - The new matrix
*/
static empty(rows, columns) {
return new this(rows, columns);
}
/**
* Creates a matrix with the given dimensions. Values will be set to zero.
* @param {number} rows - Number of rows
* @param {number} columns - Number of columns
* @return {Matrix} - The new matrix
*/
static zeros(rows, columns) {
return this.empty(rows, columns).fill(0);
}
/**
* Creates a matrix with the given dimensions. Values will be set to one.
* @param {number} rows - Number of rows
* @param {number} columns - Number of columns
* @return {Matrix} - The new matrix
*/
static ones(rows, columns) {
return this.empty(rows, columns).fill(1);
}
/**
* Creates a matrix with the given dimensions. Values will be randomly set.
* @param {number} rows - Number of rows
* @param {number} columns - Number of columns
* @param {function} [rng=Math.random] - Random number generator
* @return {Matrix} The new matrix
*/
static rand(rows, columns, rng) {
if (rng === undefined) rng = Math.random;
var matrix = this.empty(rows, columns);
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
matrix.set(i, j, rng());
}
}
return matrix; ...
n/a
function inverse(matrix) { matrix = Matrix.checkMatrix(matrix); return solve(matrix, Matrix.eye(matrix.rows)); }
n/a
function inverse(matrix) { matrix = Matrix.checkMatrix(matrix); return solve(matrix, Matrix.eye(matrix.rows)); }
n/a
function solve(leftHandSide, rightHandSide) { leftHandSide = Matrix.checkMatrix(leftHandSide); rightHandSide = Matrix.checkMatrix(rightHandSide); return leftHandSide.isSquare() ? new LuDecomposition(leftHandSide).solve(rightHandSide) : new QrDecomposition(leftHandSide). solve(rightHandSide); }
n/a
function CholeskyDecomposition(value) { if (!(this instanceof CholeskyDecomposition)) { return new CholeskyDecomposition(value); } value = Matrix.checkMatrix(value); if (!value.isSymmetric()) { throw new Error('Matrix is not symmetric'); } var a = value, dimension = a.rows, l = new Matrix(dimension, dimension), positiveDefinite = true, i, j, k; for (j = 0; j < dimension; j++) { var Lrowj = l[j]; var d = 0; for (k = 0; k < j; k++) { var Lrowk = l[k]; var s = 0; for (i = 0; i < k; i++) { s += Lrowk[i] * Lrowj[i]; } Lrowj[k] = s = (a[j][k] - s) / l[k][k]; d = d + s * s; } d = a[j][j] - d; positiveDefinite &= (d > 0); l[j][j] = Math.sqrt(Math.max(d, 0)); for (k = j + 1; k < dimension; k++) { l[j][k] = 0; } } if (!positiveDefinite) { throw new Error('Matrix is not positive definite'); } this.L = l; }
n/a
function CholeskyDecomposition(value) { if (!(this instanceof CholeskyDecomposition)) { return new CholeskyDecomposition(value); } value = Matrix.checkMatrix(value); if (!value.isSymmetric()) { throw new Error('Matrix is not symmetric'); } var a = value, dimension = a.rows, l = new Matrix(dimension, dimension), positiveDefinite = true, i, j, k; for (j = 0; j < dimension; j++) { var Lrowj = l[j]; var d = 0; for (k = 0; k < j; k++) { var Lrowk = l[k]; var s = 0; for (i = 0; i < k; i++) { s += Lrowk[i] * Lrowj[i]; } Lrowj[k] = s = (a[j][k] - s) / l[k][k]; d = d + s * s; } d = a[j][j] - d; positiveDefinite &= (d > 0); l[j][j] = Math.sqrt(Math.max(d, 0)); for (k = j + 1; k < dimension; k++) { l[j][k] = 0; } } if (!positiveDefinite) { throw new Error('Matrix is not positive definite'); } this.L = l; }
n/a
function EigenvalueDecomposition(matrix, options) { options = Object.assign({}, defaultOptions, options); if (!(this instanceof EigenvalueDecomposition)) { return new EigenvalueDecomposition(matrix, options); } matrix = Matrix.checkMatrix(matrix); if (!matrix.isSquare()) { throw new Error('Matrix is not a square matrix'); } var n = matrix.columns, V = getFilled2DArray(n, n, 0), d = new Array(n), e = new Array(n), value = matrix, i, j; var isSymmetric = false; if (options.assumeSymmetric) { isSymmetric = true; } else { isSymmetric = matrix.isSymmetric(); } if (isSymmetric) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { V[i][j] = value.get(i, j); } } tred2(n, e, d, V); tql2(n, e, d, V); } else { var H = getFilled2DArray(n, n, 0), ort = new Array(n); for (j = 0; j < n; j++) { for (i = 0; i < n; i++) { H[i][j] = value.get(i, j); } } orthes(n, H, ort, V); hqr2(n, e, d, V, H); } this.n = n; this.e = e; this.d = d; this.V = V; }
n/a
function EigenvalueDecomposition(matrix, options) { options = Object.assign({}, defaultOptions, options); if (!(this instanceof EigenvalueDecomposition)) { return new EigenvalueDecomposition(matrix, options); } matrix = Matrix.checkMatrix(matrix); if (!matrix.isSquare()) { throw new Error('Matrix is not a square matrix'); } var n = matrix.columns, V = getFilled2DArray(n, n, 0), d = new Array(n), e = new Array(n), value = matrix, i, j; var isSymmetric = false; if (options.assumeSymmetric) { isSymmetric = true; } else { isSymmetric = matrix.isSymmetric(); } if (isSymmetric) { for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { V[i][j] = value.get(i, j); } } tred2(n, e, d, V); tql2(n, e, d, V); } else { var H = getFilled2DArray(n, n, 0), ort = new Array(n); for (j = 0; j < n; j++) { for (i = 0; i < n; i++) { H[i][j] = value.get(i, j); } } orthes(n, H, ort, V); hqr2(n, e, d, V, H); } this.n = n; this.e = e; this.d = d; this.V = V; }
n/a
function LuDecomposition(matrix) { if (!(this instanceof LuDecomposition)) { return new LuDecomposition(matrix); } matrix = Matrix.Matrix.checkMatrix(matrix); var lu = matrix.clone(), rows = lu.rows, columns = lu.columns, pivotVector = new Array(rows), pivotSign = 1, i, j, k, p, s, t, v, LUrowi, LUcolj, kmax; for (i = 0; i < rows; i++) { pivotVector[i] = i; } LUcolj = new Array(rows); for (j = 0; j < columns; j++) { for (i = 0; i < rows; i++) { LUcolj[i] = lu[i][j]; } for (i = 0; i < rows; i++) { LUrowi = lu[i]; kmax = Math.min(i, j); s = 0; for (k = 0; k < kmax; k++) { s += LUrowi[k] * LUcolj[k]; } LUrowi[j] = LUcolj[i] -= s; } p = j; for (i = j + 1; i < rows; i++) { if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) { p = i; } } if (p !== j) { for (k = 0; k < columns; k++) { t = lu[p][k]; lu[p][k] = lu[j][k]; lu[j][k] = t; } v = pivotVector[p]; pivotVector[p] = pivotVector[j]; pivotVector[j] = v; pivotSign = -pivotSign; } if (j < rows && lu[j][j] !== 0) { for (i = j + 1; i < rows; i++) { lu[i][j] /= lu[j][j]; } } } this.LU = lu; this.pivotVector = pivotVector; this.pivotSign = pivotSign; }
n/a
function LuDecomposition(matrix) { if (!(this instanceof LuDecomposition)) { return new LuDecomposition(matrix); } matrix = Matrix.Matrix.checkMatrix(matrix); var lu = matrix.clone(), rows = lu.rows, columns = lu.columns, pivotVector = new Array(rows), pivotSign = 1, i, j, k, p, s, t, v, LUrowi, LUcolj, kmax; for (i = 0; i < rows; i++) { pivotVector[i] = i; } LUcolj = new Array(rows); for (j = 0; j < columns; j++) { for (i = 0; i < rows; i++) { LUcolj[i] = lu[i][j]; } for (i = 0; i < rows; i++) { LUrowi = lu[i]; kmax = Math.min(i, j); s = 0; for (k = 0; k < kmax; k++) { s += LUrowi[k] * LUcolj[k]; } LUrowi[j] = LUcolj[i] -= s; } p = j; for (i = j + 1; i < rows; i++) { if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) { p = i; } } if (p !== j) { for (k = 0; k < columns; k++) { t = lu[p][k]; lu[p][k] = lu[j][k]; lu[j][k] = t; } v = pivotVector[p]; pivotVector[p] = pivotVector[j]; pivotVector[j] = v; pivotSign = -pivotSign; } if (j < rows && lu[j][j] !== 0) { for (i = j + 1; i < rows; i++) { lu[i][j] /= lu[j][j]; } } } this.LU = lu; this.pivotVector = pivotVector; this.pivotSign = pivotSign; }
n/a
function QrDecomposition(value) { if (!(this instanceof QrDecomposition)) { return new QrDecomposition(value); } value = Matrix.checkMatrix(value); var qr = value.clone(), m = value.rows, n = value.columns, rdiag = new Array(n), i, j, k, s; for (k = 0; k < n; k++) { var nrm = 0; for (i = k; i < m; i++) { nrm = hypotenuse(nrm, qr[i][k]); } if (nrm !== 0) { if (qr[k][k] < 0) { nrm = -nrm; } for (i = k; i < m; i++) { qr[i][k] /= nrm; } qr[k][k] += 1; for (j = k + 1; j < n; j++) { s = 0; for (i = k; i < m; i++) { s += qr[i][k] * qr[i][j]; } s = -s / qr[k][k]; for (i = k; i < m; i++) { qr[i][j] += s * qr[i][k]; } } } rdiag[k] = -nrm; } this.QR = qr; this.Rdiag = rdiag; }
n/a
function QrDecomposition(value) { if (!(this instanceof QrDecomposition)) { return new QrDecomposition(value); } value = Matrix.checkMatrix(value); var qr = value.clone(), m = value.rows, n = value.columns, rdiag = new Array(n), i, j, k, s; for (k = 0; k < n; k++) { var nrm = 0; for (i = k; i < m; i++) { nrm = hypotenuse(nrm, qr[i][k]); } if (nrm !== 0) { if (qr[k][k] < 0) { nrm = -nrm; } for (i = k; i < m; i++) { qr[i][k] /= nrm; } qr[k][k] += 1; for (j = k + 1; j < n; j++) { s = 0; for (i = k; i < m; i++) { s += qr[i][k] * qr[i][j]; } s = -s / qr[k][k]; for (i = k; i < m; i++) { qr[i][j] += s * qr[i][k]; } } } rdiag[k] = -nrm; } this.QR = qr; this.Rdiag = rdiag; }
n/a
function SingularValueDecomposition(value, options) { if (!(this instanceof SingularValueDecomposition)) { return new SingularValueDecomposition(value, options); } value = Matrix.Matrix.checkMatrix(value); options = options || {}; var m = value.rows, n = value.columns, nu = Math.min(m, n); var wantu = true, wantv = true; if (options.computeLeftSingularVectors === false) wantu = false; if (options.computeRightSingularVectors === false) wantv = false; var autoTranspose = options.autoTranspose === true; var swapped = false; var a; if (m < n) { if (!autoTranspose) { a = value.clone(); // eslint-disable-next-line no-console console.warn('Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose'); } else { a = value.transpose(); m = a.rows; n = a.columns; swapped = true; var aux = wantu; wantu = wantv; wantv = aux; } } else { a = value.clone(); } var s = new Array(Math.min(m + 1, n)), U = getFilled2DArray(m, nu, 0), V = getFilled2DArray(n, n, 0), e = new Array(n), work = new Array(m); var nct = Math.min(m - 1, n); var nrt = Math.max(0, Math.min(n - 2, m)); var i, j, k, p, t, ks, f, cs, sn, max, kase, scale, sp, spm1, epm1, sk, ek, b, c, shift, g; for (k = 0, max = Math.max(nct, nrt); k < max; k++) { if (k < nct) { s[k] = 0; for (i = k; i < m; i++) { s[k] = hypotenuse(s[k], a[i][k]); } if (s[k] !== 0) { if (a[k][k] < 0) { s[k] = -s[k]; } for (i = k; i < m; i++) { a[i][k] /= s[k]; } a[k][k] += 1; } s[k] = -s[k]; } for (j = k + 1; j < n; j++) { if ((k < nct) && (s[k] !== 0)) { t = 0; for (i = k; i < m; i++) { t += a[i][k] * a[i][j]; } t = -t / a[k][k]; for (i = k; i < m; i++) { a[i][j] += t * a[i][k]; } } e[j] = a[k][j]; } if (wantu && (k < nct)) { for (i = k; i < m; i++) { U[i][k] = a[i][k]; } } if (k < nrt) { e[k] = 0; for (i = k + 1; i < n; i++) { e[k] = hypotenuse(e[k], e[i]); } if (e[k] !== 0) { if (e[k + 1] < 0) { e[k] = 0 - e[k]; } for (i = k + 1; i < n; i++) { e[i] /= e[k]; } e[k + 1] += 1; } e[k] = -e[k]; if ((k + 1 < m) && (e[k] !== 0)) { for (i = k + 1; i < m; i++) { work[i] = 0; } for (j = k + 1; j < n; j++) { for (i = k + 1; i < m; i++) { work[i] += e[j] * a[i][j]; } } for (j = k + 1; j < n; j++) { t = -e[j] / e[k + 1]; for (i = k + 1; i < m; i++) { a[i][j] += t * work[i]; } } } if (wantv) { for (i = k + 1; i < n; i++) { V[i][k] = e[i]; } } } } p = Math.min(n, m + 1); if (nct < n) { s[nct] = a[nct][nct]; } if (m < p) { s[p - 1] = 0; } if (nrt + 1 < p) { e[nrt] = a[nrt][p - 1]; } e[p - 1] = 0; if (wantu) { for (j = nct; j < nu; j++) { for (i = 0; i < m; i++) { U[i][j] = 0; } U[j][j] = 1; } for (k = nct - 1; k >= 0; k ...
n/a
function SingularValueDecomposition(value, options) { if (!(this instanceof SingularValueDecomposition)) { return new SingularValueDecomposition(value, options); } value = Matrix.Matrix.checkMatrix(value); options = options || {}; var m = value.rows, n = value.columns, nu = Math.min(m, n); var wantu = true, wantv = true; if (options.computeLeftSingularVectors === false) wantu = false; if (options.computeRightSingularVectors === false) wantv = false; var autoTranspose = options.autoTranspose === true; var swapped = false; var a; if (m < n) { if (!autoTranspose) { a = value.clone(); // eslint-disable-next-line no-console console.warn('Computing SVD on a matrix with more columns than rows. Consider enabling autoTranspose'); } else { a = value.transpose(); m = a.rows; n = a.columns; swapped = true; var aux = wantu; wantu = wantv; wantv = aux; } } else { a = value.clone(); } var s = new Array(Math.min(m + 1, n)), U = getFilled2DArray(m, nu, 0), V = getFilled2DArray(n, n, 0), e = new Array(n), work = new Array(m); var nct = Math.min(m - 1, n); var nrt = Math.max(0, Math.min(n - 2, m)); var i, j, k, p, t, ks, f, cs, sn, max, kase, scale, sp, spm1, epm1, sk, ek, b, c, shift, g; for (k = 0, max = Math.max(nct, nrt); k < max; k++) { if (k < nct) { s[k] = 0; for (i = k; i < m; i++) { s[k] = hypotenuse(s[k], a[i][k]); } if (s[k] !== 0) { if (a[k][k] < 0) { s[k] = -s[k]; } for (i = k; i < m; i++) { a[i][k] /= s[k]; } a[k][k] += 1; } s[k] = -s[k]; } for (j = k + 1; j < n; j++) { if ((k < nct) && (s[k] !== 0)) { t = 0; for (i = k; i < m; i++) { t += a[i][k] * a[i][j]; } t = -t / a[k][k]; for (i = k; i < m; i++) { a[i][j] += t * a[i][k]; } } e[j] = a[k][j]; } if (wantu && (k < nct)) { for (i = k; i < m; i++) { U[i][k] = a[i][k]; } } if (k < nrt) { e[k] = 0; for (i = k + 1; i < n; i++) { e[k] = hypotenuse(e[k], e[i]); } if (e[k] !== 0) { if (e[k + 1] < 0) { e[k] = 0 - e[k]; } for (i = k + 1; i < n; i++) { e[i] /= e[k]; } e[k + 1] += 1; } e[k] = -e[k]; if ((k + 1 < m) && (e[k] !== 0)) { for (i = k + 1; i < m; i++) { work[i] = 0; } for (j = k + 1; j < n; j++) { for (i = k + 1; i < m; i++) { work[i] += e[j] * a[i][j]; } } for (j = k + 1; j < n; j++) { t = -e[j] / e[k + 1]; for (i = k + 1; i < m; i++) { a[i][j] += t * work[i]; } } } if (wantv) { for (i = k + 1; i < n; i++) { V[i][k] = e[i]; } } } } p = Math.min(n, m + 1); if (nct < n) { s[nct] = a[nct][nct]; } if (m < p) { s[p - 1] = 0; } if (nrt + 1 < p) { e[nrt] = a[nrt][p - 1]; } e[p - 1] = 0; if (wantu) { for (j = nct; j < nu; j++) { for (i = 0; i < m; i++) { U[i][j] = 0; } U[j][j] = 1; } for (k = nct - 1; k >= 0; k ...
n/a
function inverse(matrix) { matrix = Matrix.checkMatrix(matrix); return solve(matrix, Matrix.eye(matrix.rows)); }
n/a
function solve(leftHandSide, rightHandSide) { leftHandSide = Matrix.checkMatrix(leftHandSide); rightHandSide = Matrix.checkMatrix(rightHandSide); return leftHandSide.isSquare() ? new LuDecomposition(leftHandSide).solve(rightHandSide) : new QrDecomposition(leftHandSide). solve(rightHandSide); }
n/a
solve = function (value) { value = Matrix.checkMatrix(value); var l = this.L, dimension = l.rows; if (value.rows !== dimension) { throw new Error('Matrix dimensions do not match'); } var count = value.columns, B = value.clone(), i, j, k; for (k = 0; k < dimension; k++) { for (j = 0; j < count; j++) { for (i = 0; i < k; i++) { B[k][j] -= B[i][j] * l[k][i]; } B[k][j] /= l[k][k]; } } for (k = dimension - 1; k >= 0; k--) { for (j = 0; j < count; j++) { for (i = k + 1; i < dimension; i++) { B[k][j] -= B[i][j] * l[i][k]; } B[k][j] /= l[k][k]; } } return B; }
n/a
isSingular = function () { var data = this.LU, col = data.columns; for (var j = 0; j < col; j++) { if (data[j][j] === 0) { return true; } } return false; }
n/a
solve = function (value) { value = Matrix.Matrix.checkMatrix(value); var lu = this.LU, rows = lu.rows; if (rows !== value.rows) { throw new Error('Invalid matrix dimensions'); } if (this.isSingular()) { throw new Error('LU matrix is singular'); } var count = value.columns; var X = value.subMatrixRow(this.pivotVector, 0, count - 1); var columns = lu.columns; var i, j, k; for (k = 0; k < columns; k++) { for (i = k + 1; i < columns; i++) { for (j = 0; j < count; j++) { X[i][j] -= X[k][j] * lu[i][k]; } } } for (k = columns - 1; k >= 0; k--) { for (j = 0; j < count; j++) { X[k][j] /= lu[k][k]; } for (i = 0; i < k; i++) { for (j = 0; j < count; j++) { X[i][j] -= X[k][j] * lu[i][k]; } } } return X; }
n/a
isFullRank = function () { var columns = this.QR.columns; for (var i = 0; i < columns; i++) { if (this.Rdiag[i] === 0) { return false; } } return true; }
n/a
solve = function (value) { value = Matrix.checkMatrix(value); var qr = this.QR, m = qr.rows; if (value.rows !== m) { throw new Error('Matrix row dimensions must agree'); } if (!this.isFullRank()) { throw new Error('Matrix is rank deficient'); } var count = value.columns; var X = value.clone(); var n = qr.columns; var i, j, k, s; for (k = 0; k < n; k++) { for (j = 0; j < count; j++) { s = 0; for (i = k; i < m; i++) { s += qr[i][k] * X[i][j]; } s = -s / qr[k][k]; for (i = k; i < m; i++) { X[i][j] += s * qr[i][k]; } } } for (k = n - 1; k >= 0; k--) { for (j = 0; j < count; j++) { X[k][j] /= this.Rdiag[k]; } for (i = 0; i < k; i++) { for (j = 0; j < count; j++) { X[i][j] -= X[k][j] * qr[i][k]; } } } return X.subMatrix(0, n - 1, 0, count - 1); }
n/a
inverse = function () { var V = this.V; var e = this.threshold, vrows = V.length, vcols = V[0].length, X = new Matrix.Matrix(vrows, this.s.length), i, j; for (i = 0; i < vrows; i++) { for (j = 0; j < vcols; j++) { if (Math.abs(this.s[j]) > e) { X[i][j] = V[i][j] / this.s[j]; } else { X[i][j] = 0; } } } var U = this.U; var urows = U.length, ucols = U[0].length, Y = new Matrix.Matrix(vrows, urows), k, sum; for (i = 0; i < vrows; i++) { for (j = 0; j < urows; j++) { sum = 0; for (k = 0; k < ucols; k++) { sum += X[i][k] * U[j][k]; } Y[i][j] = sum; } } return Y; }
n/a
solve = function (value) { var Y = value, e = this.threshold, scols = this.s.length, Ls = Matrix.Matrix.zeros(scols, scols), i; for (i = 0; i < scols; i++) { if (Math.abs(this.s[i]) <= e) { Ls[i][i] = 0; } else { Ls[i][i] = 1 / this.s[i]; } } var U = this.U; var V = this.rightSingularVectors; var VL = V.mmul(Ls), vrows = V.rows, urows = U.length, VLU = Matrix.Matrix.zeros(vrows, urows), j, k, sum; for (i = 0; i < vrows; i++) { for (j = 0; j < urows; j++) { sum = 0; for (k = 0; k < scols; k++) { sum += VL[i][k] * U[j][k]; } VLU[i][j] = sum; } } return VLU.mmul(Y); }
n/a
solveForDiagonal = function (value) { return this.solve(Matrix.Matrix.diag(value)); }
n/a
function abs(A){ if(typeof A==='number' ) return Math.abs(A); var ii = A.rows, jj = A.columns; var result = new Matrix(ii,jj); for (var i = 0; i < ii; i++) { for (var j = 0; j < jj; j++) { result[i][j] = Math.abs(A[i][j]); } } return result; }
n/a
function add(A, B){ if(typeof A == 'number'&&typeof B === 'number') return A+B; if(typeof A == 'number') return this.add(B,A); var result = A.clone(); return result.add(B); }
n/a
function diag(A){ var diag = null; var rows = A.rows, cols = A.columns, j, r; //It is an array if(typeof cols === "undefined" && (typeof A)=='object'){ if(A[0]&&A[0].length){ rows = A.length; cols = A[0].length; r = Math.min(rows,cols); diag = Matrix.zeros(cols, cols); for (j = 0; j < cols; j++) { diag[j][j]=A[j][j]; } } else{ cols = A.length; diag = Matrix.zeros(cols, cols); for (j = 0; j < cols; j++) { diag[j][j]=A[j]; } } } if(rows == 1){ diag = Matrix.zeros(cols, cols); for (j = 0; j < cols; j++) { diag[j][j]=A[0][j]; } } else{ if(rows>0 && cols > 0){ r = Math.min(rows,cols); diag = new Array(r); for (j = 0; j < r; j++) { diag[j] = A[j][j]; } } } return diag; }
n/a
function dotDivide(A, B){ var result = A.clone(); return result.div(B); }
n/a
function dotMultiply(A, B){ var result = A.clone(); return result.mul(B); }
n/a
function dotPow(A, b){ if(typeof A==='number' ) return Math.pow(A,b); //console.log(A); var ii = A.rows, jj = A.columns; var result = new Matrix(ii,jj); for (var i = 0; i < ii; i++) { for (var j = 0; j < jj; j++) { result[i][j] = Math.pow(A[i][j],b); } } return result; }
n/a
function exp(A){ if(typeof A==='number' ) return Math.sqrt(A); var ii = A.rows, jj = A.columns; var result = new Matrix(ii,jj); for (var i = 0; i < ii; i++) { for (var j = 0; j < jj; j++) { result[i][j] = Math.exp(A[i][j]); } } return result; }
n/a
function eye(rows, cols){ return Matrix.eye(rows, cols); }
n/a
function inv(A){ if(typeof A ==="number") return 1/A; return A.inverse(); }
n/a
function matrix(A, B){ return new Matrix(A,B); }
n/a
function max(A, B){ if(typeof A==='number' && typeof B ==='number') return Math.max(A,B); var ii = A.rows, jj = A.columns; var result = new Matrix(ii,jj); for (var i = 0; i < ii; i++) { for (var j = 0; j < jj; j++) { if (A[i][j] > B[i][j]) { result[i][j] = A[i][j]; } else{ result[i][j] = B[i][j]; } } } return result; }
n/a
function min(A, B){ if(typeof A==='number' && typeof B ==='number') return Math.min(A,B); var ii = A.rows, jj = A.columns; var result = new Matrix(ii,jj); for (var i = 0; i < ii; i++) { for (var j = 0; j < jj; j++) { if (A[i][j] < B[i][j]) { result[i][j] = A[i][j]; } else{ result[i][j] = B[i][j]; } } } return result; }
n/a
function multiply(A, B){ if(typeof A == 'number'&&typeof B === 'number') return A*B; if(typeof A == 'number') return this.multiply(B,A); var result = A.clone(); if(typeof B === 'number') result.mul(B); else result = result.mmul(B); if(result.rows==1&&result.columns==1) return result[0][0]; else return result; }
n/a
function ones(rows, cols){ return Matrix.ones(rows,cols); }
n/a
function random(rows, cols){ return Matrix.rand(rows,cols); }
n/a
function solve(A, B){ return A.solve(B); }
n/a
function sqrt(A){ if(typeof A==='number' ) return Math.sqrt(A); var ii = A.rows, jj = A.columns; var result = new Matrix(ii,jj); for (var i = 0; i < ii; i++) { for (var j = 0; j < jj; j++) { result[i][j] = Math.sqrt(A[i][j]); } } return result; }
n/a
function subtract(A, B){ if(typeof A == 'number'&&typeof B === 'number') return A-B; if(typeof A == 'number') return this.subtract(B,A); var result = A.clone(); return result.sub(B); }
n/a
function transpose(A){ if(typeof A == 'number') return A; var result = A.clone(); return result.transpose(); }
n/a
function zeros(rows, cols){ return Matrix.zeros(rows, cols); }
n/a
inv = function () { return inverse(this); }
n/a
inverse = function () { return inverse(this); }
n/a
solve = function (other) { return solve(this, other); }
n/a
function XSadd() { var seed = arguments.length <= 0 || arguments[0] === undefined ? Date.now() : arguments[0]; _classCallCheck(this, XSadd); this.state = new Uint32Array(4); this.init(seed); }
n/a
class KernelRidgeRegression extends BaseRegression { constructor(inputs, outputs, options) { super(); if (inputs === true) { // reloading model this.alpha = outputs.alpha; this.inputs = outputs.inputs; this.kernelType = outputs.kernelType; this.kernelOptions = outputs.kernelOptions; this.kernel = new Kernel(outputs.kernelType, outputs.kernelOptions); if (outputs.quality) { this.quality = outputs.quality; } } else { options = Object.assign({}, defaultOptions, options); const kernelFunction = new Kernel(options.kernelType, options.kernelOptions); const K = kernelFunction.compute(inputs); const n = inputs.length; K.add(Matrix.eye(n, n).mul(options.lambda)); this.alpha = solve(K, outputs); this.inputs = inputs; this.kernelType = options.kernelType; this.kernelOptions = options.kernelOptions; this.kernel = kernelFunction; if (options.computeQuality) { this.quality = this.modelQuality(inputs, outputs); } } } _predict(newInputs) { return this.kernel.compute([newInputs], this.inputs).mmul(this.alpha)[0]; } toJSON() { var out = { name: 'kernelRidgeRegression', alpha: this.alpha, inputs: this.inputs, kernelType: this.kernelType, kernelOptions: this.kernelOptions }; if (this.quality) { out.quality = this.quality; } return out; } static load(json) { if (json.name !== 'kernelRidgeRegression') { throw new TypeError('not a KRR model'); } return new KernelRidgeRegression(true, json); } }
n/a
class KernelRidgeRegression extends BaseRegression { constructor(inputs, outputs, options) { super(); if (inputs === true) { // reloading model this.alpha = outputs.alpha; this.inputs = outputs.inputs; this.kernelType = outputs.kernelType; this.kernelOptions = outputs.kernelOptions; this.kernel = new Kernel(outputs.kernelType, outputs.kernelOptions); if (outputs.quality) { this.quality = outputs.quality; } } else { options = Object.assign({}, defaultOptions, options); const kernelFunction = new Kernel(options.kernelType, options.kernelOptions); const K = kernelFunction.compute(inputs); const n = inputs.length; K.add(Matrix.eye(n, n).mul(options.lambda)); this.alpha = solve(K, outputs); this.inputs = inputs; this.kernelType = options.kernelType; this.kernelOptions = options.kernelOptions; this.kernel = kernelFunction; if (options.computeQuality) { this.quality = this.modelQuality(inputs, outputs); } } } _predict(newInputs) { return this.kernel.compute([newInputs], this.inputs).mmul(this.alpha)[0]; } toJSON() { var out = { name: 'kernelRidgeRegression', alpha: this.alpha, inputs: this.inputs, kernelType: this.kernelType, kernelOptions: this.kernelOptions }; if (this.quality) { out.quality = this.quality; } return out; } static load(json) { if (json.name !== 'kernelRidgeRegression') { throw new TypeError('not a KRR model'); } return new KernelRidgeRegression(true, json); } }
n/a
class PolynomialFitRegression2D extends BaseRegression {
/**
* Constructor for the 2D polynomial fitting
*
* @param inputs
* @param outputs
* @param options
* @constructor
*/
constructor(inputs, outputs, options) {
super();
if (inputs === true) { // reloading model
this.coefficients = Matrix.columnVector(outputs.coefficients);
this.order = outputs.order;
if (outputs.r) {
this.r = outputs.r;
this.r2 = outputs.r2;
}
if (outputs.chi2) {
this.chi2 = outputs.chi2;
}
} else {
options = Object.assign({}, defaultOptions, options);
this.order = options.order;
this.coefficients = [];
this.X = inputs;
this.y = outputs;
this.train(this.X, this.y, options);
if (options.computeQuality) {
this.quality = this.modelQuality(inputs, outputs);
}
}
}
/**
* Function that fits the model given the data(X) and predictions(y).
* The third argument is an object with the following options:
* * order: order of the polynomial to fit.
*
* @param {Matrix} X - A matrix with n rows and 2 columns.
* @param {Matrix} y - A vector of the prediction values.
*/
train(X, y) {
if (!Matrix.isMatrix(X)) X = new Matrix(X);
if (!Matrix.isMatrix(y)) y = Matrix.columnVector(y);
//Perhaps y is transpose
if (y.rows !== X.rows) {
y = y.transpose();
}
if (X.columns !== 2) {
throw new RangeError('You give X with ' + X.columns + ' columns and it must be 2');
}
if (X.rows !== y.rows) {
throw new RangeError('X and y must have the same rows');
}
var examples = X.rows;
var coefficients = ((this.order + 2) * (this.order + 1)) / 2;
this.coefficients = new Array(coefficients);
var x1 = X.getColumnVector(0);
var x2 = X.getColumnVector(1);
var scaleX1 = 1.0 / x1.clone().apply(abs).max();
var scaleX2 = 1.0 / x2.clone().apply(abs).max();
var scaleY = 1.0 / y.clone().apply(abs).max();
x1.mulColumn(0, scaleX1);
x2.mulColumn(0, scaleX2);
y.mulColumn(0, scaleY);
var A = new Matrix(examples, coefficients);
var col = 0;
for (var i = 0; i <= this.order; ++i) {
var limit = this.order - i;
for (var j = 0; j <= limit; ++j) {
var result = powColVector(x1, i).mulColumnVector(powColVector(x2, j));
A.setColumn(col, result);
col++;
}
}
var svd = new SVD(A.transpose(), {
computeLeftSingularVectors: true,
computeRightSingularVectors: true,
autoTranspose: false
});
var qqs = Matrix.rowVector(svd.diagonal);
qqs = qqs.apply(function (i, j) {
if (this[i][j] >= 1e-15) this[i][j] = 1 / this[i][j];
else this[i][j] = 0;
});
var qqs1 = Matrix.zeros(examples, coefficients);
for (i = 0; i < coefficients; ++i) {
qqs1[i][i] = qqs[0][i];
}
qqs = qqs1;
var U = svd.rightSingularVectors;
var V = svd.leftSingularVectors;
this.coefficients = V.mmul(qqs.transpose()).mmul(U.transpose()).mmul(y);
col = 0;
for (i = 0; i <= coefficients; ++i) {
limit = this.order - i;
for (j = 0; j <= limit; ++j) {
this.coefficients[col][0] = (this.coefficients[col][0] * Math.pow(scaleX1, i) * Math.pow(scaleX2, j)) / scaleY;
col++;
}
}
}
_predict(newInputs) {
var x1 = newInputs[0];
var x2 = newInputs[1];
var y = 0;
var column = 0;
for (var i = 0; i <= this.order; i++) {
for (var j = 0; j <= this.order - i; j++) {
y += Math.pow(x1, i) * ( ...
n/a
class SimpleLinearRegression extends BaseRegression { constructor(x, y, options) { options = options || {}; super(); if (x === true) { this.slope = y.slope; this.intercept = y.intercept; this.quality = y.quality || {}; if (y.quality.r) { this.quality.r = y.quality.r; this.quality.r2 = y.quality.r2; } if (y.quality.chi2) { this.quality.chi2 = y.quality.chi2; } } else { var n = x.length; if (n !== y.length) { throw new RangeError('input and output array have a different length'); } var xSum = 0; var ySum = 0; var xSquared = 0; var xY = 0; for (var i = 0; i < n; i++) { xSum += x[i]; ySum += y[i]; xSquared += x[i] * x[i]; xY += x[i] * y[i]; } var numerator = (n * xY - xSum * ySum); this.slope = numerator / (n * xSquared - xSum * xSum); this.intercept = (1 / n) * ySum - this.slope * (1 / n) * xSum; this.coefficients = [this.intercept, this.slope]; if (options.computeQuality) { this.quality = this.modelQuality(x, y); } } } toJSON() { var out = { name: 'simpleLinearRegression', slope: this.slope, intercept: this.intercept }; if (this.quality) { out.quality = this.quality; } return out; } _predict(input) { return this.slope * input + this.intercept; } computeX(input) { return (input - this.intercept) / this.slope; } toString(precision) { var result = 'f(x) = '; if (this.slope) { var xFactor = maybeToPrecision(this.slope, precision); result += (Math.abs(xFactor - 1) < 1e-5 ? '' : xFactor + ' * ') + 'x'; if (this.intercept) { var absIntercept = Math.abs(this.intercept); var operator = absIntercept === this.intercept ? '+' : '-'; result += ' ' + operator + ' ' + maybeToPrecision(absIntercept, precision); } } else { result += maybeToPrecision(this.intercept, precision); } return result; } toLaTeX(precision) { return this.toString(precision); } static load(json) { if (json.name !== 'simpleLinearRegression') { throw new TypeError('not a SLR model'); } return new SimpleLinearRegression(true, json); } }
n/a
class SimpleLinearRegression extends BaseRegression { constructor(x, y, options) { options = options || {}; super(); if (x === true) { this.slope = y.slope; this.intercept = y.intercept; this.quality = y.quality || {}; if (y.quality.r) { this.quality.r = y.quality.r; this.quality.r2 = y.quality.r2; } if (y.quality.chi2) { this.quality.chi2 = y.quality.chi2; } } else { var n = x.length; if (n !== y.length) { throw new RangeError('input and output array have a different length'); } var xSum = 0; var ySum = 0; var xSquared = 0; var xY = 0; for (var i = 0; i < n; i++) { xSum += x[i]; ySum += y[i]; xSquared += x[i] * x[i]; xY += x[i] * y[i]; } var numerator = (n * xY - xSum * ySum); this.slope = numerator / (n * xSquared - xSum * xSum); this.intercept = (1 / n) * ySum - this.slope * (1 / n) * xSum; this.coefficients = [this.intercept, this.slope]; if (options.computeQuality) { this.quality = this.modelQuality(x, y); } } } toJSON() { var out = { name: 'simpleLinearRegression', slope: this.slope, intercept: this.intercept }; if (this.quality) { out.quality = this.quality; } return out; } _predict(input) { return this.slope * input + this.intercept; } computeX(input) { return (input - this.intercept) / this.slope; } toString(precision) { var result = 'f(x) = '; if (this.slope) { var xFactor = maybeToPrecision(this.slope, precision); result += (Math.abs(xFactor - 1) < 1e-5 ? '' : xFactor + ' * ') + 'x'; if (this.intercept) { var absIntercept = Math.abs(this.intercept); var operator = absIntercept === this.intercept ? '+' : '-'; result += ' ' + operator + ' ' + maybeToPrecision(absIntercept, precision); } } else { result += maybeToPrecision(this.intercept, precision); } return result; } toLaTeX(precision) { return this.toString(precision); } static load(json) { if (json.name !== 'simpleLinearRegression') { throw new TypeError('not a SLR model'); } return new SimpleLinearRegression(true, json); } }
n/a
class TheilSenRegression extends BaseRegression {
/**
* Theil–Sen estimator
* https://en.wikipedia.org/wiki/Theil%E2%80%93Sen_estimator
* @param {Array<number>} x
* @param {Array<number>} y
* @param {object} options
* @constructor
*/
constructor(x, y, options) {
options = options || {};
super();
if (x === true) {
// loads the model
this.slope = y.slope;
this.intercept = y.intercept;
this.quality = Object.assign({}, y.quality, this.quality);
} else {
// creates the model
let len = x.length;
if (len !== y.length) {
throw new RangeError('Input and output array have a different length');
}
let slopes = new Array(len * len);
let count = 0;
for (let i = 0; i < len; ++i) {
for (let j = i + 1; j < len; ++j) {
if (x[i] !== x[j]) {
slopes[count++] = (y[j] - y[i]) / (x[j] - x[i]);
}
}
}
slopes.length = count;
let medianSlope = median(slopes);
let cuts = new Array(len);
for (let i = 0; i < len; ++i) {
cuts[i] = y[i] - medianSlope * x[i];
}
this.slope = medianSlope;
this.intercept = median(cuts);
this.coefficients = [this.intercept, this.slope];
if (options.computeQuality) {
this.quality = this.modelQuality(x, y);
}
}
}
toJSON() {
var out = {
name: 'TheilSenRegression',
slope: this.slope,
intercept: this.intercept
};
if (this.quality) {
out.quality = this.quality;
}
return out;
}
_predict(input) {
return this.slope * input + this.intercept;
}
computeX(input) {
return (input - this.intercept) / this.slope;
}
toString(precision) {
var result = 'f(x) = ';
if (this.slope) {
var xFactor = maybeToPrecision(this.slope, precision);
result += (Math.abs(xFactor - 1) < 1e-5 ? '' : xFactor + ' * ') + 'x';
if (this.intercept) {
var absIntercept = Math.abs(this.intercept);
var operator = absIntercept === this.intercept ? '+' : '-';
result += ' ' + operator + ' ' + maybeToPrecision(absIntercept, precision);
}
} else {
result += maybeToPrecision(this.intercept, precision);
}
return result;
}
toLaTeX(precision) {
return this.toString(precision);
}
static load(json) {
if (json.name !== 'TheilSenRegression') {
throw new TypeError('not a Theil-Sen model');
}
return new TheilSenRegression(true, json);
}
}
n/a
class ExpRegression extends BaseRegression {
/**
* @constructor
* @param {Array<number>} x - Independent variable
* @param {Array<number>} y - Dependent variable
* @param {object} options
*/
constructor(x, y, options) {
super();
let opt = options || {};
if (x === true) { // reloading model
this.A = y.A;
this.C = y.C;
if (y.quality) {
this.quality = y.quality;
}
} else {
var n = x.length;
if (n !== y.length) {
throw new RangeError('input and output array have a different length');
}
var yl = new Array(n);
for (var i = 0; i < n; i++) {
yl[i] = Math.log(y[i]);
}
var linear = new SimpleLinearRegression(x, yl, {computeCoefficient: false});
this.A = linear.slope;
this.C = Math.exp(linear.intercept);
if (opt.computeQuality) {
this.quality = this.modelQuality(x, y);
}
}
}
_predict(newInputs) {
return this.C * Math.exp(newInputs * this.A);
}
toJSON() {
var out = {name: 'expRegression', A: this.A, C: this.C};
if (this.quality) {
out.quality = this.quality;
}
return out;
}
toString(precision) {
return 'f(x) = ' + maybeToPrecision(this.C, precision) + ' * exp(' + maybeToPrecision(this.A, precision) + ' * x)';
}
toLaTeX(precision) {
if (this.A >= 0) {
return 'f(x) = ' + maybeToPrecision(this.C, precision) + 'e^{' + maybeToPrecision(this.A, precision) + 'x}';
} else {
return 'f(x) = \\frac{' + maybeToPrecision(this.C, precision) + '}{e^{' + maybeToPrecision(-this.A, precision) + 'x}}';
}
}
static load(json) {
if (json.name !== 'expRegression') {
throw new TypeError('not a exp regression model');
}
return new ExpRegression(true, json);
}
}
n/a
class PolynomialRegression extends BaseRegression {
/**
* @constructor
* @param x: Independent variable
* @param y: Dependent variable
* @param M: Maximum degree of the polynomial
* @param options
*/
constructor(x, y, M, options) {
super();
let opt = options || {};
if (x === true) { // reloading model
this.coefficients = y.coefficients;
this.powers = y.powers;
this.M = y.M;
if (y.quality) {
this.quality = y.quality;
}
} else {
var n = x.length;
if (n !== y.length) {
throw new RangeError('input and output array have a different length');
}
let powers;
if (Array.isArray(M)) {
powers = M;
M = powers.length;
} else {
M++;
powers = new Array(M);
for (k = 0; k < M; k++) {
powers[k] = k;
}
}
var F = new Matrix(n, M);
var Y = new Matrix([y]);
var k, i;
for (k = 0; k < M; k++) {
for (i = 0; i < n; i++) {
if (powers[k] === 0) {
F[i][k] = 1;
} else {
F[i][k] = Math.pow(x[i], powers[k]);
}
}
}
var FT = F.transposeView();
var A = FT.mmul(F);
var B = FT.mmul(Y.transposeView());
this.coefficients = solve(A, B).to1DArray();
this.powers = powers;
this.M = M - 1;
if (opt.computeQuality) {
this.quality = this.modelQuality(x, y);
}
}
}
_predict(x) {
var y = 0;
for (var k = 0; k < this.powers.length; k++) {
y += this.coefficients[k] * Math.pow(x, this.powers[k]);
}
return y;
}
toJSON() {
var out = {name: 'polynomialRegression',
coefficients: this.coefficients,
powers: this.powers,
M: this.M
};
if (this.quality) {
out.quality = this.quality;
}
return out;
}
toString(precision) {
return this._toFormula(precision, false);
}
toLaTeX(precision) {
return this._toFormula(precision, true);
}
_toFormula(precision, isLaTeX) {
var sup = '^';
var closeSup = '';
var times = ' * ';
if (isLaTeX) {
sup = '^{';
closeSup = '}';
times = '';
}
var fn = '', str;
for (var k = 0; k < this.coefficients.length; k++) {
str = '';
if (this.coefficients[k] !== 0) {
if (this.powers[k] === 0) {
str = maybeToPrecision(this.coefficients[k], precision);
} else {
if (this.powers[k] === 1) {
str = maybeToPrecision(this.coefficients[k], precision) + times + 'x';
} else {
str = 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;
}
if (fn.charAt(0) === ' + ') {
fn = fn.slice(1);
}
return 'f(x) = ' + fn;
}
static load(json) {
if (json.name !== 'polynomialRegression') {
throw new TypeError('not a polynomial regression model');
}
return new PolynomialRegression(true, json);
}
}
n/a
class PotentialRegression extends BaseRegression {
/**
* @constructor
* @param x: Independent variable
* @param y: Dependent variable
* @param M
* @param options
*/
constructor(x, y, M, options) {
super();
let opt = options || {};
if (x === true) { // reloading model
this.A = y.A;
this.M = y.M;
if (y.quality) {
this.quality = y.quality;
}
} else {
var n = x.length;
if (n !== y.length) {
throw new RangeError('input and output array have a different length');
}
var linear = new PolynomialRegression(x, y, [M], {computeCoefficient: true});
this.A = linear.coefficients[0];
this.M = M;
if (opt.computeQuality) {
this.quality = this.modelQuality(x, y);
}
}
}
_predict(x) {
return this.A * Math.pow(x, this.M);
}
toJSON() {
var out = {name: 'potentialRegression', A: this.A, M: this.M};
if (this.quality) {
out.quality = this.quality;
}
return out;
}
toString(precision) {
return 'f(x) = ' + maybeToPrecision(this.A, precision) + ' * x^' + this.M;
}
toLaTeX(precision) {
if (this.M >= 0) {
return 'f(x) = ' + maybeToPrecision(this.A, precision) + 'x^{' + this.M + '}';
} else {
return 'f(x) = \\frac{' + maybeToPrecision(this.A, precision) + '}{x^{' + (-this.M) + '}}';
}
}
static load(json) {
if (json.name !== 'potentialRegression') {
throw new TypeError('not a potential regression model');
}
return new PotentialRegression(true, json);
}
}
n/a
class PowerRegression extends BaseRegression {
/**
* @constructor
* @param x: Independent variable
* @param y: Dependent variable
* @param options
*/
constructor(x, y, options) {
super();
let opt = options || {};
if (x === true) { // reloading model
this.A = y.A;
this.B = y.B;
this.quality = y.quality || {};
if (y.quality.r) {
this.quality.r = y.quality.r;
this.quality.r2 = y.quality.r2;
}
if (y.quality.chi2) {
this.quality.chi2 = y.quality.chi2;
}
} else {
var n = x.length;
if (n !== y.length) {
throw new RangeError('input and output array have a different length');
}
var xl = new Array(n), yl = new Array(n);
for (var i = 0; i < n; i++) {
xl[i] = Math.log(x[i]);
yl[i] = Math.log(y[i]);
}
var linear = new SimpleLinearRegression(xl, yl, {computeCoefficient: false});
this.A = Math.exp(linear.intercept);
this.B = linear.slope;
if (opt.computeQuality) {
this.quality = this.modelQuality(x, y);
}
}
}
_predict(newInputs) {
return this.A * Math.pow(newInputs, this.B);
}
toJSON() {
var out = {name: 'powerRegression', A: this.A, B: this.B};
if (this.quality) {
out.quality = this.quality;
}
return out;
}
toString(precision) {
return 'f(x) = ' + maybeToPrecision(this.A, precision) + ' * x^' + maybeToPrecision(this.B, precision);
}
toLaTeX(precision) {
if (this.B >= 0) {
return 'f(x) = ' + maybeToPrecision(this.A, precision) + 'x^{' + maybeToPrecision(this.B, precision) + '}';
} else {
return 'f(x) = \\frac{' + maybeToPrecision(this.A, precision) + '}{x^{' + maybeToPrecision(-this.B, precision) + '}}';
}
}
static load(json) {
if (json.name !== 'powerRegression') {
throw new TypeError('not a power regression model');
}
return new PowerRegression(true, json);
}
}
n/a
function KNN(reload, model) { if(reload) { this.kdtree = model.kdtree; this.k = model.k; this.classes = model.classes; } }
n/a
function NaiveBayes(reload, model) { if(reload) { this.means = model.means; this.calculateProbabilities = model.calculateProbabilities; } }
n/a
class PLS {
constructor(X, Y) {
if (X === true) {
const model = Y;
this.meanX = model.meanX;
this.stdDevX = model.stdDevX;
this.meanY = model.meanY;
this.stdDevY = model.stdDevY;
this.PBQ = Matrix.checkMatrix(model.PBQ);
this.R2X = model.R2X;
} else {
if (X.length !== Y.length)
throw new RangeError('The number of X rows must be equal to the number of Y rows');
const resultX = Utils.featureNormalize(X);
this.X = resultX.result;
this.meanX = resultX.means;
this.stdDevX = resultX.std;
const resultY = Utils.featureNormalize(Y);
this.Y = resultY.result;
this.meanY = resultY.means;
this.stdDevY = resultY.std;
}
}
/**
* Fits the model with the given data and predictions, in this function is calculated the
* following outputs:
*
* T - Score matrix of X
* P - Loading matrix of X
* U - Score matrix of Y
* Q - Loading matrix of Y
* B - Matrix of regression coefficient
* W - Weight matrix of X
*
* @param {Object} options - recieves the latentVectors and the tolerance of each step of the PLS
*/
train(options) {
if(options === undefined) options = {};
var latentVectors = options.latentVectors;
if (latentVectors === undefined) {
latentVectors = Math.min(this.X.length - 1, this.X[0].length);
}
var tolerance = options.tolerance;
if (tolerance === undefined) {
tolerance = 1e-5;
}
var X = this.X;
var Y = this.Y;
var rx = X.rows;
var cx = X.columns;
var ry = Y.rows;
var cy = Y.columns;
var ssqXcal = X.clone().mul(X).sum(); // for the r²
var sumOfSquaresY = Y.clone().mul(Y).sum();
var n = latentVectors; //Math.max(cx, cy); // components of the pls
var T = Matrix.zeros(rx, n);
var P = Matrix.zeros(cx, n);
var U = Matrix.zeros(ry, n);
var Q = Matrix.zeros(cy, n);
var B = Matrix.zeros(n, n);
var W = P.clone();
var k = 0;
while(Utils.norm(Y) > tolerance && k < n) {
var transposeX = X.transpose();
var transposeY = Y.transpose();
var tIndex = maxSumColIndex(X.clone().mulM(X));
var uIndex = maxSumColIndex(Y.clone().mulM(Y));
var t1 = X.getColumnVector(tIndex);
var u = Y.getColumnVector(uIndex);
var t = Matrix.zeros(rx, 1);
while(Utils.norm(t1.clone().sub(t)) > tolerance) {
var w = transposeX.mmul(u);
w.div(Utils.norm(w));
t = t1;
t1 = X.mmul(w);
var q = transposeY.mmul(t1);
q.div(Utils.norm(q));
u = Y.mmul(q);
}
t = t1;
var num = transposeX.mmul(t);
var den = (t.transpose().mmul(t))[0][0];
var p = num.div(den);
var pnorm = Utils.norm(p);
p.div(pnorm);
t.mul(pnorm);
w.mul(pnorm);
num = u.transpose().mmul(t);
den = (t.transpose().mmul(t))[0][0];
var b = (num.div(den))[0][0];
X.sub(t.mmul(p.transpose()));
Y.sub(t.clone().mul(b).mmul(q.transpose()));
T.setColumn(k, t);
P.setColumn(k, p);
U.setColumn(k, u);
Q.setColumn(k, q);
W.setColumn(k, w);
B[k][k] = b;
k++;
}
k--;
T = T.subMatrix(0, T.rows - 1, 0, k);
P = P.subMatrix(0, P.rows - 1, 0, k);
U = U.subMatrix(0, U.rows - 1, 0, k);
Q = Q.subMatrix(0, Q.rows - 1, 0, k);
W = W.subMatrix(0, W.rows - 1, 0, k);
B = B.subMatrix(0, k, 0, k);
// TODO: review of R2Y
//this.R2Y = t.transpose().mmul(t).mul(q[k][0]*q[k][0]).divS(ssqYcal)[0][0]; ...
n/a
function SVM(options) { this.options = Object.assign({}, defaultOptions, options); this.kernel = new Kernel(this.options.kernel, this.options.kernelOptions); this.b = 0; }
n/a
kFold = function (Classifier, features, labels, classifierOptions, k) { check(features, labels); const distinct = getDistinct(labels); const confusionMatrix = initMatrix(distinct.length, distinct.length); var N = features.length; var allIdx = new Array(N); for (var i = 0; i < N; i++) { allIdx[i] = i; } var l = Math.floor(N / k); // create random k-folds var current = []; var folds = []; while (allIdx.length) { var randi = Math.floor(Math.random() * allIdx.length); current.push(allIdx[randi]); allIdx.splice(randi, 1); if (current.length === l) { folds.push(current); current = []; } } if (current.length) folds.push(current); folds = folds.slice(0, k); for (i = 0; i < folds.length; i++) { var testIdx = folds[i]; var trainIdx = []; for (var j = 0; j < folds.length; j++) { if (j !== i) trainIdx = trainIdx.concat(folds[j]); } validate(Classifier, features, labels, classifierOptions, testIdx, trainIdx, confusionMatrix, distinct); } return new ConfusionMatrix(confusionMatrix, distinct); }
n/a
leaveOneOut = function (Classifier, features, labels, classifierOptions) { return CV.leavePOut(Classifier, features, labels, classifierOptions, 1); }
n/a
leavePOut = function (Classifier, features, labels, classifierOptions, p) { check(features, labels); const distinct = getDistinct(labels); const confusionMatrix = initMatrix(distinct.length, distinct.length); var i, N = features.length; var gen = combinations(p, N); var allIdx = new Array(N); for (i = 0; i < N; i++) { allIdx[i] = i; } for (const testIdx of gen) { var trainIdx = allIdx.slice(); for (i = testIdx.length - 1; i >= 0; i--) { trainIdx.splice(testIdx[i], 1); } validate(Classifier, features, labels, classifierOptions, testIdx, trainIdx, confusionMatrix, distinct); } return new ConfusionMatrix(confusionMatrix, distinct); }
n/a
function KNN(reload, model) { if(reload) { this.kdtree = model.kdtree; this.k = model.k; this.classes = model.classes; } }
n/a
load = function (model) { if(model.modelName !== "KNN") throw new RangeError("The given model is invalid!"); return new KNN(true, model); }
...
This method is optional.
It should return a value that represents the quality of a predictor.
### predictor.toJSON()
This method should return plain JS Object that enables to reload the current predictor.
### Predictor.load(json)
This static method should return a new predictor instance that is ready to make predictions. The `json`
parameter is the object returned by an earlier call of `toJSON`.
## Commit Guidelines
The rules are based on the [AngularJS commit guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit
). This leads to **more readable messages** that are easy to follow when looking through the **project history**.
...
export = function () { return { modelName: "KNN", kdtree: this.kdtree, k: this.k, classes: this.classes }; }
n/a
getSinglePrediction = function (currentCase) { var nearestPoints = this.kdtree.nearest(currentCase, this.k); var pointsPerClass = new Array(this.classes); var predictedClass = -1; var maxPoints = -1; var lastElement = nearestPoints[0][0].length - 1; for(var i = 0; i < pointsPerClass.length; ++i) { pointsPerClass[i] = 0; } for(i = 0; i < nearestPoints.length; ++i) { var currentClass = nearestPoints[i][0][lastElement]; var currentPoints = ++pointsPerClass[currentClass]; if(currentPoints > maxPoints) { predictedClass = currentClass; maxPoints = currentPoints; } } return predictedClass; }
n/a
predict = function (dataset) { var predictions = new Array(dataset.length); for(var i = 0; i < dataset.length; ++i) { predictions[i] = this.getSinglePrediction(dataset[i]); } return predictions; }
...
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
This method is optional.
It should return a value that represents the quality of a predictor.
...
train = function (trainingSet, trainingLabels, options) { if(options === undefined) options = {}; if(options.distance === undefined) options.distance = Distances.distance.euclidean; if(options.k === undefined) options.k = trainingSet[0].length + 1; var classes = 0; var exist = new Array(1000); var j = 0; for(var i = 0; i < trainingLabels.length; ++i) { if(exist.indexOf(trainingLabels[i]) === -1) { classes++; exist[j] = trainingLabels[i]; j++; } } // copy dataset var points = new Array(trainingSet.length); for(i = 0; i < points.length; ++i) { points[i] = trainingSet[i].slice(); } this.features = trainingSet[0].length; for(i = 0; i < trainingLabels.length; ++i) { points[i].push(trainingLabels[i]); } var dimensions = new Array(trainingSet[0].length); for(i = 0; i < dimensions.length; ++i) { dimensions[i] = i; } this.kdtree = new KDTree(points, options.distance, dimensions); this.k = options.k; this.classes = classes; }
...
Predictors are classes which implement the following interface.
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
...
function NaiveBayes(reload, model) { if(reload) { this.means = model.means; this.calculateProbabilities = model.calculateProbabilities; } }
n/a
load = function (model) { if(model.modelName !== 'NaiveBayes') throw new RangeError("The given model is invalid!"); return new NaiveBayes(true, model); }
...
This method is optional.
It should return a value that represents the quality of a predictor.
### predictor.toJSON()
This method should return plain JS Object that enables to reload the current predictor.
### Predictor.load(json)
This static method should return a new predictor instance that is ready to make predictions. The `json`
parameter is the object returned by an earlier call of `toJSON`.
## Commit Guidelines
The rules are based on the [AngularJS commit guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit
). This leads to **more readable messages** that are easy to follow when looking through the **project history**.
...
function separateClasses(X, y) { var features = X.columns; var classes = 0; var totalPerClasses = new Array(100); // max upperbound of classes for (var i = 0; i < y.length; i++) { if(totalPerClasses[y[i]] === undefined) { totalPerClasses[y[i]] = 0; classes++; } totalPerClasses[y[i]]++; } var separatedClasses = new Array(classes); var currentIndex = new Array(classes); for(i = 0; i < classes; ++i) { separatedClasses[i] = new Matrix(totalPerClasses[i], features); currentIndex[i] = 0; } for(i = 0; i < X.rows; ++i) { separatedClasses[y[i]].setRow(currentIndex[y[i]], X.getRow(i)); currentIndex[y[i]]++; } return separatedClasses; }
n/a
export = function () { return { modelName: "NaiveBayes", means: this.means, calculateProbabilities: this.calculateProbabilities }; }
n/a
predict = function (dataset) { if(dataset[0].length === this.calculateProbabilities[0].length) throw new RangeError('the dataset must have the same features as the training set'); var predictions = new Array(dataset.length); for(var i = 0; i < predictions.length; ++i) { predictions[i] = getCurrentClass(dataset[i], this.means, this.calculateProbabilities); } return predictions; }
...
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
This method is optional.
It should return a value that represents the quality of a predictor.
...
train = function (trainingSet, trainingLabels) { var C1 = Math.sqrt(2*Math.PI); // constant to precalculate the squared root if(!Matrix.isMatrix(trainingSet)) trainingSet = new Matrix(trainingSet); else trainingSet = trainingSet.clone(); if(trainingSet.rows !== trainingLabels.length) throw new RangeError("the size of the training set and the training labels must be the same."); var separatedClasses = separateClasses(trainingSet, trainingLabels); var calculateProbabilities = new Array(separatedClasses.length); this.means = new Array(separatedClasses.length); for(var i = 0; i < separatedClasses.length; ++i) { var means = Stat.matrix.mean(separatedClasses[i]); var std = Stat.matrix.standardDeviation(separatedClasses[i], means); var logPriorProbability = Math.log(separatedClasses[i].rows / trainingSet.rows); calculateProbabilities[i] = new Array(means.length + 1); calculateProbabilities[i][0] = logPriorProbability; for(var j = 1; j < means.length + 1; ++j) { var currentStd = std[j - 1]; calculateProbabilities[i][j] = [(1 / (C1 * currentStd)), -2*currentStd*currentStd]; } this.means[i] = means; } this.calculateProbabilities = calculateProbabilities; }
...
Predictors are classes which implement the following interface.
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
...
class PLS {
constructor(X, Y) {
if (X === true) {
const model = Y;
this.meanX = model.meanX;
this.stdDevX = model.stdDevX;
this.meanY = model.meanY;
this.stdDevY = model.stdDevY;
this.PBQ = Matrix.checkMatrix(model.PBQ);
this.R2X = model.R2X;
} else {
if (X.length !== Y.length)
throw new RangeError('The number of X rows must be equal to the number of Y rows');
const resultX = Utils.featureNormalize(X);
this.X = resultX.result;
this.meanX = resultX.means;
this.stdDevX = resultX.std;
const resultY = Utils.featureNormalize(Y);
this.Y = resultY.result;
this.meanY = resultY.means;
this.stdDevY = resultY.std;
}
}
/**
* Fits the model with the given data and predictions, in this function is calculated the
* following outputs:
*
* T - Score matrix of X
* P - Loading matrix of X
* U - Score matrix of Y
* Q - Loading matrix of Y
* B - Matrix of regression coefficient
* W - Weight matrix of X
*
* @param {Object} options - recieves the latentVectors and the tolerance of each step of the PLS
*/
train(options) {
if(options === undefined) options = {};
var latentVectors = options.latentVectors;
if (latentVectors === undefined) {
latentVectors = Math.min(this.X.length - 1, this.X[0].length);
}
var tolerance = options.tolerance;
if (tolerance === undefined) {
tolerance = 1e-5;
}
var X = this.X;
var Y = this.Y;
var rx = X.rows;
var cx = X.columns;
var ry = Y.rows;
var cy = Y.columns;
var ssqXcal = X.clone().mul(X).sum(); // for the r²
var sumOfSquaresY = Y.clone().mul(Y).sum();
var n = latentVectors; //Math.max(cx, cy); // components of the pls
var T = Matrix.zeros(rx, n);
var P = Matrix.zeros(cx, n);
var U = Matrix.zeros(ry, n);
var Q = Matrix.zeros(cy, n);
var B = Matrix.zeros(n, n);
var W = P.clone();
var k = 0;
while(Utils.norm(Y) > tolerance && k < n) {
var transposeX = X.transpose();
var transposeY = Y.transpose();
var tIndex = maxSumColIndex(X.clone().mulM(X));
var uIndex = maxSumColIndex(Y.clone().mulM(Y));
var t1 = X.getColumnVector(tIndex);
var u = Y.getColumnVector(uIndex);
var t = Matrix.zeros(rx, 1);
while(Utils.norm(t1.clone().sub(t)) > tolerance) {
var w = transposeX.mmul(u);
w.div(Utils.norm(w));
t = t1;
t1 = X.mmul(w);
var q = transposeY.mmul(t1);
q.div(Utils.norm(q));
u = Y.mmul(q);
}
t = t1;
var num = transposeX.mmul(t);
var den = (t.transpose().mmul(t))[0][0];
var p = num.div(den);
var pnorm = Utils.norm(p);
p.div(pnorm);
t.mul(pnorm);
w.mul(pnorm);
num = u.transpose().mmul(t);
den = (t.transpose().mmul(t))[0][0];
var b = (num.div(den))[0][0];
X.sub(t.mmul(p.transpose()));
Y.sub(t.clone().mul(b).mmul(q.transpose()));
T.setColumn(k, t);
P.setColumn(k, p);
U.setColumn(k, u);
Q.setColumn(k, q);
W.setColumn(k, w);
B[k][k] = b;
k++;
}
k--;
T = T.subMatrix(0, T.rows - 1, 0, k);
P = P.subMatrix(0, P.rows - 1, 0, k);
U = U.subMatrix(0, U.rows - 1, 0, k);
Q = Q.subMatrix(0, Q.rows - 1, 0, k);
W = W.subMatrix(0, W.rows - 1, 0, k);
B = B.subMatrix(0, k, 0, k);
// TODO: review of R2Y
//this.R2Y = t.transpose().mmul(t).mul(q[k][0]*q[k][0]).divS(ssqYcal)[0][0]; ...
n/a
function OPLS(dataset, predictions, numberOSC) { var X = new Matrix(dataset); var y = new Matrix(predictions); X = Utils.featureNormalize(X).result; y = Utils.featureNormalize(y).result; var rows = X.rows; var columns = X.columns; var sumOfSquaresX = X.clone().mul(X).sum(); var w = X.transpose().mmul(y); w.div(Utils.norm(w)); var orthoW = new Array(numberOSC); var orthoT = new Array(numberOSC); var orthoP = new Array(numberOSC); for (var i = 0; i < numberOSC; i++) { var t = X.mmul(w); var numerator = X.transpose().mmul(t); var denominator = t.transpose().mmul(t)[0][0]; var p = numerator.div(denominator); numerator = w.transpose().mmul(p)[0][0]; denominator = w.transpose().mmul(w)[0][0]; var wOsc = p.sub(w.clone().mul(numerator / denominator)); wOsc.div(Utils.norm(wOsc)); var tOsc = X.mmul(wOsc); numerator = X.transpose().mmul(tOsc); denominator = tOsc.transpose().mmul(tOsc)[0][0]; var pOsc = numerator.div(denominator); X.sub(tOsc.mmul(pOsc.transpose())); orthoW[i] = wOsc.getColumn(0); orthoT[i] = tOsc.getColumn(0); orthoP[i] = pOsc.getColumn(0); } this.Xosc = X; var sumOfSquaresXosx = this.Xosc.clone().mul(this.Xosc).sum(); this.R2X = 1 - sumOfSquaresXosx/sumOfSquaresX; this.W = orthoW; this.T = orthoT; this.P = orthoP; this.numberOSC = numberOSC; }
n/a
correctDataset = function (dataset) { var X = new Matrix(dataset); var sumOfSquaresX = X.clone().mul(X).sum(); for (var i = 0; i < this.numberOSC; i++) { var currentW = this.W.getColumnVector(i); var currentP = this.P.getColumnVector(i); var t = X.mmul(currentW); X.sub(t.mmul(currentP)); } var sumOfSquaresXosx = X.clone().mul(X).sum(); var R2X = 1 - sumOfSquaresXosx / sumOfSquaresX; return { datasetOsc: X, R2Dataset: R2X }; }
n/a
function SVM(options) { this.options = Object.assign({}, defaultOptions, options); this.kernel = new Kernel(this.options.kernel, this.options.kernelOptions); this.b = 0; }
n/a
load = function (model) { this._loaded = true; this._trained = false; var svm = new SVM(model.options); if (model.options.kernel === 'linear') { svm.W = model.W.slice(); svm.D = svm.W.length; } else { svm.X = model.X.slice(); svm.Y = model.Y.slice(); svm.alphas = model.alphas.slice(); svm.N = svm.X.length; svm.D = svm.X[0].length; } svm.minMax = model.minMax; svm.b = model.b; svm._loaded = true; svm._trained = false; return svm; }
...
This method is optional.
It should return a value that represents the quality of a predictor.
### predictor.toJSON()
This method should return plain JS Object that enables to reload the current predictor.
### Predictor.load(json)
This static method should return a new predictor instance that is ready to make predictions. The `json`
parameter is the object returned by an earlier call of `toJSON`.
## Commit Guidelines
The rules are based on the [AngularJS commit guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit
). This leads to **more readable messages** that are easy to follow when looking through the **project history**.
...
_applyWhitening = function (features) { if (!this.minMax) throw new Error('Could not apply whitening'); var whitened = new Array(features.length); for (var j = 0; j < features.length; j++) { whitened[j] = (features[j] - this.minMax[j].min) / (this.minMax[j].max - this.minMax[j].min); } return whitened; }
n/a
_marginOnePrecomputed = function (index, kernel) { var ans = this.b, i; for (i = 0; i < this.N; i++) { ans += this.alphas[i] * this.Y[i] * kernel[index][i]; } return ans; }
n/a
margin = function (features) { if (Array.isArray(features)) { return features.map(this.marginOne.bind(this)); } else { return this.marginOne(features); } }
n/a
marginOne = function (features, noWhitening) { // Apply normalization if (this.options.whitening && !noWhitening) { features = this._applyWhitening(features); } var ans = this.b, i; if (this.options.kernel === 'linear' && this.W) { // Use weights, it's faster for (i = 0; i < this.W.length; i++) { ans += this.W[i] * features[i]; } } else { for (i = 0; i < this.N; i++) { ans += this.alphas[i] * this.Y[i] * this.kernel.compute([features], [this.X[i]])[0][0]; } } return ans; }
n/a
predict = function (features) { if (!this._trained && !this._loaded) throw new Error('Cannot predict, you need to train the SVM first'); if (Array.isArray(features) && Array.isArray(features[0])) { return features.map(this.predictOne.bind(this)); } else { return this.predictOne(features); } }
...
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
This method is optional.
It should return a value that represents the quality of a predictor.
...
predictOne = function (p) { var margin = this.marginOne(p); return margin > 0 ? 1 : -1; }
n/a
supportVectors = function () { if (!this._trained && !this._loaded) throw new Error('Cannot get support vectors, you need to train the SVM first'); if (this._loaded && this.options.kernel === 'linear') throw new Error('Cannot get support vectors from saved linear model, you need to train the SVM to have them'); return this._supportVectorIdx; }
n/a
toJSON = function () { if (!this._trained && !this._loaded) throw new Error('Cannot export, you need to train the SVM first'); var model = {}; model.options = Object.assign({}, this.options); model.b = this.b; model.minMax = this.minMax; if (model.options.kernel === 'linear') { model.W = this.W.slice(); } else { // Exporting non-linear models is heavier model.X = this.X.slice(); model.Y = this.Y.slice(); model.alphas = this.alphas.slice(); } return model; }
...
This method runs the prediction for a new set of observations.
### predictor.score()
This method is optional.
It should return a value that represents the quality of a predictor.
### predictor.toJSON()
This method should return plain JS Object that enables to reload the current predictor.
### Predictor.load(json)
This static method should return a new predictor instance that is ready to make predictions. The `json`
parameter is the object returned by an earlier call of `toJSON`.
...
train = function (features, labels) { if (features.length !== labels.length) { throw new Error('Features and labels should have the same length'); } if (features.length < 2) { throw new Error('Cannot train with less than 2 observations'); } this._trained = false; this._loaded = false; this.N = labels.length; this.D = features[0].length; if (this.options.whitening) { this.X = new Array(this.N); for (var i = 0; i < this.N; i++) { this.X[i] = new Array(this.D); } this.minMax = new Array(this.D); // Apply normalization and keep normalization parameters for (var j = 0; j < this.D; j++) { var d = new Array(this.N); for (i = 0; i < this.N; i++) { d[i] = features[i][j]; } this.minMax[j] = stat.minMax(d); for (i = 0; i < this.N; i++) { this.X[i][j] = (features[i][j] - this.minMax[j].min) / (this.minMax[j].max - this.minMax[j].min); } } } else { this.X = features; } this.Y = labels; this.b = 0; this.W = undefined; var kernel = this.kernel.compute(this.X); var m = labels.length; var alpha = new Array(m).fill(0); this.alphas = alpha; for (var a = 0; a < m; a++) alpha[a] = 0; var b1 = 0, b2 = 0, iter = 0, passes = 0, Ei = 0, Ej = 0, ai = 0, aj = 0, L = 0, H = 0, eta = 0; while (passes < this.options.maxPasses && iter < this.options.maxIterations) { var numChange = 0; for (i = 0; i < m; i++) { Ei = this._marginOnePrecomputed(i, kernel) - labels[i]; if (labels[i] * Ei < -this.options.tol && alpha[i] < this.options.C || labels[i] * Ei > this.options.tol && alpha[i] > 0) { j = i; while (j === i) j = Math.floor(this.options.random() * m); Ej = this._marginOnePrecomputed(j, kernel) - labels[j]; ai = alpha[i]; aj = alpha[j]; if (labels[i] === labels[j]) { L = Math.max(0, ai + aj - this.options.C); H = Math.min(this.options.C, ai + aj); } else { L = Math.max(0, aj - ai); H = Math.min(this.options.C, this.options.C + aj + ai); } if (Math.abs(L - H) < 1e-4) continue; eta = 2 * kernel[i][j] - kernel[i][i] - kernel[j][j]; if (eta >= 0) continue; var newaj = alpha[j] - labels[j] * (Ei - Ej) / eta; if (newaj > H) newaj = H; else if (newaj < L) newaj = L; if (Math.abs(aj - newaj) < 10e-4) continue; alpha[j] = newaj; alpha[i] = alpha[i] + labels[i] * labels[j] * (aj - newaj); b1 = this.b - Ei - labels[i] * (alpha[i] - ai) * kernel[i][i] - labels[j] * (alpha[j] - aj) * kernel[i][j]; b2 = this.b - Ej - labels[i] * (alpha[i] - ai) * kernel[i][j] - labels[j] * (alpha[j] - aj) * kernel[j][j]; this.b = (b1 + b2) / 2; if (alpha[i] < this.options.C && alpha[i] > 0) this.b = b1; if (alpha[j] < this.options.C && alpha[j] > 0) this.b = b2; numChange += 1; } } iter++; if (numChange === 0) passes += 1; else passes = 0; } if (iter === this.options.maxIterations) { throw new Error('max iterations reached'); } this.iterations = iter; // Compute the weights (useful for fast decision on new test instances when linear SVM) if (this.options.kernel === 'linear') { this.W = new Array(this.D); for (var r = 0; r < this.D; r++) { this.W[r] = 0; for (var w = 0; w < m; w++) this.W[r] += labels[w] * alpha[w] * this.X[w][r]; } } ...
...
Predictors are classes which implement the following interface.
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
...
class PCA {
constructor(dataset, options) {
if (dataset === true) {
const model = options;
this.center = model.center;
this.scale = model.scale;
this.means = model.means;
this.stdevs = model.stdevs;
this.U = Matrix.checkMatrix(model.U);
this.S = model.S;
return;
}
options = Object.assign({}, defaultOptions, options);
this.center = false;
this.scale = false;
this.means = null;
this.stdevs = null;
if (options.isCovarianceMatrix) { // user provided a covariance matrix instead of dataset
this._computeFromCovarianceMatrix(dataset);
return;
}
var useCovarianceMatrix;
if (typeof options.useCovarianceMatrix === 'boolean') {
useCovarianceMatrix = options.useCovarianceMatrix;
} else {
useCovarianceMatrix = dataset.length > dataset[0].length;
}
if (useCovarianceMatrix) { // user provided a dataset but wants us to compute and use the covariance matrix
dataset = this._adjust(dataset, options);
const covarianceMatrix = dataset.transposeView().mmul(dataset).div(dataset.rows - 1);
this._computeFromCovarianceMatrix(covarianceMatrix);
} else {
dataset = this._adjust(dataset, options);
var svd = new SVD(dataset, {
computeLeftSingularVectors: false,
computeRightSingularVectors: true,
autoTranspose: true
});
this.U = svd.rightSingularVectors;
const singularValues = svd.diagonal;
const eigenvalues = new Array(singularValues.length);
for (var i = 0; i < singularValues.length; i++) {
eigenvalues[i] = singularValues[i] * singularValues[i] / (dataset.length - 1);
}
this.S = eigenvalues;
}
}
/**
* Load a PCA model from JSON
* @param {Object} model
* @return {PCA}
*/
static load(model) {
if (model.name !== 'PCA')
throw new RangeError('Invalid model: ' + model.name);
return new PCA(true, model);
}
/**
* Project the dataset into the PCA space
* @param {Matrix} dataset
* @return {Matrix} dataset projected in the PCA space
*/
predict(dataset) {
dataset = new Matrix(dataset);
if (this.center) {
dataset.subRowVector(this.means);
if (this.scale) {
dataset.divRowVector(this.stdevs);
}
}
return dataset.mmul(this.U);
}
/**
* Returns the proportion of variance for each component
* @return {[number]}
*/
getExplainedVariance() {
var sum = 0;
for (var i = 0; i < this.S.length; i++) {
sum += this.S[i];
}
return this.S.map(value => value / sum);
}
/**
* Returns the cumulative proportion of variance
* @return {[number]}
*/
getCumulativeVariance() {
var explained = this.getExplainedVariance();
for (var i = 1; i < explained.length; i++) {
explained[i] += explained[i - 1];
}
return explained;
}
/**
* Returns the Eigenvectors of the covariance matrix
* @returns {Matrix}
*/
getEigenvectors() {
return this.U;
}
/**
* Returns the Eigenvalues (on the diagonal)
* @returns {[number]}
*/
getEigenvalues() {
return this.S;
}
/**
* Returns the standard deviations of the principal components
* @returns {[number]}
*/
getStandardDeviations() {
return this.S.map(x => Math.sqrt(x));
}
/**
* Returns the loadings matrix
* @return {Matrix}
*/
getLoadings() {
return this.U.transpose();
}
/**
* Export the current model to a JSON object
* @return {Object} model
*/
toJSON() {
return {
name: 'PCA', ...
n/a
class Performance {
/**
*
* @param prediction - The prediction matrix
* @param target - The target matrix (values: truthy for same class, falsy for different class)
* @param options
*
* @option all True if the entire matrix must be used. False to ignore the diagonal and lower part (default is false,
for similarity/distance matrices)
* @option max True if the max value corresponds to a perfect match (like in similarity matrices), false if it is the
min value (default is false, like in distance matrices. All values will be multiplied by -1)
*/
constructor(prediction, target, options) {
options = options || {};
if (prediction.length !== target.length || prediction[0].length !== target[0].length) {
throw new Error('dimensions of prediction and target do not match');
}
const rows = prediction.length;
const columns = prediction[0].length;
const isDistance = !options.max;
const predP = [];
if (options.all) {
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
predP.push({
pred: prediction[i][j],
targ: target[i][j]
});
}
}
} else {
if (rows < 3 || rows !== columns) {
throw new Error('When "all" option is false, the prediction matrix must be square and have at least 3 columns');
}
for (var i = 0; i < rows - 1; i++) {
for (var j = i + 1; j < columns; j++) {
predP.push({
pred: prediction[i][j],
targ: target[i][j]
});
}
}
}
if (isDistance) {
predP.sort((a, b) => a.pred - b.pred);
} else {
predP.sort((a, b) => b.pred - a.pred);
}
const cutoffs = this.cutoffs = [isDistance ? Number.MIN_VALUE : Number.MAX_VALUE];
const fp = this.fp = [0];
const tp = this.tp = [0];
var nPos = 0;
var nNeg = 0;
var currentPred = predP[0].pred;
var nTp = 0;
var nFp = 0;
for (var i = 0; i < predP.length; i++) {
if (predP[i].pred !== currentPred) {
cutoffs.push(currentPred);
fp.push(nFp);
tp.push(nTp);
currentPred = predP[i].pred;
}
if (predP[i].targ) {
nPos++;
nTp++;
} else {
nNeg++;
nFp++;
}
}
cutoffs.push(currentPred);
fp.push(nFp);
tp.push(nTp);
const l = cutoffs.length;
const fn = this.fn = new Array(l);
const tn = this.tn = new Array(l);
const nPosPred = this.nPosPred = new Array(l);
const nNegPred = this.nNegPred = new Array(l);
for (var i = 0; i < l; i++) {
fn[i] = nPos - tp[i];
tn[i] = nNeg - fp[i];
nPosPred[i] = tp[i] + fp[i];
nNegPred[i] = tn[i] + fn[i];
}
this.nPos = nPos;
this.nNeg = nNeg;
this.nSamples = nPos + nNeg;
}
/**
* Computes a measure from the prediction object.
*
* Many measures are available and can be combined :
* To create a ROC curve, you need fpr and tpr
* To create a DET curve, you need fnr and fpr
* To create a Lift chart, you need rpp and lift
*
* Possible measures are : threshold (Threshold), acc (Accuracy), err (Error rate),
* fpr (False positive rate), tpr (True positive rate), fnr (False negative rate), tnr (True negative rate), ppv (Positive predictive
value),
* npv (Negative predictive value), pcfall (Prediction-conditioned fallout), pcmiss (Prediction-conditioned miss), lift (Lift
value), rpp (Rate of positive predictions), rnp (Rate of negative predictions)
*
* @param measure - The s ...
n/a
function arithmeticMean(values) { var sum = 0; var l = values.length; for (var i = 0; i < l; i++) { sum += values[i]; } return sum / l; }
n/a
function center(values, inPlace) { if (typeof (inPlace) === 'undefined') inPlace = false; var result = values; if (!inPlace) result = [].concat(values); var theMean = exports.mean(result), l = result.length; for (var i = 0; i < l; i++) result[i] -= theMean; }
n/a
function contraHarmonicMean(values) { var r1 = 0; var r2 = 0; var l = values.length; for (var i = 0; i < l; i++) { r1 += values[i] * values[i]; r2 += values[i]; } if (r2 < 0) { throw new RangeError('sum of values is negative'); } return r1 / r2; }
n/a
function covariance(vector1, vector2, unbiased) { if (typeof (unbiased) === 'undefined') unbiased = true; var mean1 = exports.mean(vector1); var mean2 = exports.mean(vector2); if (vector1.length !== vector2.length) throw 'Vectors do not have the same dimensions'; var cov = 0, l = vector1.length; for (var i = 0; i < l; i++) { var x = vector1[i] - mean1; var y = vector2[i] - mean2; cov += x * y; } if (unbiased) return cov / (l - 1); else return cov / l; }
n/a
function cumulativeSum(array) { var l = array.length; var result = new Array(l); result[0] = array[0]; for (var i = 1; i < l; i++) result[i] = result[i - 1] + array[i]; return result; }
n/a
function entropy(values, eps) { if (typeof (eps) === 'undefined') eps = 0; var sum = 0, l = values.length; for (var i = 0; i < l; i++) sum += values[i] * Math.log(values[i] + eps); return -sum; }
n/a
function geometricMean(values) { var mul = 1; var l = values.length; for (var i = 0; i < l; i++) { mul *= values[i]; } return Math.pow(mul, 1 / l); }
n/a
function grandMean(means, samples) { var sum = 0; var n = 0; var l = means.length; for (var i = 0; i < l; i++) { sum += samples[i] * means[i]; n += samples[i]; } return sum / n; }
n/a
function harmonicMean(values) { var sum = 0; var l = values.length; for (var i = 0; i < l; i++) { if (values[i] === 0) { throw new RangeError('value at index ' + i + 'is zero'); } sum += 1 / values[i]; } return l / sum; }
n/a
function kurtosis(values, unbiased) { if (typeof (unbiased) === 'undefined') unbiased = true; var theMean = exports.mean(values); var n = values.length, s2 = 0, s4 = 0; for (var i = 0; i < n; i++) { var dev = values[i] - theMean; s2 += dev * dev; s4 += dev * dev * dev * dev; } var m2 = s2 / n; var m4 = s4 / n; if (unbiased) { var v = s2 / (n - 1); var a = (n * (n + 1)) / ((n - 1) * (n - 2) * (n - 3)); var b = s4 / (v * v); var c = ((n - 1) * (n - 1)) / ((n - 2) * (n - 3)); return a * b - 3 * c; } else { return m4 / (m2 * m2) - 3; } }
n/a
function logMean(values) { var lnsum = 0; var l = values.length; for (var i = 0; i < l; i++) { lnsum += Math.log(values[i]); } return lnsum / l; }
n/a
function max(values) { var max = values[0]; var l = values.length; for (var i = 1; i < l; i++) { if (values[i] > max) max = values[i]; } return max; }
n/a
function arithmeticMean(values) { var sum = 0; var l = values.length; for (var i = 0; i < l; i++) { sum += values[i]; } return sum / l; }
n/a
function median(values, alreadySorted) { if (alreadySorted === undefined) alreadySorted = false; if (!alreadySorted) { values = [].concat(values).sort(compareNumbers); } var l = values.length; var half = Math.floor(l / 2); if (l % 2 === 0) { return (values[half - 1] + values[half]) * 0.5; } else { return values[half]; } }
n/a
function min(values) { var min = values[0]; var l = values.length; for (var i = 1; i < l; i++) { if (values[i] < min) min = values[i]; } return min; }
n/a
function minMax(values) { var min = values[0]; var max = values[0]; var l = values.length; for (var i = 1; i < l; i++) { if (values[i] < min) min = values[i]; if (values[i] > max) max = values[i]; } return { min: min, max: max }; }
n/a
function mode(values) { var l = values.length, itemCount = new Array(l), i; for (i = 0; i < l; i++) { itemCount[i] = 0; } var itemArray = new Array(l); var count = 0; for (i = 0; i < l; i++) { var index = itemArray.indexOf(values[i]); if (index >= 0) itemCount[index]++; else { itemArray[count] = values[i]; itemCount[count] = 1; count++; } } var maxValue = 0, maxIndex = 0; for (i = 0; i < count; i++) { if (itemCount[i] > maxValue) { maxValue = itemCount[i]; maxIndex = i; } } return itemArray[maxIndex]; }
n/a
function pooledStandardDeviation(samples, unbiased) { return Math.sqrt(exports.pooledVariance(samples, unbiased)); }
n/a
function pooledVariance(samples, unbiased) { if (typeof (unbiased) === 'undefined') unbiased = true; var sum = 0; var length = 0, l = samples.length; for (var i = 0; i < l; i++) { var values = samples[i]; var vari = exports.variance(values); sum += (values.length - 1) * vari; if (unbiased) length += values.length - 1; else length += values.length; } return sum / length; }
n/a
function quartiles(values, alreadySorted) { if (typeof (alreadySorted) === 'undefined') alreadySorted = false; if (!alreadySorted) { values = [].concat(values).sort(compareNumbers); } var quart = values.length / 4; var q1 = values[Math.ceil(quart) - 1]; var q2 = exports.median(values, true); var q3 = values[Math.ceil(quart * 3) - 1]; return {q1: q1, q2: q2, q3: q3}; }
n/a
function robustMeanAndStdev(y) { var mean = 0, stdev = 0; var length = y.length, i = 0; for (i = 0; i < length; i++) { mean += y[i]; } mean /= length; var averageDeviations = new Array(length); for (i = 0; i < length; i++) averageDeviations[i] = Math.abs(y[i] - mean); averageDeviations.sort(compareNumbers); if (length % 2 === 1) { stdev = averageDeviations[(length - 1) / 2] / 0.6745; } else { stdev = 0.5 * (averageDeviations[length / 2] + averageDeviations[length / 2 - 1]) / 0.6745; } return { mean: mean, stdev: stdev }; }
n/a
function skewness(values, unbiased) { if (typeof (unbiased) === 'undefined') unbiased = true; var theMean = exports.mean(values); var s2 = 0, s3 = 0, l = values.length; for (var i = 0; i < l; i++) { var dev = values[i] - theMean; s2 += dev * dev; s3 += dev * dev * dev; } var m2 = s2 / l; var m3 = s3 / l; var g = m3 / (Math.pow(m2, 3 / 2.0)); if (unbiased) { var a = Math.sqrt(l * (l - 1)); var b = l - 2; return (a / b) * g; } else { return g; } }
n/a
function standardDeviation(values, unbiased) { return Math.sqrt(exports.variance(values, unbiased)); }
n/a
function standardError(values) { return exports.standardDeviation(values) / Math.sqrt(values.length); }
n/a
function standardize(values, standardDev, inPlace) { if (typeof (standardDev) === 'undefined') standardDev = exports.standardDeviation(values); if (typeof (inPlace) === 'undefined') inPlace = false; var l = values.length; var result = inPlace ? values : new Array(l); for (var i = 0; i < l; i++) result[i] = values[i] / standardDev; return result; }
n/a
function sum(values) { var sum = 0; for (var i = 0; i < values.length; i++) { sum += values[i]; } return sum; }
n/a
function truncatedMean(values, percent, alreadySorted) { if (alreadySorted === undefined) alreadySorted = false; if (!alreadySorted) { values = [].concat(values).sort(compareNumbers); } var l = values.length; var k = Math.floor(l * percent); var sum = 0; for (var i = k; i < (l - k); i++) { sum += values[i]; } return sum / (l - 2 * k); }
n/a
function variance(values, unbiased) { if (unbiased === undefined) unbiased = true; var theMean = exports.mean(values); var theVariance = 0; var l = values.length; for (var i = 0; i < l; i++) { var x = values[i] - theMean; theVariance += x * x; } if (unbiased) { return theVariance / (l - 1); } else { return theVariance / l; } }
n/a
function weightedMean(values, weights) { var sum = 0, l = values.length; for (var i = 0; i < l; i++) sum += values[i] * weights[i]; return sum; }
n/a
function weightedStandardDeviation(values, weights) { return Math.sqrt(exports.weightedVariance(values, weights)); }
n/a
function weightedVariance(values, weights) { var theMean = exports.weightedMean(values, weights); var vari = 0, l = values.length; var a = 0, b = 0; for (var i = 0; i < l; i++) { var z = values[i] - theMean; var w = weights[i]; vari += w * (z * z); b += w; a += w * w; } return vari * (b / (b * b - a)); }
n/a
function center(matrix, means, inPlace) { means = means || exports.mean(matrix); var result = matrix, l = matrix.length, i, j, jj; if (!inPlace) { result = new Array(l); for (i = 0; i < l; i++) { result[i] = new Array(matrix[i].length); } } for (i = 0; i < l; i++) { var row = result[i]; for (j = 0, jj = row.length; j < jj; j++) { row[j] = matrix[i][j] - means[j]; } } return result; }
n/a
function correlation(matrix) { var means = exports.mean(matrix), standardDeviations = exports.standardDeviation(matrix, true, means), scores = exports.zScores(matrix, means, standardDeviations), rows = matrix.length, cols = matrix[0].length, i, j; var cor = new Array(cols); for (i = 0; i < cols; i++) { cor[i] = new Array(cols); } for (i = 0; i < cols; i++) { for (j = i; j < cols; j++) { var c = 0; for (var k = 0, l = scores.length; k < l; k++) { c += scores[k][j] * scores[k][i]; } c /= rows - 1; cor[i][j] = c; cor[j][i] = c; } } return cor; }
n/a
function covariance(matrix, dimension) { return exports.scatter(matrix, undefined, dimension); }
n/a
function entropy(matrix, eps) { if (typeof (eps) === 'undefined') { eps = 0; } var sum = 0, l1 = matrix.length, l2 = matrix[0].length; for (var i = 0; i < l1; i++) { for (var j = 0; j < l2; j++) { sum += matrix[i][j] * Math.log(matrix[i][j] + eps); } } return -sum; }
n/a
function kurtosis(matrix, unbiased) { if (typeof (unbiased) === 'undefined') unbiased = true; var means = exports.mean(matrix); var n = matrix.length, m = matrix[0].length; var kurt = new Array(m); for (var j = 0; j < m; j++) { var s2 = 0, s4 = 0; for (var i = 0; i < n; i++) { var dev = matrix[i][j] - means[j]; s2 += dev * dev; s4 += dev * dev * dev * dev; } var m2 = s2 / n; var m4 = s4 / n; if (unbiased) { var v = s2 / (n - 1); var a = (n * (n + 1)) / ((n - 1) * (n - 2) * (n - 3)); var b = s4 / (v * v); var c = ((n - 1) * (n - 1)) / ((n - 2) * (n - 3)); kurt[j] = a * b - 3 * c; } else { kurt[j] = m4 / (m2 * m2) - 3; } } return kurt; }
n/a
function max(matrix) { var max = -Infinity; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { if (matrix[i][j] > max) max = matrix[i][j]; } } return max; }
n/a
function mean(matrix, dimension) { if (typeof (dimension) === 'undefined') { dimension = 0; } var rows = matrix.length, cols = matrix[0].length, theMean, N, i, j; if (dimension === -1) { theMean = [0]; N = rows * cols; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { theMean[0] += matrix[i][j]; } } theMean[0] /= N; } else if (dimension === 0) { theMean = new Array(cols); N = rows; for (j = 0; j < cols; j++) { theMean[j] = 0; for (i = 0; i < rows; i++) { theMean[j] += matrix[i][j]; } theMean[j] /= N; } } else if (dimension === 1) { theMean = new Array(rows); N = cols; for (j = 0; j < rows; j++) { theMean[j] = 0; for (i = 0; i < cols; i++) { theMean[j] += matrix[j][i]; } theMean[j] /= N; } } else { throw new Error('Invalid dimension'); } return theMean; }
n/a
function median(matrix) { var rows = matrix.length, cols = matrix[0].length; var medians = new Array(cols); for (var i = 0; i < cols; i++) { var data = new Array(rows); for (var j = 0; j < rows; j++) { data[j] = matrix[j][i]; } data.sort(compareNumbers); var N = data.length; if (N % 2 === 0) { medians[i] = (data[N / 2] + data[(N / 2) - 1]) * 0.5; } else { medians[i] = data[Math.floor(N / 2)]; } } return medians; }
n/a
function min(matrix) { var min = Infinity; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { if (matrix[i][j] < min) min = matrix[i][j]; } } return min; }
n/a
function minMax(matrix) { var min = Infinity; var max = -Infinity; for (var i = 0; i < matrix.length; i++) { for (var j = 0; j < matrix[i].length; j++) { if (matrix[i][j] < min) min = matrix[i][j]; if (matrix[i][j] > max) max = matrix[i][j]; } } return { min:min, max:max }; }
n/a
function mode(matrix) { var rows = matrix.length, cols = matrix[0].length, modes = new Array(cols), i, j; for (i = 0; i < cols; i++) { var itemCount = new Array(rows); for (var k = 0; k < rows; k++) { itemCount[k] = 0; } var itemArray = new Array(rows); var count = 0; for (j = 0; j < rows; j++) { var index = itemArray.indexOf(matrix[j][i]); if (index >= 0) { itemCount[index]++; } else { itemArray[count] = matrix[j][i]; itemCount[count] = 1; count++; } } var maxValue = 0, maxIndex = 0; for (j = 0; j < count; j++) { if (itemCount[j] > maxValue) { maxValue = itemCount[j]; maxIndex = j; } } modes[i] = itemArray[maxIndex]; } return modes; }
n/a
function product(matrix, dimension) { if (typeof (dimension) === 'undefined') { dimension = 0; } var rows = matrix.length, cols = matrix[0].length, theProduct, i, j; if (dimension === -1) { theProduct = [1]; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { theProduct[0] *= matrix[i][j]; } } } else if (dimension === 0) { theProduct = new Array(cols); for (j = 0; j < cols; j++) { theProduct[j] = 1; for (i = 0; i < rows; i++) { theProduct[j] *= matrix[i][j]; } } } else if (dimension === 1) { theProduct = new Array(rows); for (j = 0; j < rows; j++) { theProduct[j] = 1; for (i = 0; i < cols; i++) { theProduct[j] *= matrix[j][i]; } } } else { throw new Error('Invalid dimension'); } return theProduct; }
n/a
function scatter(matrix, divisor, dimension) { if (typeof (dimension) === 'undefined') { dimension = 0; } if (typeof (divisor) === 'undefined') { if (dimension === 0) { divisor = matrix.length - 1; } else if (dimension === 1) { divisor = matrix[0].length - 1; } } var means = exports.mean(matrix, dimension); var rows = matrix.length; if (rows === 0) { return [[]]; } var cols = matrix[0].length, cov, i, j, s, k; if (dimension === 0) { cov = new Array(cols); for (i = 0; i < cols; i++) { cov[i] = new Array(cols); } for (i = 0; i < cols; i++) { for (j = i; j < cols; j++) { s = 0; for (k = 0; k < rows; k++) { s += (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]); } s /= divisor; cov[i][j] = s; cov[j][i] = s; } } } else if (dimension === 1) { cov = new Array(rows); for (i = 0; i < rows; i++) { cov[i] = new Array(rows); } for (i = 0; i < rows; i++) { for (j = i; j < rows; j++) { s = 0; for (k = 0; k < cols; k++) { s += (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]); } s /= divisor; cov[i][j] = s; cov[j][i] = s; } } } else { throw new Error('Invalid dimension'); } return cov; }
n/a
function skewness(matrix, unbiased) { if (typeof (unbiased) === 'undefined') unbiased = true; var means = exports.mean(matrix); var n = matrix.length, l = means.length; var skew = new Array(l); for (var j = 0; j < l; j++) { var s2 = 0, s3 = 0; for (var i = 0; i < n; i++) { var dev = matrix[i][j] - means[j]; s2 += dev * dev; s3 += dev * dev * dev; } var m2 = s2 / n; var m3 = s3 / n; var g = m3 / Math.pow(m2, 3 / 2); if (unbiased) { var a = Math.sqrt(n * (n - 1)); var b = n - 2; skew[j] = (a / b) * g; } else { skew[j] = g; } } return skew; }
n/a
function standardDeviation(matrix, means, unbiased) { var vari = exports.variance(matrix, means, unbiased), l = vari.length; for (var i = 0; i < l; i++) { vari[i] = Math.sqrt(vari[i]); } return vari; }
n/a
function standardError(matrix) { var samples = matrix.length; var standardDeviations = exports.standardDeviation(matrix); var l = standardDeviations.length; var standardErrors = new Array(l); var sqrtN = Math.sqrt(samples); for (var i = 0; i < l; i++) { standardErrors[i] = standardDeviations[i] / sqrtN; } return standardErrors; }
n/a
function standardize(matrix, standardDeviations, inPlace) { if (typeof (standardDeviations) === 'undefined') standardDeviations = exports.standardDeviation(matrix); var result = matrix, l = matrix.length, i, j, jj; if (!inPlace) { result = new Array(l); for (i = 0; i < l; i++) { result[i] = new Array(matrix[i].length); } } for (i = 0; i < l; i++) { var resultRow = result[i]; var sourceRow = matrix[i]; for (j = 0, jj = resultRow.length; j < jj; j++) { if (standardDeviations[j] !== 0 && !isNaN(standardDeviations[j])) { resultRow[j] = sourceRow[j] / standardDeviations[j]; } } } return result; }
n/a
function sum(matrix, dimension) { if (typeof (dimension) === 'undefined') { dimension = 0; } var rows = matrix.length, cols = matrix[0].length, theSum, i, j; if (dimension === -1) { theSum = [0]; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { theSum[0] += matrix[i][j]; } } } else if (dimension === 0) { theSum = new Array(cols); for (j = 0; j < cols; j++) { theSum[j] = 0; for (i = 0; i < rows; i++) { theSum[j] += matrix[i][j]; } } } else if (dimension === 1) { theSum = new Array(rows); for (j = 0; j < rows; j++) { theSum[j] = 0; for (i = 0; i < cols; i++) { theSum[j] += matrix[j][i]; } } } else { throw new Error('Invalid dimension'); } return theSum; }
n/a
function variance(matrix, means, unbiased) { if (typeof (unbiased) === 'undefined') { unbiased = true; } means = means || exports.mean(matrix); var rows = matrix.length; if (rows === 0) return []; var cols = matrix[0].length; var vari = new Array(cols); for (var j = 0; j < cols; j++) { var sum1 = 0, sum2 = 0, x = 0; for (var i = 0; i < rows; i++) { x = matrix[i][j] - means[j]; sum1 += x; sum2 += x * x; } if (unbiased) { vari[j] = (sum2 - ((sum1 * sum1) / rows)) / (rows - 1); } else { vari[j] = (sum2 - ((sum1 * sum1) / rows)) / rows; } } return vari; }
n/a
function weightedCovariance(matrix, weights, means, dimension) { dimension = dimension || 0; means = means || exports.weightedMean(matrix, weights, dimension); var s1 = 0, s2 = 0; for (var i = 0, ii = weights.length; i < ii; i++) { s1 += weights[i]; s2 += weights[i] * weights[i]; } var factor = s1 / (s1 * s1 - s2); return exports.weightedScatter(matrix, weights, means, factor, dimension); }
n/a
function weightedMean(matrix, weights, dimension) { if (typeof (dimension) === 'undefined') { dimension = 0; } var rows = matrix.length; if (rows === 0) return []; var cols = matrix[0].length, means, i, ii, j, w, row; if (dimension === 0) { means = new Array(cols); for (i = 0; i < cols; i++) { means[i] = 0; } for (i = 0; i < rows; i++) { row = matrix[i]; w = weights[i]; for (j = 0; j < cols; j++) { means[j] += row[j] * w; } } } else if (dimension === 1) { means = new Array(rows); for (i = 0; i < rows; i++) { means[i] = 0; } for (j = 0; j < rows; j++) { row = matrix[j]; w = weights[j]; for (i = 0; i < cols; i++) { means[j] += row[i] * w; } } } else { throw new Error('Invalid dimension'); } var weightSum = arrayStat.sum(weights); if (weightSum !== 0) { for (i = 0, ii = means.length; i < ii; i++) { means[i] /= weightSum; } } return means; }
n/a
function weightedScatter(matrix, weights, means, factor, dimension) { dimension = dimension || 0; means = means || exports.weightedMean(matrix, weights, dimension); if (typeof (factor) === 'undefined') { factor = 1; } var rows = matrix.length; if (rows === 0) { return [[]]; } var cols = matrix[0].length, cov, i, j, k, s; if (dimension === 0) { cov = new Array(cols); for (i = 0; i < cols; i++) { cov[i] = new Array(cols); } for (i = 0; i < cols; i++) { for (j = i; j < cols; j++) { s = 0; for (k = 0; k < rows; k++) { s += weights[k] * (matrix[k][j] - means[j]) * (matrix[k][i] - means[i]); } cov[i][j] = s * factor; cov[j][i] = s * factor; } } } else if (dimension === 1) { cov = new Array(rows); for (i = 0; i < rows; i++) { cov[i] = new Array(rows); } for (i = 0; i < rows; i++) { for (j = i; j < rows; j++) { s = 0; for (k = 0; k < cols; k++) { s += weights[k] * (matrix[j][k] - means[j]) * (matrix[i][k] - means[i]); } cov[i][j] = s * factor; cov[j][i] = s * factor; } } } else { throw new Error('Invalid dimension'); } return cov; }
n/a
function weightedVariance(matrix, weights) { var means = exports.mean(matrix); var rows = matrix.length; if (rows === 0) return []; var cols = matrix[0].length; var vari = new Array(cols); for (var j = 0; j < cols; j++) { var sum = 0; var a = 0, b = 0; for (var i = 0; i < rows; i++) { var z = matrix[i][j] - means[j]; var w = weights[i]; sum += w * (z * z); b += w; a += w * w; } vari[j] = sum * (b / (b * b - a)); } return vari; }
n/a
function zScores(matrix, means, standardDeviations) { means = means || exports.mean(matrix); if (typeof (standardDeviations) === 'undefined') standardDeviations = exports.standardDeviation(matrix, true, means); return exports.standardize(exports.center(matrix, means, false), standardDeviations, true); }
n/a
class FeedForwardNeuralNetworks {
/**
* Create a new Feedforword neural network model.
* @param {object} options
* @param {Array} [options.hiddenLayers=[10]] - Array that contains the sizes of the hidden layers.
* @oaram {number} [options.iterations=50] - Number of iterations at the training step.
* @param {number} [options.learningRate=0.01] - Learning rate of the neural net (also known as epsilon).
* @poram {number} [options.regularization=0.01] - Regularization parameter af the neural net.
* @poram {string} [options.activation='tanh'] - activation function to be used. (options: 'tanh'(default),
* 'identity', 'logistic', 'arctan', 'softsign', 'relu', 'softplus', 'bent', 'sinusoid', 'sinc', 'gaussian').
* (single-parametric options: 'parametric-relu', 'exponential-relu', 'soft-exponential').
* @param {number} [options.activationParam=1] - if the selected activation function needs a parameter.
*/
constructor(options) {
options = options || {};
if (options.model) {
// load network
this.hiddenLayers = options.hiddenLayers;
this.iterations = options.iterations;
this.learningRate = options.learningRate;
this.regularization = options.regularization;
this.dicts = options.dicts;
this.activation = options.activation;
this.activationParam = options.activationParam;
this.model = new Array(options.layers.length);
for (var i = 0; i < this.model.length - 1; ++i) {
this.model[i] = Layer.load(options.layers[i]);
}
this.model[this.model.length - 1] = OutputLayer.load(options.layers[this.model.length - 1]);
} else {
// default constructor
this.hiddenLayers = options.hiddenLayers === undefined ? [10] : options.hiddenLayers;
this.iterations = options.iterations === undefined ? 50 : options.iterations;
this.learningRate = options.learningRate === undefined ? 0.01 : options.learningRate;
//this.momentum = options.momentum === undefined ? 0.1 : options.momentum;
this.regularization = options.regularization === undefined ? 0.01 : options.regularization;
this.activation = options.activation === undefined ? 'tanh' : options.activation;
this.activationParam = options.activationParam === undefined ? 1 : options.activationParam;
if (!(this.activation in Object.keys(ACTIVATION_FUNCTIONS))) {
this.activation = 'tanh';
}
}
}
/**
* Function that build and initialize the neural net.
* @param {number} inputSize - total of features to fit.
* @param {number} outputSize - total of labels of the prediction set.
*/
buildNetwork(inputSize, outputSize) {
var size = 2 + (this.hiddenLayers.length - 1);
this.model = new Array(size);
// input layer
this.model[0] = new Layer({
inputSize: inputSize,
outputSize: this.hiddenLayers[0],
activation: this.activation,
activationParam: this.activationParam,
regularization: this.regularization,
epsilon: this.learningRate
});
// hidden layers
for (var i = 1; i < this.hiddenLayers.length; ++i) {
this.model[i] = new Layer({
inputSize: this.hiddenLayers[i - 1],
outputSize: this.hiddenLayers[i],
activation: this.activation,
activationParam: this.activationParam,
regularization: this.regularization,
epsilon: this.learningRate
});
}
// output layer
this.model[size - 1] = new OutputLayer({
inputSize: this.hiddenLayers[this.hiddenLayers.length - 1],
outputSize: outputSize,
activation: this.activation,
activationParam: this.activationParam,
regularization: this.regularization, ...
n/a
function SOM(x, y, options, reload) { this.x = x; this.y = y; options = options || {}; this.options = {}; for (var i in defaultOptions) { if (options.hasOwnProperty(i)) { this.options[i] = options[i]; } else { this.options[i] = defaultOptions[i]; } } if (typeof this.options.fields === 'number') { this.numWeights = this.options.fields; } else if (Array.isArray(this.options.fields)) { this.numWeights = this.options.fields.length; var converters = getConverters(this.options.fields); this.extractor = converters.extractor; this.creator = converters.creator; } else { throw new Error('Invalid fields definition'); } if (this.options.gridType === 'rect') { this.nodeType = NodeSquare; this.gridDim = { x: x, y: y }; } else { this.nodeType = NodeHexagonal; var hx = this.x - Math.floor(this.y / 2); this.gridDim = { x: hx, y: this.y, z: -(0 - hx - this.y) }; } this.torus = this.options.torus; this.distanceMethod = this.torus ? 'getDistanceTorus' : 'getDistance'; this.distance = this.options.distance; this.maxDistance = getMaxDistance(this.distance, this.numWeights); if (reload === true) { // For model loading this.done = true; return; } if (!(x > 0 && y > 0)) { throw new Error('x and y must be positive'); } this.times = { findBMU: 0, adjust: 0 }; this.randomizer = this.options.randomizer; this.iterationCount = 0; this.iterations = this.options.iterations; this.startLearningRate = this.learningRate = this.options.learningRate; this.mapRadius = Math.floor(Math.max(x, y) / 2); this.algorithmMethod = this.options.method; this._initNodes(); this.done = false; }
n/a
function SOM(x, y, options, reload) { this.x = x; this.y = y; options = options || {}; this.options = {}; for (var i in defaultOptions) { if (options.hasOwnProperty(i)) { this.options[i] = options[i]; } else { this.options[i] = defaultOptions[i]; } } if (typeof this.options.fields === 'number') { this.numWeights = this.options.fields; } else if (Array.isArray(this.options.fields)) { this.numWeights = this.options.fields.length; var converters = getConverters(this.options.fields); this.extractor = converters.extractor; this.creator = converters.creator; } else { throw new Error('Invalid fields definition'); } if (this.options.gridType === 'rect') { this.nodeType = NodeSquare; this.gridDim = { x: x, y: y }; } else { this.nodeType = NodeHexagonal; var hx = this.x - Math.floor(this.y / 2); this.gridDim = { x: hx, y: this.y, z: -(0 - hx - this.y) }; } this.torus = this.options.torus; this.distanceMethod = this.torus ? 'getDistanceTorus' : 'getDistance'; this.distance = this.options.distance; this.maxDistance = getMaxDistance(this.distance, this.numWeights); if (reload === true) { // For model loading this.done = true; return; } if (!(x > 0 && y > 0)) { throw new Error('x and y must be positive'); } this.times = { findBMU: 0, adjust: 0 }; this.randomizer = this.options.randomizer; this.iterationCount = 0; this.iterations = this.options.iterations; this.startLearningRate = this.learningRate = this.options.learningRate; this.mapRadius = Math.floor(Math.max(x, y) / 2); this.algorithmMethod = this.options.method; this._initNodes(); this.done = false; }
n/a
function loadModel(model, distance) { if (model.name === 'SOM') { var x = model.data.length, y = model.data[0].length; if (distance) { model.options.distance = distance; } else if (model.options.distance) { model.options.distance = eval('(' + model.options.distance + ')'); } var som = new SOM(x, y, model.options, true); som.nodes = new Array(x); for (var i = 0; i < x; i++) { som.nodes[i] = new Array(y); for (var j = 0; j < y; j++) { som.nodes[i][j] = new som.nodeType(i, j, model.data[i][j], som); } } return som; } else { throw new Error('expecting a SOM model'); } }
...
This method is optional.
It should return a value that represents the quality of a predictor.
### predictor.toJSON()
This method should return plain JS Object that enables to reload the current predictor.
### Predictor.load(json)
This static method should return a new predictor instance that is ready to make predictions. The `json`
parameter is the object returned by an earlier call of `toJSON`.
## Commit Guidelines
The rules are based on the [AngularJS commit guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#commit
). This leads to **more readable messages** that are easy to follow when looking through the **project history**.
...
function adjust(trainingValue, neighbourhoodRadius) { var now = Date.now(), x, y, dist, influence; var bmu = this._findBestMatchingUnit(trainingValue); var now2 = Date.now(); this.times.findBMU += now2 - now; var radiusLimit = Math.floor(neighbourhoodRadius); var xMin = bmu.x - radiusLimit, xMax = bmu.x + radiusLimit, yMin = bmu.y - radiusLimit, yMax = bmu.y + radiusLimit; for (x = xMin; x <= xMax; x++) { var theX = x; if (x < 0) { theX += this.x; } else if (x >= this.x) { theX -= this.x; } for (y = yMin; y <= yMax; y++) { var theY = y; if (y < 0) { theY += this.y; } else if (y >= this.y) { theY -= this.y; } dist = bmu[this.distanceMethod](this.nodes[theX][theY]); if (dist < neighbourhoodRadius) { influence = Math.exp(-dist / (2 * neighbourhoodRadius)); this.nodes[theX][theY].adjustWeights(trainingValue, this.learningRate, influence); } } } this.times.adjust += (Date.now() - now2); }
n/a
function findBestMatchingUnit(candidate) { var bmu, lowest = Infinity, dist; for (var i = 0; i < this.x; i++) { for (var j = 0; j < this.y; j++) { dist = this.distance(this.nodes[i][j].weights, candidate); if (dist < lowest) { lowest = dist; bmu = this.nodes[i][j]; } } } return bmu; }
n/a
function initNodes() { var now = Date.now(), i, j, k; this.nodes = new Array(this.x); for (i = 0; i < this.x; i++) { this.nodes[i] = new Array(this.y); for (j = 0; j < this.y; j++) { var weights = new Array(this.numWeights); for (k = 0; k < this.numWeights; k++) { weights[k] = this.randomizer(); } this.nodes[i][j] = new this.nodeType(i, j, weights, this); } } this.times.initNodes = Date.now() - now; }
n/a
function _predict(element, computePosition) { if (!Array.isArray(element)) { element = this.extractor(element); } var bmu = this._findBestMatchingUnit(element); var result = [bmu.x, bmu.y]; if (computePosition) { result[2] = bmu.getPosition(element); } return result; }
n/a
function exportModel(includeDistance) { if (!this.done) { throw new Error('model is not ready yet'); } var model = { name: 'SOM' }; model.options = { fields: this.options.fields, gridType: this.options.gridType, torus: this.options.torus }; model.data = new Array(this.x); for (var i = 0; i < this.x; i++) { model.data[i] = new Array(this.y); for (var j = 0; j < this.y; j++) { model.data[i][j] = this.nodes[i][j].weights; } } if (includeDistance) { model.options.distance = this.distance.toString(); } return model; }
n/a
function getConvertedNodes() { var result = new Array(this.x); for (var i = 0; i < this.x; i++) { result[i] = new Array(this.y); for (var j = 0; j < this.y; j++) { var node = this.nodes[i][j]; result[i][j] = this.creator ? this.creator(node.weights) : node.weights; } } return result; }
n/a
function getFit(dataset) { if (!dataset) { dataset = this.trainingSet; } var l = dataset.length, bmu, result = new Array(l); for (var i = 0; i < l; i++) { bmu = this._findBestMatchingUnit(dataset[i]); result[i] = Math.sqrt(this.distance(dataset[i], bmu.weights)); } return result; }
n/a
function getQuantizationError() { var fit = this.getFit(), l = fit.length, sum = 0; for (var i = 0; i < l; i++) { sum += fit[i]; } return sum / l; }
n/a
function predict(data, computePosition) { if (typeof data === 'boolean') { computePosition = data; data = null; } if (!data) { data = this.trainingSet; } if (Array.isArray(data) && (Array.isArray(data[0]) || (typeof data[0] === 'object'))) { // predict a dataset var self = this; return data.map(function (element) { return self._predict(element, computePosition); }); } else { // predict a single element return this._predict(data, computePosition); } }
...
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
This method is optional.
It should return a value that represents the quality of a predictor.
...
function setTraining(trainingSet) { if (this.trainingSet) { throw new Error('training set has already been set'); } var now = Date.now(); var convertedSet = trainingSet; var i, l = trainingSet.length; if (this.extractor) { convertedSet = new Array(l); for (i = 0; i < l; i++) { convertedSet[i] = this.extractor(trainingSet[i]); } } this.numIterations = this.iterations * l; if (this.algorithmMethod === 'random') { this.timeConstant = this.numIterations / Math.log(this.mapRadius); } else { this.timeConstant = l / Math.log(this.mapRadius); } this.trainingSet = convertedSet; this.times.setTraining = Date.now() - now; }
n/a
function train(trainingSet) { if (!this.done) { this.setTraining(trainingSet); while (this.trainOne()) { } } }
...
Predictors are classes which implement the following interface.
### new Predictor()
Creates the predictor. The constructor can take parameters or options to initialize the algorithm.
### predictor.train(features, [labels])
If the predictor has a training phase, it is executed here.
### predictor.predict(features)
This method runs the prediction for a new set of observations.
### predictor.score()
...
function trainOne() { if (this.done) { return false; } else if (this.numIterations-- > 0) { var neighbourhoodRadius, trainingValue, trainingSetFactor; if (this.algorithmMethod === 'random') { // Pick a random value of the training set at each step neighbourhoodRadius = this.mapRadius * Math.exp(-this.iterationCount / this.timeConstant); trainingValue = getRandomValue(this.trainingSet, this.randomizer); this._adjust(trainingValue, neighbourhoodRadius); this.learningRate = this.startLearningRate * Math.exp(-this.iterationCount / this.numIterations); } else { // Get next input vector trainingSetFactor = -Math.floor(this.iterationCount / this.trainingSet.length); neighbourhoodRadius = this.mapRadius * Math.exp(trainingSetFactor / this.timeConstant); trainingValue = this.trainingSet[this.iterationCount % this.trainingSet.length]; this._adjust(trainingValue, neighbourhoodRadius); if (((this.iterationCount + 1) % this.trainingSet.length) === 0) { this.learningRate = this.startLearningRate * Math.exp(trainingSetFactor / Math.floor(this.numIterations / this.trainingSet .length)); } } this.iterationCount++; return true; } else { this.done = true; return false; } }
n/a
asc = function (a, b) { assertNum(a); assertNum(b); return a - b; }
n/a
desc = function (a, b) { assertNum(a); assertNum(b); return b - a; }
n/a