Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/v2 fix docs #182

Merged
merged 8 commits into from
Dec 28, 2018
1 change: 1 addition & 0 deletions docs/processor/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const tagTypeIgnore = 'ignore';
export const refKindInterface = 'Interface';
export const refKindTypeAlias = 'Type alias';
export const refTypeArgTypeUnion = 'union';
export const refTypeTypeParameter = 'typeParameter';
export const refTypeArgTypeIntrinsic = 'intrinsic';

// Matrix Types
Expand Down
15 changes: 12 additions & 3 deletions docs/processor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,9 @@ export function constructParamTable(parameters): string {
if (typeArg.type === consts.refTypeArgTypeUnion) {
const types = typeArg.types;
typeList.push(constructMatrixType(refName, types));
} else if (typeArg.type === consts.refTypeTypeParameter) {
const types = typeArg.constraint.types;
typeList.push(constructMatrixType(refName, types));
} else if (typeArg.type === consts.refTypeArgTypeIntrinsic) {
typeList.push(constructMatrixType(refName, [typeArg]));
} else {
Expand All @@ -344,9 +347,15 @@ export function constructParamTable(parameters): string {
} else if (consts.paramTypeUnion === paramType) {
// 5. Handles any union types.
// e.g. string[] | string[][]
const unionTypes = _.map(param.type.types, singleType =>
renderParamType(singleType)
);
const unionTypes = _.map(param.type.types, singleType => {
if (singleType.type === consts.paramTypeReference) {
return constructMatrixType(
singleType.name,
singleType.typeArguments
);
}
return renderParamType(singleType);
});
const unionTypesStr = unionTypes.join(' or ');
sum.push([
param.name,
Expand Down
43 changes: 22 additions & 21 deletions src/lib/cluster/k_means.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,9 @@ import { IMlModel, Type1DMatrix, Type2DMatrix } from '../types';
import math from '../utils/MathExtra';

export interface KMeansOptions {
/**
* Number of clusters
*/
k: number;
/**
* Choice of distance method. Defaulting to euclidean
*/
distance?: 'euclidean' | 'manhattan';
/**
* Relative tolerance with regards to inertia to declare convergence
*/
maxIteration?: number;
/**
* Random state value for sorting centroids during the getInitialCentroid phase
*/
randomState?: number;
}

Expand All @@ -44,16 +32,29 @@ export class KMeans implements IMlModel<number> {
private randomState: number;
private maxIteration: number;

/**
*
* @param distance - Choice of distance method. Defaulting to euclidean
* @param k - Number of clusters
* @param maxIteration - Relative tolerance with regards to inertia to declare convergence
* @param randomState - Random state value for sorting centroids during the getInitialCentroid phase
*/
constructor(
options: KMeansOptions = {
{
distance = 'euclidean',
k = 3,
maxIteration = 300,
randomState = 0
}: KMeansOptions = {
distance: 'euclidean',
k: 3,
maxIteration: 300
maxIteration: 300,
randomState: 0
}
) {
this.k = _.get(options, 'k', 3);
this.k = k;
// Assigning a distance method
const distanceType = _.get(options, 'distance', 'euclidean');
const distanceType = distance;
switch (distanceType) {
case 'euclidean':
this.distance = math.euclideanDistance;
Expand All @@ -64,8 +65,8 @@ export class KMeans implements IMlModel<number> {
default:
throw new Error(`Unknown distance type ${distanceType}`);
}
this.randomState = _.get(options, 'randomState', 0);
this.maxIteration = _.get(options, 'maxIteration', 300);
this.randomState = randomState;
this.maxIteration = maxIteration;
this.centroids = [];
}

Expand All @@ -74,7 +75,7 @@ export class KMeans implements IMlModel<number> {
* @param {any} X - array-like or sparse matrix of shape = [n_samples, n_features]
* @returns {{centroids: number[]; clusters: number[]}}
*/
public fit(X: Type2DMatrix<number> = []): void {
public fit(X: Type2DMatrix<number> = null): void {
validateMatrix2D(X);
this.assignment = new Array(_.size(X));
this.centroids = this.getInitialCentroids(X, this.k);
Expand Down Expand Up @@ -134,10 +135,10 @@ export class KMeans implements IMlModel<number> {

/**
* Predicts the cluster index with the given X
* @param {any} X
* @param {any} X - array-like or sparse matrix of shape = [n_samples, n_features]
* @returns {number[]}
*/
public predict(X: Type2DMatrix<number>): number[] {
public predict(X: Type2DMatrix<number> = null): number[] {
validateMatrix2D(X);
return _.map(X, data => {
return this.getClosestCentroids(data, this.centroids, this.distance);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/linear_model/coordinate_descent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class Ridge extends SGDRegressor {
*/
constructor(
{
l2,
l2 = null,
epochs = 1000,
learning_rate = 0.001
}: {
Expand Down
7 changes: 5 additions & 2 deletions src/lib/linear_model/linear_regression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export class LinearRegression {
* @param {any} X - training values
* @param {any} y - target values
*/
public fit(X: Type1DMatrix<number>, y: Type1DMatrix<number>): void {
public fit(
X: Type1DMatrix<number> = null,
y: Type1DMatrix<number> = null
): void {
const xShape = validateMatrix1D(X);
const yShape = validateMatrix1D(y);
if (xShape.length === 1 && yShape.length === 1 && xShape[0] === yShape[0]) {
Expand All @@ -46,7 +49,7 @@ export class LinearRegression {
* @param {number} X - Values to predict.
* @returns {number}
*/
public predict(X: Type1DMatrix<number>): number[] {
public predict(X: Type1DMatrix<number> = null): number[] {
validateMatrix1D(X);
const preds = [];
for (let i = 0; i < size(X); i++) {
Expand Down
124 changes: 65 additions & 59 deletions src/lib/metrics/classification.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as tf from '@tensorflow/tfjs';
import * as _ from 'lodash';
import { reshape } from '../ops';
import { Type1DMatrix } from '../types';
import { checkArray } from '../utils/validation';

/**
Expand Down Expand Up @@ -86,24 +87,29 @@ export const validateInitialInputs = (y_true, y_pred, labels, options = {}) => {
* @example
* import { accuracyScore } from 'kalimdor/metrics';
*
* const accResult = accuracyScore({
* y_true: [0, 1, 2, 3],
* y_pred: [0, 2, 1, 3]
* });
* const accResult = accuracyScore(
* [0, 1, 2, 3],
* [0, 2, 1, 3]
* );
*
* // accuracy result: 0.5
*
* @param {any} y_true
* @param {any} y_pred
* @param {any} normalize
* @param y_true - 1d array-like, or label indicator array / sparse matrix
* @param y_pred - 1d array-like, or label indicator array / sparse matrix
* @param normalize
*/
export function accuracyScore({
y_true,
y_pred,
normalize = true
// sample_weight = null
}): // TODO: Fix any array type
number {
export function accuracyScore(
y_true: Type1DMatrix<number | string> = null,
y_pred: Type1DMatrix<number | string> = null,
{
normalize = true
}: // sample_weight = null
{
normalize: boolean;
} = {
normalize: true
}
): number {
validateInitialInputs(y_true, y_pred, null, { multiclass: true });

const yTrueRange = _.range(0, _.size(y_true));
Expand All @@ -128,47 +134,38 @@ number {
* @example
* import { zeroOneLoss } from 'kalimdor/metrics';
*
* const loss_zero_one_result = zeroOneLoss({
* y_true: [1, 2, 3, 4],
* y_pred: [2, 2, 3, 5]
* });
* const loss_zero_one_result = zeroOneLoss(
* [1, 2, 3, 4],
* [2, 2, 3, 5]
* );
* console.log(loss_zero_one_result); // 0.5
*
* @param {any} y_true
* @param {any} y_pred
* @param {any} y_true - Ground truth (correct) labels.
* @param {any} y_pred - Predicted labels, as returned by a classifier.
* @param {any} normalize
* @returns {number}
*/
export function zeroOneLoss({
y_true,
y_pred,
normalize = true
// sample_weight = null
}): number {
export function zeroOneLoss(
y_true = null,
y_pred = null,
{
/**
* If False, return the number of misclassifications. Otherwise, return the fraction of misclassifications.
*/
normalize = true
}: {
normalize: boolean;
} = {
normalize: true
}
): number {
if (normalize) {
return 1 - accuracyScore({ y_true, y_pred });
return 1 - accuracyScore(y_true, y_pred);
}
// TODO: Fix return 0; implement when normalize === false
return 0;
}

export interface ConfusionMatrixOptions {
/**
* Ground truth (correct) target values.
*/
y_true: any[];
/**
* Estimated targets as returned by a classifier.
*/
y_pred: any[];
/**
* List of labels to index the matrix. This may be used to reorder or
* select a subset of labels. If none is given, those that appear
* at least once in y_true or y_pred are used in sorted order.
*/
labels?: any[];
}

/**
* A confusion matrix is a technique for summarizing the performance of a classification algorithm.
*
Expand All @@ -179,26 +176,35 @@ export interface ConfusionMatrixOptions {
* @example
* import { confusion_matrix } from 'kalimdor/metrics';
*
* const matrix1 = confusion_matrix({
* y_true: [1, 2, 3],
* y_pred: [1, 2, 3]
* });
* const matrix1 = confusion_matrix([1, 2, 3], [1, 2, 3]);
* console.log(matrix1); // [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]
*
* const matrix2 = confusion_matrix({
* y_true: ['cat', 'ant', 'cat', 'cat', 'ant', 'bird'],
* y_pred: ['ant', 'ant', 'cat', 'cat', 'ant', 'cat']
* });
* const matrix2 = confusion_matrix(
* ['cat', 'ant', 'cat', 'cat', 'ant', 'bird'],
* ['ant', 'ant', 'cat', 'cat', 'ant', 'cat']
* );
* console.log(matrix2); // [ [ 1, 2, 0 ], [ 2, 0, 0 ], [ 0, 1, 0 ] ]
*
* @param {ConfusionMatrixOptions} options
* @returns {number[]}
* @param y_true - Ground truth (correct) target values.
* @param y_pred - Estimated targets as returned by a classifier.
* @param labels
*/
export function confusion_matrix(options: ConfusionMatrixOptions): number[] {
const y_true = _.get(options, 'y_true', null);
const y_pred = _.get(options, 'y_pred', null);
const labels = _.get(options, 'labels', null);

export function confusion_matrix(
y_true: Type1DMatrix<string | number> = null,
y_pred: Type1DMatrix<string | number> = null,
{
/**
* List of labels to index the matrix. This may be used to reorder or
* select a subset of labels. If none is given, those that appear
* at least once in y_true or y_pred are used in sorted order.
*/
labels = null
}: {
labels?: any[];
} = {
labels: null
}
): number[] {
validateInitialInputs(y_true, y_pred, labels);

// TODO: Sorting if set by options
Expand Down
32 changes: 9 additions & 23 deletions src/lib/metrics/index.repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,30 @@

import { accuracyScore, zeroOneLoss, confusion_matrix } from './classification';

const accResult = accuracyScore({
y_true: [0, 1, 2, 3],
y_pred: [0, 2, 1, 3]
});
const accResult = accuracyScore([0, 1, 2, 3], [0, 2, 1, 3]);

console.log('accuracy result ', accResult);

const accResultNorm = accuracyScore({
y_true: [0, 1, 2, 3],
y_pred: [0, 2, 1, 3],
const accResultNorm = accuracyScore([0, 1, 2, 3], [0, 2, 1, 3], {
normalize: false
});

console.log('accuracy result with norm false ', accResultNorm);

const loss_zero_one_result = zeroOneLoss({
y_true: [1, 2, 3, 4],
y_pred: [2, 2, 3, 5]
});
const loss_zero_one_result = zeroOneLoss([1, 2, 3, 4], [2, 2, 3, 5]);

console.log('loss zero one ', loss_zero_one_result);

const matrix1 = confusion_matrix({
y_true: [1, 2, 3],
y_pred: [1, 2, 3]
});
const matrix1 = confusion_matrix([1, 2, 3], [1, 2, 3]);
console.log(matrix1);

const matrix2 = confusion_matrix({
y_true: [2, 0, 2, 2, 0, 1],
y_pred: [0, 0, 2, 2, 0, 2]
});
const matrix2 = confusion_matrix([2, 0, 2, 2, 0, 1], [0, 0, 2, 2, 0, 2]);
console.log(matrix2);

const matrix3 = confusion_matrix({
y_true: ['cat', 'ant', 'cat', 'cat', 'ant', 'bird'],
y_pred: ['ant', 'ant', 'cat', 'cat', 'ant', 'cat']
});
const matrix3 = confusion_matrix(
['cat', 'ant', 'cat', 'cat', 'ant', 'bird'],
['ant', 'ant', 'cat', 'cat', 'ant', 'cat']
);

console.log(matrix3);

Expand Down
Loading