@datagrok/eda 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/LICENSE.txt +202 -0
- package/README.md +11 -1
- package/dist/221.js +2 -0
- package/dist/694.js +2 -0
- package/dist/729.js +2 -0
- package/dist/80.js +2 -0
- package/dist/package-test.js +2 -2
- package/dist/package.js +2 -2
- package/package.json +12 -9
- package/src/eda-tools.ts +185 -0
- package/src/{EDAui.ts → eda-ui.ts} +6 -0
- package/src/package.ts +63 -11
- package/src/utils.ts +129 -2
- package/src/workers/tsne-worker.ts +20 -0
- package/src/workers/umap-worker.ts +9 -0
- package/src/EDAtools.ts +0 -46
- /package/src/{dataGenerators.ts → data-generators.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datagrok/eda",
|
|
3
3
|
"friendlyName": "EDA",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.3",
|
|
5
5
|
"description": "Exploratory Data Analysis Tools",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"datagrok-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"@
|
|
11
|
-
"
|
|
7
|
+
"@datagrok-libraries/ml": "^6.3.39",
|
|
8
|
+
"@datagrok-libraries/tutorials": "^1.3.6",
|
|
9
|
+
"@datagrok-libraries/utils": "^4.1.4",
|
|
10
|
+
"@keckelt/tsne": "^1.0.2",
|
|
11
|
+
"cash-dom": "^8.1.1",
|
|
12
|
+
"datagrok-api": "^1.16.0",
|
|
13
|
+
"dayjs": "^1.11.9",
|
|
14
|
+
"umap-js": "^1.3.3"
|
|
12
15
|
},
|
|
13
16
|
"author": {
|
|
14
17
|
"name": "Viktor Makarichev",
|
|
15
18
|
"email": "vmakarichev@datagrok.ai"
|
|
16
19
|
},
|
|
17
20
|
"devDependencies": {
|
|
18
|
-
"webpack": "latest",
|
|
19
|
-
"webpack-cli": "latest",
|
|
20
21
|
"ts-loader": "latest",
|
|
21
|
-
"typescript": "latest"
|
|
22
|
+
"typescript": "latest",
|
|
23
|
+
"webpack": "latest",
|
|
24
|
+
"webpack-cli": "latest"
|
|
22
25
|
},
|
|
23
26
|
"scripts": {
|
|
24
27
|
"link-all": "npm link datagrok-api @datagrok-libraries/utils @datagrok-libraries/tutorials",
|
package/src/eda-tools.ts
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// Exploratory data analysis (EDA) tools
|
|
2
|
+
|
|
3
|
+
import * as grok from 'datagrok-api/grok';
|
|
4
|
+
import * as ui from 'datagrok-api/ui';
|
|
5
|
+
import * as DG from 'datagrok-api/dg';
|
|
6
|
+
|
|
7
|
+
import {DimensionalityReducer} from '@datagrok-libraries/ml/src/reduce-dimensionality';
|
|
8
|
+
import {VectorMetricsNames} from '@datagrok-libraries/ml/src/typed-metrics';
|
|
9
|
+
|
|
10
|
+
import {_principalComponentAnalysisInWebWorker,
|
|
11
|
+
_partialLeastSquareRegressionInWebWorker} from '../wasm/EDAAPI';
|
|
12
|
+
|
|
13
|
+
import {checkWasmDimensionReducerInputs, checkUMAPinputs, checkTSNEinputs, checkSPEinputs,
|
|
14
|
+
getRowsOfNumericalColumnns} from './utils';
|
|
15
|
+
|
|
16
|
+
// Principal components analysis (PCA)
|
|
17
|
+
export async function computePCA(table: DG.DataFrame, features: DG.ColumnList, components: number,
|
|
18
|
+
center: boolean, scale: boolean): Promise<DG.DataFrame>
|
|
19
|
+
{
|
|
20
|
+
checkWasmDimensionReducerInputs(features, components);
|
|
21
|
+
|
|
22
|
+
const centerNum = center ? 1 : 0;
|
|
23
|
+
const scaleNum = scale ? 1 : 0;
|
|
24
|
+
|
|
25
|
+
return await _principalComponentAnalysisInWebWorker(table, features, components, centerNum, scaleNum);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Partial least square regression (PLS)
|
|
29
|
+
export async function computePLS(table: DG.DataFrame, features: DG.ColumnList, predict: DG.Column, components: number): Promise<any>
|
|
30
|
+
{
|
|
31
|
+
// Inputs are checked in the same manner as in PCA, since the same computations are applied.
|
|
32
|
+
checkWasmDimensionReducerInputs(features, components);
|
|
33
|
+
|
|
34
|
+
return await _partialLeastSquareRegressionInWebWorker(table, features, predict, components);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Uniform Manifold Approximation and Projection (UMAP)
|
|
38
|
+
export async function computeUMAP(features: DG.ColumnList, components: number, epochs: number,
|
|
39
|
+
neighbors: number, minDist: number, spread: number): Promise<DG.DataFrame>
|
|
40
|
+
{
|
|
41
|
+
// check inputs
|
|
42
|
+
checkUMAPinputs(features, components, epochs, neighbors, minDist, spread);
|
|
43
|
+
|
|
44
|
+
// get row-by-row data
|
|
45
|
+
const data = getRowsOfNumericalColumnns(features);
|
|
46
|
+
|
|
47
|
+
let workerOutput: any;
|
|
48
|
+
|
|
49
|
+
// UMAP in webworker
|
|
50
|
+
let promise = new Promise((resolve, reject) => {
|
|
51
|
+
const worker = new Worker(new URL('workers/umap-worker.ts', import.meta.url));
|
|
52
|
+
|
|
53
|
+
worker.postMessage({
|
|
54
|
+
data: data,
|
|
55
|
+
options: {
|
|
56
|
+
nComponents: components,
|
|
57
|
+
nEpochs: epochs,
|
|
58
|
+
nNeighbors: neighbors,
|
|
59
|
+
minDist: minDist,
|
|
60
|
+
spread: spread
|
|
61
|
+
}});
|
|
62
|
+
|
|
63
|
+
worker.onmessage = function(e) {
|
|
64
|
+
worker.terminate();
|
|
65
|
+
resolve(e.data.embeddings);
|
|
66
|
+
}});
|
|
67
|
+
|
|
68
|
+
await promise.then(
|
|
69
|
+
result => { workerOutput = result; },
|
|
70
|
+
error => { throw new Error ('applying UMAP fails.'); }
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const embeddings = workerOutput as number[][];
|
|
74
|
+
const rowCount = embeddings.length;
|
|
75
|
+
const range = [...Array(components).keys()];
|
|
76
|
+
|
|
77
|
+
// Create output
|
|
78
|
+
|
|
79
|
+
// columns data
|
|
80
|
+
const umapColumnsData = range.map(_ => new Float32Array(rowCount));
|
|
81
|
+
|
|
82
|
+
// perform transponation
|
|
83
|
+
for (let i = 0; i < rowCount; ++i)
|
|
84
|
+
for (let j = 0; j < components; ++j)
|
|
85
|
+
umapColumnsData[j][i] = embeddings[i][j];
|
|
86
|
+
|
|
87
|
+
return DG.DataFrame.fromColumns(range.map(i =>
|
|
88
|
+
DG.Column.fromFloat32Array('UMAP' + i.toString(), umapColumnsData[i])
|
|
89
|
+
));
|
|
90
|
+
} // computeUMAP
|
|
91
|
+
|
|
92
|
+
// t-distributed stochastic neighbor embedding (t-SNE)
|
|
93
|
+
export async function computeTSNE(features: DG.ColumnList, components: number,
|
|
94
|
+
learningRate: number, perplexity: number, iterations: number): Promise<DG.DataFrame>
|
|
95
|
+
{
|
|
96
|
+
// check inputs
|
|
97
|
+
checkTSNEinputs(features, components, learningRate, perplexity, iterations);
|
|
98
|
+
|
|
99
|
+
// get row-by-row data
|
|
100
|
+
const data = getRowsOfNumericalColumnns(features);
|
|
101
|
+
|
|
102
|
+
let workerOutput: any;
|
|
103
|
+
|
|
104
|
+
// t-SNE in webworker
|
|
105
|
+
let promise = new Promise((resolve, reject) => {
|
|
106
|
+
const worker = new Worker(new URL('workers/tsne-worker.ts', import.meta.url));
|
|
107
|
+
|
|
108
|
+
worker.postMessage({
|
|
109
|
+
data: data,
|
|
110
|
+
options: {
|
|
111
|
+
learningRate: learningRate,
|
|
112
|
+
perplexity: perplexity,
|
|
113
|
+
components: components,
|
|
114
|
+
iterations: iterations
|
|
115
|
+
}});
|
|
116
|
+
|
|
117
|
+
worker.onmessage = function(e) {
|
|
118
|
+
worker.terminate();
|
|
119
|
+
resolve(e.data.embeddings);
|
|
120
|
+
}});
|
|
121
|
+
|
|
122
|
+
await promise.then(
|
|
123
|
+
result => { workerOutput = result; },
|
|
124
|
+
error => { throw new Error ('applying t-SNE fails.'); }
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const embeddings = workerOutput as any[];
|
|
128
|
+
|
|
129
|
+
const rowCount = embeddings.length;
|
|
130
|
+
const range = [...Array(components).keys()];
|
|
131
|
+
|
|
132
|
+
// Create output
|
|
133
|
+
|
|
134
|
+
// columns data
|
|
135
|
+
const umapColumnsData = range.map(_ => new Float32Array(rowCount));
|
|
136
|
+
|
|
137
|
+
// perform transponation
|
|
138
|
+
for (let i = 0; i < rowCount; ++i)
|
|
139
|
+
for (let j = 0; j < components; ++j)
|
|
140
|
+
umapColumnsData[j][i] = embeddings[i][j];
|
|
141
|
+
|
|
142
|
+
return DG.DataFrame.fromColumns(range.map(i =>
|
|
143
|
+
DG.Column.fromFloat32Array('tSNE' + i.toString(), umapColumnsData[i])
|
|
144
|
+
));
|
|
145
|
+
} // computeTSNE
|
|
146
|
+
|
|
147
|
+
// Stochastic proximity embedding (SPE)
|
|
148
|
+
export async function computeSPE(features: DG.ColumnList, dimension: number,
|
|
149
|
+
steps: number, cycles: number, cutoff: number, lambda: number): Promise<DG.DataFrame>
|
|
150
|
+
{
|
|
151
|
+
// check inputs
|
|
152
|
+
checkSPEinputs(features, dimension, steps, cycles, cutoff, lambda);
|
|
153
|
+
|
|
154
|
+
// get row-by-row data
|
|
155
|
+
const data = getRowsOfNumericalColumnns(features);
|
|
156
|
+
|
|
157
|
+
// SPE reducer
|
|
158
|
+
const spe = new DimensionalityReducer(data, 'SPE', VectorMetricsNames.Euclidean, {
|
|
159
|
+
dimension: dimension,
|
|
160
|
+
steps: steps,
|
|
161
|
+
cycles: cycles,
|
|
162
|
+
cutoff: cutoff,
|
|
163
|
+
lambda: lambda
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// compute embeddings
|
|
167
|
+
const embeddings = (await spe.transform(false, false)).embedding;
|
|
168
|
+
|
|
169
|
+
const rowCount = embeddings.length;
|
|
170
|
+
const range = [...Array(dimension).keys()];
|
|
171
|
+
|
|
172
|
+
// Create output
|
|
173
|
+
|
|
174
|
+
// columns data
|
|
175
|
+
const umapColumnsData = range.map(_ => new Float32Array(rowCount));
|
|
176
|
+
|
|
177
|
+
// perform transponation
|
|
178
|
+
for (let i = 0; i < rowCount; ++i)
|
|
179
|
+
for (let j = 0; j < dimension; ++j)
|
|
180
|
+
umapColumnsData[j][i] = embeddings[i][j];
|
|
181
|
+
|
|
182
|
+
return DG.DataFrame.fromColumns(range.map(i =>
|
|
183
|
+
DG.Column.fromFloat32Array('SPE' + i.toString(), umapColumnsData[i])
|
|
184
|
+
));
|
|
185
|
+
} // computeSPE
|
|
@@ -12,6 +12,12 @@ export function renamePCAcolumns(pcaTable: DG.DataFrame): DG.DataFrame {
|
|
|
12
12
|
return pcaTable;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Adds prefix to each column name
|
|
16
|
+
export function addPrefixToEachColumnName(prefix: string, columns: DG.ColumnList): void {
|
|
17
|
+
for (const col of columns.toList())
|
|
18
|
+
col.name = prefix + col.name;
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
// Predicted vs Reference scatter plot
|
|
16
22
|
export function predictedVersusReferenceScatterPlot(samplesNames: DG.Column, reference: DG.Column, prediction: DG.Column): DG.Viewer {
|
|
17
23
|
prediction.name = reference.name + '(predicted)';
|
package/src/package.ts
CHANGED
|
@@ -6,10 +6,10 @@ import * as DG from 'datagrok-api/dg';
|
|
|
6
6
|
import {DemoScript} from '@datagrok-libraries/tutorials/src/demo-script';
|
|
7
7
|
|
|
8
8
|
import {_initEDAAPI} from '../wasm/EDAAPI';
|
|
9
|
-
import {computePCA, computePLS} from './
|
|
10
|
-
import {
|
|
11
|
-
scoresScatterPlot, predictedVersusReferenceScatterPlot} from './
|
|
12
|
-
import {carsDataframe, testDataForBinaryClassification} from './
|
|
9
|
+
import {computePCA, computePLS, computeUMAP, computeTSNE, computeSPE} from './eda-tools';
|
|
10
|
+
import {addPrefixToEachColumnName, addPLSvisualization, regressionCoefficientsBarChart,
|
|
11
|
+
scoresScatterPlot, predictedVersusReferenceScatterPlot} from './eda-ui';
|
|
12
|
+
import {carsDataframe, testDataForBinaryClassification} from './data-generators';
|
|
13
13
|
import {LINEAR, RBF, POLYNOMIAL, SIGMOID,
|
|
14
14
|
getTrainedModel, getPrediction, showTrainReport, getPackedModel} from './svm';
|
|
15
15
|
|
|
@@ -25,19 +25,71 @@ export async function init(): Promise<void> {
|
|
|
25
25
|
await _initEDAAPI();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
//top-menu:
|
|
28
|
+
//top-menu: ML | Dimension Reduction | PCA...
|
|
29
29
|
//name: PCA
|
|
30
30
|
//description: Principal component analysis (PCA).
|
|
31
|
-
//input: dataframe table
|
|
32
|
-
//input: column_list features {type: numerical}
|
|
33
|
-
//input: int components = 2
|
|
34
|
-
//input: bool center =
|
|
35
|
-
//input: bool scale =
|
|
31
|
+
//input: dataframe table {category: Data}
|
|
32
|
+
//input: column_list features {type: numerical; category: Data}
|
|
33
|
+
//input: int components = 2 {caption: Components; category: Hyperparameters} [Number of components.]
|
|
34
|
+
//input: bool center = false {category: Hyperparameters} [Indicating whether the variables should be shifted to be zero centered.]
|
|
35
|
+
//input: bool scale = false {category: Hyperparameters} [Indicating whether the variables should be scaled to have unit variance.]
|
|
36
36
|
//output: dataframe result {action:join(table)}
|
|
37
37
|
export async function PCA(table: DG.DataFrame, features: DG.ColumnList, components: number,
|
|
38
38
|
center: boolean, scale: boolean): Promise<DG.DataFrame>
|
|
39
39
|
{
|
|
40
|
-
|
|
40
|
+
const pcaTable = await computePCA(table, features, components, center, scale);
|
|
41
|
+
addPrefixToEachColumnName('PCA', pcaTable.columns);
|
|
42
|
+
return pcaTable;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//top-menu: ML | Dimension Reduction | UMAP...
|
|
46
|
+
//name: UMAP
|
|
47
|
+
//description: Uniform Manifold Approximation and Projection (UMAP).
|
|
48
|
+
//input: dataframe table {category: Data}
|
|
49
|
+
//input: column_list features {type: numerical; category: Data}
|
|
50
|
+
//input: int components = 2 {caption: Components; category: Hyperparameters} [The number of components (dimensions) to project the data to.]
|
|
51
|
+
//input: int epochs = 100 {caption: Epochs; category: Hyperparameters} [The number of epochs to optimize embeddings.]
|
|
52
|
+
//input: int neighbors = 15 {caption: Neighbors; category: Hyperparameters} [The number of nearest neighbors to construct the fuzzy manifold.]
|
|
53
|
+
//input: double minDist = 0.1 {caption: Minimum distance; category: Hyperparameters} [The effective minimum distance between embedded points.]
|
|
54
|
+
//input: double spread = 1.0 {caption: Spread; category: Hyperparameters} [The effective scale of embedded points.]
|
|
55
|
+
//output: dataframe result {action:join(table)}
|
|
56
|
+
export async function UMAP(table: DG.DataFrame, features: DG.ColumnList, components: number,
|
|
57
|
+
epochs: number, neighbors: number, minDist: number, spread: number): Promise<DG.DataFrame>
|
|
58
|
+
{
|
|
59
|
+
return await computeUMAP(features, components, epochs, neighbors, minDist, spread);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//top-menu: ML | Dimension Reduction | t-SNE...
|
|
63
|
+
//name: t-SNE
|
|
64
|
+
//description: t-distributed stochastic neighbor embedding (t-SNE).
|
|
65
|
+
//input: dataframe table {category: Data}
|
|
66
|
+
//input: column_list features {type: numerical; category: Data}
|
|
67
|
+
//input: int components = 2 {caption: Components; category: Hyperparameters} [Dimension of the embedded space.]
|
|
68
|
+
//input: double learningRate = 10 {caption: Learning rate; category: Hyperparameters} [Optimization tuning parameter. Should be in the range 10...1000.]
|
|
69
|
+
//input: int perplexity = 30 {caption: Perplexity; category: Hyperparameters} [The number of nearest neighbors. Should be less than the number of samples.]
|
|
70
|
+
//input: int iterations = 500 {caption: Iterations; category: Hyperparameters} [Maximum number of iterations for the optimization. Should be at least 250.]
|
|
71
|
+
//output: dataframe result {action:join(table)}
|
|
72
|
+
export async function tSNE(table: DG.DataFrame, features: DG.ColumnList, components: number,
|
|
73
|
+
learningRate: number, perplexity: number, iterations: number): Promise<DG.DataFrame>
|
|
74
|
+
{
|
|
75
|
+
return await computeTSNE(features, components, learningRate, perplexity, iterations);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//top-menu: ML | Dimension Reduction | SPE...
|
|
79
|
+
//name: SPE
|
|
80
|
+
//description: Stochastic proximity embedding (SPE).
|
|
81
|
+
//input: dataframe table {category: Data}
|
|
82
|
+
//input: column_list features {type: numerical; category: Data}
|
|
83
|
+
//input: int dimension = 2 {caption: Dimension; category: Hyperparameters} [Dimension of the embedded space.]
|
|
84
|
+
//input: int steps = 0 {caption: Steps; category: Hyperparameters} [Number of random selections of point pairs and distance computations between them.]
|
|
85
|
+
//input: int cycles = 1000000 {caption: Cycles; category: Hyperparameters} [Number of the method cycles.]
|
|
86
|
+
//input: double cutoff = 0.0 {caption: Cutoff; category: Hyperparameters} [Cutoff distance between points.]
|
|
87
|
+
//input: double lambda = 2.0 {caption: Learning rate; category: Hyperparameters} [Optimization tuning parameter.]
|
|
88
|
+
//output: dataframe result {action:join(table)}
|
|
89
|
+
export async function SPE(table: DG.DataFrame, features: DG.ColumnList, dimension: number,
|
|
90
|
+
steps: number, cycles: number, cutoff: number, lambda: number): Promise<DG.DataFrame>
|
|
91
|
+
{
|
|
92
|
+
return await computeSPE(features, dimension, steps, cycles, cutoff, lambda);
|
|
41
93
|
}
|
|
42
94
|
|
|
43
95
|
//top-menu: ML | Multivariate Analysis (PLS)...
|
package/src/utils.ts
CHANGED
|
@@ -20,15 +20,117 @@ const INCORERRECT_FEATURES_MES = 'features must be positive.';
|
|
|
20
20
|
const INCORERRECT_SAMPLES_MES = 'samples must be positive.';
|
|
21
21
|
const INCORERRECT_PERCENTAGE_MES = 'violators percentage must be from the range from 0 to 100.';
|
|
22
22
|
const DATAFRAME_IS_TOO_BIG_MES = 'dataframe is too big.';
|
|
23
|
+
const UNSUPPORTED_COLUMN_TYPE_MES = 'unsupported column type: ';
|
|
24
|
+
const INCORRECT_MIN_DIST_MES = 'min distance must be positive.';
|
|
25
|
+
const INCORRECT_SPREAD_MES = 'spread must be positive.';
|
|
26
|
+
const INCORRECT_EPOCH_MES = 'number of epoch must be at least 1.';
|
|
27
|
+
const INCORRECT_NEIBORS_MES = 'number of neibors must be at least 2 and not greater than samples count.';
|
|
28
|
+
const INCORRECT_ITERATIONS_MES = 'number of iterations must be at least 1.';
|
|
29
|
+
const INCORRECT_LEARNING_RATE_MES = 'learning rate must be positive.';
|
|
30
|
+
const INCORRECT_PERPLEXITY_MES = 'perplexity must be at least 2 and not greater than samples count.';
|
|
31
|
+
const INCORRECT_STEPS_MES = 'steps must be non-negative.';
|
|
32
|
+
const INCORRECT_CYCLES_MES = 'cycles must be positive.';
|
|
33
|
+
const INCORRECT_CUTOFF_MES = 'cutoff must be non-negative.'
|
|
23
34
|
|
|
24
|
-
// Check
|
|
25
|
-
export function
|
|
35
|
+
// Check column type
|
|
36
|
+
export function checkColumnType(col: DG.Column): void {
|
|
37
|
+
if ((col.type != DG.COLUMN_TYPE.FLOAT) && (col.type != DG.COLUMN_TYPE.INT))
|
|
38
|
+
throw new Error(UNSUPPORTED_COLUMN_TYPE_MES + col.type);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Check dimension reducer inputs
|
|
42
|
+
export function checkDimensionReducerInputs(features: DG.ColumnList, components: number): void {
|
|
26
43
|
if (components < COMP_MIN)
|
|
27
44
|
throw new Error(COMP_POSITVE_MES);
|
|
28
45
|
|
|
29
46
|
if (components > features.length)
|
|
30
47
|
throw new Error(COMP_EXCESS);
|
|
31
48
|
|
|
49
|
+
for (const col of features)
|
|
50
|
+
checkColumnType(col);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Check UMAP inputs
|
|
54
|
+
export function checkUMAPinputs(features: DG.ColumnList, components: number, epochs: number,
|
|
55
|
+
neighbors: number, minDist: number, spread: number): void
|
|
56
|
+
{
|
|
57
|
+
// General dim reducer checks
|
|
58
|
+
checkDimensionReducerInputs(features, components);
|
|
59
|
+
|
|
60
|
+
// Check data total size
|
|
61
|
+
if (features.length * features.byIndex(0).length > MAX_ELEMENTS_COUNT)
|
|
62
|
+
throw new Error(DATAFRAME_IS_TOO_BIG_MES);
|
|
63
|
+
|
|
64
|
+
// UMAP specific checks
|
|
65
|
+
|
|
66
|
+
if (minDist <= 0)
|
|
67
|
+
throw new Error(INCORRECT_MIN_DIST_MES);
|
|
68
|
+
|
|
69
|
+
if (spread <= 0)
|
|
70
|
+
throw new Error(INCORRECT_SPREAD_MES);
|
|
71
|
+
|
|
72
|
+
if (epochs < 1)
|
|
73
|
+
throw new Error(INCORRECT_EPOCH_MES);
|
|
74
|
+
|
|
75
|
+
if ((neighbors < 2) || (neighbors > features.byIndex(0).length))
|
|
76
|
+
throw new Error(INCORRECT_NEIBORS_MES);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check t-SNE inputs
|
|
80
|
+
export function checkTSNEinputs(features: DG.ColumnList, components: number,
|
|
81
|
+
learningRate: number, perplexity: number, iterations: number): void
|
|
82
|
+
{
|
|
83
|
+
// General dim reducer checks
|
|
84
|
+
checkDimensionReducerInputs(features, components);
|
|
85
|
+
|
|
86
|
+
// Check data total size
|
|
87
|
+
if (features.length * features.byIndex(0).length > MAX_ELEMENTS_COUNT)
|
|
88
|
+
throw new Error(DATAFRAME_IS_TOO_BIG_MES);
|
|
89
|
+
|
|
90
|
+
// t-SNE specific checks
|
|
91
|
+
|
|
92
|
+
if (learningRate < 0)
|
|
93
|
+
throw new Error(INCORRECT_LEARNING_RATE_MES);
|
|
94
|
+
|
|
95
|
+
if (iterations < 1)
|
|
96
|
+
throw new Error(INCORRECT_ITERATIONS_MES);
|
|
97
|
+
|
|
98
|
+
if ((perplexity < 2) || (perplexity > features.byIndex(0).length))
|
|
99
|
+
throw new Error(INCORRECT_PERPLEXITY_MES);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check SPE inputs
|
|
103
|
+
export function checkSPEinputs(features: DG.ColumnList, dimension: number,
|
|
104
|
+
steps: number, cycles: number, cutoff: number, lambda: number): void
|
|
105
|
+
{
|
|
106
|
+
// General dim reducer checks
|
|
107
|
+
checkDimensionReducerInputs(features, dimension);
|
|
108
|
+
|
|
109
|
+
// Check data total size
|
|
110
|
+
if (features.length * features.byIndex(0).length > MAX_ELEMENTS_COUNT)
|
|
111
|
+
throw new Error(DATAFRAME_IS_TOO_BIG_MES);
|
|
112
|
+
|
|
113
|
+
// SPE specific checks
|
|
114
|
+
|
|
115
|
+
if (steps < 0)
|
|
116
|
+
throw new Error(INCORRECT_STEPS_MES);
|
|
117
|
+
|
|
118
|
+
if (cycles <= 0)
|
|
119
|
+
throw new Error(INCORRECT_CYCLES_MES);
|
|
120
|
+
|
|
121
|
+
if (cutoff < 0)
|
|
122
|
+
throw new Error(INCORRECT_CUTOFF_MES);
|
|
123
|
+
|
|
124
|
+
if (lambda <= 0)
|
|
125
|
+
throw new Error(INCORRECT_LEARNING_RATE_MES);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Check wasm dimension reducer inputs
|
|
129
|
+
export function checkWasmDimensionReducerInputs(features: DG.ColumnList, components: number): void {
|
|
130
|
+
// General dim reducer checks
|
|
131
|
+
checkDimensionReducerInputs(features, components);
|
|
132
|
+
|
|
133
|
+
// Check data total size
|
|
32
134
|
if (features.length * features.byIndex(0).length > MAX_ELEMENTS_COUNT)
|
|
33
135
|
throw new Error(DATAFRAME_IS_TOO_BIG_MES);
|
|
34
136
|
}
|
|
@@ -49,3 +151,28 @@ export function checkGeneratorSVMinputs(samplesCount: number, featuresCount: num
|
|
|
49
151
|
if ((violatorsPercentage < PERCENTAGE_MIN) || (violatorsPercentage > PERCENTAGE_MAX))
|
|
50
152
|
throw new Error(INCORERRECT_PERCENTAGE_MES);
|
|
51
153
|
}
|
|
154
|
+
|
|
155
|
+
// Returns rows of column data
|
|
156
|
+
export function getRowsOfNumericalColumnns(columnList: DG.ColumnList): any[][] {
|
|
157
|
+
const columns = columnList.toList();
|
|
158
|
+
const rowCount = columns[0].length;
|
|
159
|
+
const colCount = columns.length;
|
|
160
|
+
|
|
161
|
+
const output = [] as any[][];
|
|
162
|
+
|
|
163
|
+
for (let i = 0; i < rowCount; ++i)
|
|
164
|
+
output.push(Array(colCount));
|
|
165
|
+
|
|
166
|
+
for (let j = 0; j < colCount; ++j) {
|
|
167
|
+
const col = columns[j];
|
|
168
|
+
|
|
169
|
+
checkColumnType(col);
|
|
170
|
+
|
|
171
|
+
const array = col.getRawData();
|
|
172
|
+
|
|
173
|
+
for (let i = 0; i < rowCount; ++i)
|
|
174
|
+
output[i][j] = array[i];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return output;
|
|
178
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Worker for the method t-SNE
|
|
2
|
+
|
|
3
|
+
import {TSNE} from '@keckelt/tsne';
|
|
4
|
+
|
|
5
|
+
onmessage = async function (evt) {
|
|
6
|
+
const tsne = new TSNE({
|
|
7
|
+
epsilon: evt.data.options.learningRate,
|
|
8
|
+
perplexity: evt.data.options.perplexity,
|
|
9
|
+
dim: evt.data.options.components
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
tsne.initDataRaw(evt.data.data);
|
|
13
|
+
|
|
14
|
+
const iterCount = evt.data.options.iterations;
|
|
15
|
+
|
|
16
|
+
for(let i = 0; i < iterCount; ++i)
|
|
17
|
+
tsne.step();
|
|
18
|
+
|
|
19
|
+
postMessage({'embeddings': tsne.getSolution()});
|
|
20
|
+
}
|
package/src/EDAtools.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// Exploratory data analysis (EDA) tools
|
|
2
|
-
|
|
3
|
-
import * as grok from 'datagrok-api/grok';
|
|
4
|
-
import * as ui from 'datagrok-api/ui';
|
|
5
|
-
import * as DG from 'datagrok-api/dg';
|
|
6
|
-
|
|
7
|
-
import {_principalComponentAnalysisInWebWorker,
|
|
8
|
-
_partialLeastSquareRegressionInWebWorker} from '../wasm/EDAAPI';
|
|
9
|
-
|
|
10
|
-
import {checkComponenets, checkGeneratorSVMinputs} from './utils';
|
|
11
|
-
|
|
12
|
-
// Principal components analysis (PCA)
|
|
13
|
-
export async function computePCA(table: DG.DataFrame, features: DG.ColumnList, components: number,
|
|
14
|
-
center: boolean, scale: boolean): Promise<DG.DataFrame>
|
|
15
|
-
{
|
|
16
|
-
checkComponenets(features, components);
|
|
17
|
-
|
|
18
|
-
const centerNum = center ? 1 : 0;
|
|
19
|
-
const scaleNum = scale ? 1 : 0;
|
|
20
|
-
|
|
21
|
-
let _output: any;
|
|
22
|
-
let _promise = _principalComponentAnalysisInWebWorker(table, features, components, centerNum, scaleNum);
|
|
23
|
-
|
|
24
|
-
await _promise.then(
|
|
25
|
-
_result => { _output = _result; },
|
|
26
|
-
_error => { throw new Error (`Error: ${_error}`); }
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
return _output;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Partial least square regression (PLS)
|
|
33
|
-
export async function computePLS(table: DG.DataFrame, features: DG.ColumnList, predict: DG.Column, components: number): Promise<any>
|
|
34
|
-
{
|
|
35
|
-
checkComponenets(features, components);
|
|
36
|
-
|
|
37
|
-
let _output: any;
|
|
38
|
-
let _promise = _partialLeastSquareRegressionInWebWorker(table, features, predict, components);
|
|
39
|
-
|
|
40
|
-
await _promise.then(
|
|
41
|
-
_result => { _output = _result; },
|
|
42
|
-
_error => { throw new Error (`Error: ${_error}`); }
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
return _output;
|
|
46
|
-
}
|
|
File without changes
|