deepbox 0.1.0 → 0.2.0
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/LICENSE +1 -1
- package/README.md +39 -37
- package/dist/{CSRMatrix-KzNt6QpS.d.ts → CSRMatrix-B7XtUAZO.d.cts} +3 -3
- package/dist/{CSRMatrix-CwGwQRea.d.cts → CSRMatrix-CtD23fRM.d.ts} +3 -3
- package/dist/{Tensor-BQLk1ltW.d.cts → Tensor-BORFp_zt.d.ts} +27 -7
- package/dist/{Tensor-g8mUClel.d.ts → Tensor-fxBg-TFZ.d.cts} +27 -7
- package/dist/{chunk-FJYLIGJX.js → chunk-3AX37GPK.js} +33 -7
- package/dist/chunk-3AX37GPK.js.map +1 -0
- package/dist/{chunk-PR647I7R.js → chunk-3YFEYDHN.js} +21 -4
- package/dist/chunk-3YFEYDHN.js.map +1 -0
- package/dist/{chunk-XMWVME2W.js → chunk-6SX26MAJ.js} +4 -4
- package/dist/{chunk-XMWVME2W.js.map → chunk-6SX26MAJ.js.map} +1 -1
- package/dist/{chunk-C4PKXY74.cjs → chunk-6X7XFNDO.cjs} +94 -77
- package/dist/chunk-6X7XFNDO.cjs.map +1 -0
- package/dist/{chunk-6AE5FKKQ.cjs → chunk-724CXHFH.cjs} +1211 -919
- package/dist/chunk-724CXHFH.cjs.map +1 -0
- package/dist/{chunk-AU7XHGKJ.js → chunk-AJTKVBY5.js} +4 -4
- package/dist/{chunk-AU7XHGKJ.js.map → chunk-AJTKVBY5.js.map} +1 -1
- package/dist/{chunk-ZB75FESB.cjs → chunk-AV6WGSYX.cjs} +130 -104
- package/dist/chunk-AV6WGSYX.cjs.map +1 -0
- package/dist/{chunk-ZLW62TJG.cjs → chunk-BWOSU234.cjs} +142 -141
- package/dist/chunk-BWOSU234.cjs.map +1 -0
- package/dist/{chunk-4S73VUBD.js → chunk-CZOMBUI7.js} +3 -3
- package/dist/chunk-CZOMBUI7.js.map +1 -0
- package/dist/{chunk-QERHVCHC.cjs → chunk-EUZHJDZ6.cjs} +419 -364
- package/dist/chunk-EUZHJDZ6.cjs.map +1 -0
- package/dist/{chunk-AD436M45.js → chunk-G2G55ATL.js} +120 -58
- package/dist/chunk-G2G55ATL.js.map +1 -0
- package/dist/{chunk-5R4S63PF.js → chunk-G3WNLNYS.js} +119 -64
- package/dist/chunk-G3WNLNYS.js.map +1 -0
- package/dist/{chunk-XEG44RF6.cjs → chunk-G7KXZHG6.cjs} +105 -95
- package/dist/chunk-G7KXZHG6.cjs.map +1 -0
- package/dist/{chunk-MLBMYKCG.js → chunk-H3JR7SV2.js} +255 -113
- package/dist/chunk-H3JR7SV2.js.map +1 -0
- package/dist/{chunk-PHV2DKRS.cjs → chunk-HDKMIG6E.cjs} +107 -107
- package/dist/{chunk-PHV2DKRS.cjs.map → chunk-HDKMIG6E.cjs.map} +1 -1
- package/dist/{chunk-ALS7ETWZ.cjs → chunk-HI2EZHCJ.cjs} +111 -102
- package/dist/chunk-HI2EZHCJ.cjs.map +1 -0
- package/dist/{chunk-OX6QXFMV.cjs → chunk-IT4BZUYE.cjs} +490 -428
- package/dist/chunk-IT4BZUYE.cjs.map +1 -0
- package/dist/{chunk-E3EU5FZO.cjs → chunk-JTZPRV6E.cjs} +123 -123
- package/dist/{chunk-E3EU5FZO.cjs.map → chunk-JTZPRV6E.cjs.map} +1 -1
- package/dist/{chunk-PL7TAYKI.js → chunk-K2L5C5YH.js} +8 -7
- package/dist/chunk-K2L5C5YH.js.map +1 -0
- package/dist/{chunk-BCR7G3A6.js → chunk-KCF6P34A.js} +356 -64
- package/dist/chunk-KCF6P34A.js.map +1 -0
- package/dist/{chunk-ZXKBDFP3.js → chunk-LZHVHD62.js} +15 -6
- package/dist/chunk-LZHVHD62.js.map +1 -0
- package/dist/{chunk-LWECRCW2.cjs → chunk-MTJF52AJ.cjs} +141 -141
- package/dist/{chunk-LWECRCW2.cjs.map → chunk-MTJF52AJ.cjs.map} +1 -1
- package/dist/{chunk-B5TNKUEY.js → chunk-NDDTUFKK.js} +16 -6
- package/dist/chunk-NDDTUFKK.js.map +1 -0
- package/dist/{chunk-DWZY6PIP.cjs → chunk-NOQI6OFL.cjs} +615 -473
- package/dist/chunk-NOQI6OFL.cjs.map +1 -0
- package/dist/{chunk-F3JWBINJ.js → chunk-OEXDJFHA.js} +4 -4
- package/dist/{chunk-F3JWBINJ.js.map → chunk-OEXDJFHA.js.map} +1 -1
- package/dist/{chunk-JSCDE774.cjs → chunk-Z6BGACIH.cjs} +3 -3
- package/dist/chunk-Z6BGACIH.cjs.map +1 -0
- package/dist/core/index.cjs +50 -50
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/dataframe/index.cjs +6 -6
- package/dist/dataframe/index.d.cts +3 -3
- package/dist/dataframe/index.d.ts +3 -3
- package/dist/dataframe/index.js +3 -3
- package/dist/datasets/index.cjs +34 -34
- package/dist/datasets/index.d.cts +3 -3
- package/dist/datasets/index.d.ts +3 -3
- package/dist/datasets/index.js +3 -3
- package/dist/{index-C1mfVYoo.d.ts → index-B18dHc8q.d.ts} +81 -46
- package/dist/{index-GFAVyOWO.d.ts → index-BHHX0qTY.d.cts} +14 -12
- package/dist/{index-tk4lSYod.d.ts → index-BI6QOUvV.d.ts} +106 -80
- package/dist/{index-DIp_RrRt.d.ts → index-BKvK21lf.d.ts} +13 -35
- package/dist/{index-BJY2SI4i.d.ts → index-BL8jLf3K.d.cts} +12 -11
- package/dist/{index-Cn3SdB0O.d.ts → index-BNbX167d.d.cts} +16 -10
- package/dist/{index-BWGhrDlr.d.ts → index-BT2ofL7Z.d.cts} +35 -35
- package/dist/{index-BbA2Gxfl.d.ts → index-BqcfIcL4.d.ts} +15 -15
- package/dist/{index-ZtI1Iy4L.d.ts → index-BrgrECM2.d.ts} +41 -38
- package/dist/{index-CDw5CnOU.d.ts → index-BtYKI9yJ.d.ts} +10 -8
- package/dist/{index-DIT_OO9C.d.cts → index-C7nLsAOC.d.cts} +10 -8
- package/dist/{index-D9Loo1_A.d.cts → index-CNj2Mxwf.d.cts} +81 -46
- package/dist/{index-DmEg_LCm.d.cts → index-CYlxeNW1.d.cts} +5 -3
- package/dist/{index-D61yaSMY.d.cts → index-CiTd61a5.d.ts} +12 -11
- package/dist/{index-BndMbqsM.d.ts → index-Cjnn0KeN.d.cts} +35 -21
- package/dist/{index-9oQx1HgV.d.cts → index-CkGGAn69.d.cts} +41 -38
- package/dist/{index-74AB8Cyh.d.cts → index-D4URSgqA.d.ts} +16 -10
- package/dist/{index-DoPWVxPo.d.cts → index-D4pn5zLT.d.ts} +35 -21
- package/dist/{index-DuCxd-8d.d.ts → index-D9ztTlDr.d.ts} +60 -42
- package/dist/{index-BgHYAoSS.d.cts → index-DF28ZPB5.d.cts} +60 -42
- package/dist/{index-eJgeni9c.d.cts → index-DLdiQzf0.d.cts} +106 -80
- package/dist/{index-WHQLn0e8.d.cts → index-DN4omPQw.d.ts} +35 -35
- package/dist/{index-CrqLlS-a.d.ts → index-DUnFq1WV.d.ts} +5 -3
- package/dist/{index-DbultU6X.d.cts → index-DgaYshkF.d.ts} +14 -12
- package/dist/{index-B_DK4FKY.d.cts → index-GUHYEhxs.d.cts} +13 -35
- package/dist/{index-CCvlwAmL.d.cts → index-TP--4irE.d.cts} +16 -14
- package/dist/{index-Dx42TZaY.d.ts → index-x0z_sanT.d.ts} +16 -14
- package/dist/{index-DyZ4QQf5.d.cts → index-xWH7ujWa.d.cts} +15 -15
- package/dist/index.cjs +26 -26
- package/dist/index.d.cts +17 -17
- package/dist/index.d.ts +17 -17
- package/dist/index.js +13 -13
- package/dist/linalg/index.cjs +22 -22
- package/dist/linalg/index.d.cts +3 -3
- package/dist/linalg/index.d.ts +3 -3
- package/dist/linalg/index.js +3 -3
- package/dist/metrics/index.cjs +40 -40
- package/dist/metrics/index.d.cts +3 -3
- package/dist/metrics/index.d.ts +3 -3
- package/dist/metrics/index.js +3 -3
- package/dist/ml/index.cjs +23 -23
- package/dist/ml/index.d.cts +3 -3
- package/dist/ml/index.d.ts +3 -3
- package/dist/ml/index.js +4 -4
- package/dist/ndarray/index.cjs +125 -125
- package/dist/ndarray/index.d.cts +5 -5
- package/dist/ndarray/index.d.ts +5 -5
- package/dist/ndarray/index.js +2 -2
- package/dist/nn/index.cjs +36 -36
- package/dist/nn/index.d.cts +6 -6
- package/dist/nn/index.d.ts +6 -6
- package/dist/nn/index.js +3 -3
- package/dist/optim/index.cjs +19 -19
- package/dist/optim/index.d.cts +4 -4
- package/dist/optim/index.d.ts +4 -4
- package/dist/optim/index.js +2 -2
- package/dist/plot/index.cjs +29 -29
- package/dist/plot/index.d.cts +6 -6
- package/dist/plot/index.d.ts +6 -6
- package/dist/plot/index.js +3 -3
- package/dist/preprocess/index.cjs +21 -21
- package/dist/preprocess/index.d.cts +4 -4
- package/dist/preprocess/index.d.ts +4 -4
- package/dist/preprocess/index.js +3 -3
- package/dist/random/index.cjs +19 -19
- package/dist/random/index.d.cts +3 -3
- package/dist/random/index.d.ts +3 -3
- package/dist/random/index.js +3 -3
- package/dist/stats/index.cjs +36 -36
- package/dist/stats/index.d.cts +3 -3
- package/dist/stats/index.d.ts +3 -3
- package/dist/stats/index.js +3 -3
- package/dist/{tensor-B96jjJLQ.d.cts → tensor-IlVTF0bz.d.cts} +16 -3
- package/dist/{tensor-B96jjJLQ.d.ts → tensor-IlVTF0bz.d.ts} +16 -3
- package/package.json +3 -2
- package/dist/chunk-4S73VUBD.js.map +0 -1
- package/dist/chunk-5R4S63PF.js.map +0 -1
- package/dist/chunk-6AE5FKKQ.cjs.map +0 -1
- package/dist/chunk-AD436M45.js.map +0 -1
- package/dist/chunk-ALS7ETWZ.cjs.map +0 -1
- package/dist/chunk-B5TNKUEY.js.map +0 -1
- package/dist/chunk-BCR7G3A6.js.map +0 -1
- package/dist/chunk-C4PKXY74.cjs.map +0 -1
- package/dist/chunk-DWZY6PIP.cjs.map +0 -1
- package/dist/chunk-FJYLIGJX.js.map +0 -1
- package/dist/chunk-JSCDE774.cjs.map +0 -1
- package/dist/chunk-MLBMYKCG.js.map +0 -1
- package/dist/chunk-OX6QXFMV.cjs.map +0 -1
- package/dist/chunk-PL7TAYKI.js.map +0 -1
- package/dist/chunk-PR647I7R.js.map +0 -1
- package/dist/chunk-QERHVCHC.cjs.map +0 -1
- package/dist/chunk-XEG44RF6.cjs.map +0 -1
- package/dist/chunk-ZB75FESB.cjs.map +0 -1
- package/dist/chunk-ZLW62TJG.cjs.map +0 -1
- package/dist/chunk-ZXKBDFP3.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { svd, lstsq, cholesky, solveTriangular } from './chunk-
|
|
2
|
-
import { tensor, mean, dot, sub, reshape, transpose, isContiguous } from './chunk-
|
|
3
|
-
import { __export, InvalidParameterError, NotImplementedError, NotFittedError, DataValidationError, ShapeError, DeepboxError } from './chunk-
|
|
1
|
+
import { svd, lstsq, cholesky, solveTriangular } from './chunk-AJTKVBY5.js';
|
|
2
|
+
import { tensor, mean, dot, sub, reshape, transpose, isContiguous } from './chunk-KCF6P34A.js';
|
|
3
|
+
import { __export, InvalidParameterError, NotImplementedError, NotFittedError, DataValidationError, ShapeError, DeepboxError } from './chunk-CZOMBUI7.js';
|
|
4
4
|
|
|
5
5
|
// src/ml/index.ts
|
|
6
6
|
var ml_exports = {};
|
|
@@ -272,6 +272,23 @@ var DBSCAN = class {
|
|
|
272
272
|
}
|
|
273
273
|
return this.labels_;
|
|
274
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Number of clusters found (excluding noise).
|
|
277
|
+
*
|
|
278
|
+
* @returns Number of distinct clusters (labels >= 0)
|
|
279
|
+
* @throws {NotFittedError} If the model has not been fitted
|
|
280
|
+
*/
|
|
281
|
+
get nClusters() {
|
|
282
|
+
if (!this.fitted || !this.labels_) {
|
|
283
|
+
throw new NotFittedError("DBSCAN must be fitted to access nClusters");
|
|
284
|
+
}
|
|
285
|
+
const unique = /* @__PURE__ */ new Set();
|
|
286
|
+
for (let i = 0; i < this.labels_.size; i++) {
|
|
287
|
+
const label = Number(this.labels_.data[this.labels_.offset + i]);
|
|
288
|
+
if (label >= 0) unique.add(label);
|
|
289
|
+
}
|
|
290
|
+
return unique.size;
|
|
291
|
+
}
|
|
275
292
|
/**
|
|
276
293
|
* Get indices of core samples discovered during fitting.
|
|
277
294
|
*
|
|
@@ -1903,10 +1920,10 @@ var GradientBoostingClassifier = class {
|
|
|
1903
1920
|
maxDepth;
|
|
1904
1921
|
/** Minimum samples to split */
|
|
1905
1922
|
minSamplesSplit;
|
|
1906
|
-
/**
|
|
1907
|
-
|
|
1908
|
-
/**
|
|
1909
|
-
|
|
1923
|
+
/** Per-class arrays of weak learners (OvR for multiclass, single for binary) */
|
|
1924
|
+
estimatorsPerClass = [];
|
|
1925
|
+
/** Per-class initial log-odds predictions */
|
|
1926
|
+
initPredictions = [];
|
|
1910
1927
|
/** Number of features */
|
|
1911
1928
|
nFeatures = 0;
|
|
1912
1929
|
/** Unique class labels */
|
|
@@ -1947,19 +1964,65 @@ var GradientBoostingClassifier = class {
|
|
|
1947
1964
|
);
|
|
1948
1965
|
}
|
|
1949
1966
|
}
|
|
1967
|
+
/**
|
|
1968
|
+
* Fit a single binary boosting ensemble.
|
|
1969
|
+
* Trains nEstimators regression trees to optimize log loss for a binary target.
|
|
1970
|
+
*/
|
|
1971
|
+
fitBinary(X, yBinary, nSamples) {
|
|
1972
|
+
const posCount = yBinary.filter((v) => v === 1).length;
|
|
1973
|
+
const negCount = nSamples - posCount;
|
|
1974
|
+
const initPred = Math.log((posCount + 1) / (negCount + 1));
|
|
1975
|
+
const rawScores = new Array(nSamples).fill(initPred);
|
|
1976
|
+
const estimators = [];
|
|
1977
|
+
for (let m = 0; m < this.nEstimators; m++) {
|
|
1978
|
+
const residuals = [];
|
|
1979
|
+
for (let i = 0; i < nSamples; i++) {
|
|
1980
|
+
const prob = 1 / (1 + Math.exp(-(rawScores[i] ?? 0)));
|
|
1981
|
+
residuals.push((yBinary[i] ?? 0) - prob);
|
|
1982
|
+
}
|
|
1983
|
+
const tree = new DecisionTreeRegressor({
|
|
1984
|
+
maxDepth: this.maxDepth,
|
|
1985
|
+
minSamplesSplit: this.minSamplesSplit,
|
|
1986
|
+
minSamplesLeaf: 1
|
|
1987
|
+
});
|
|
1988
|
+
tree.fit(X, tensor(residuals));
|
|
1989
|
+
estimators.push(tree);
|
|
1990
|
+
const treePred = tree.predict(X);
|
|
1991
|
+
for (let i = 0; i < nSamples; i++) {
|
|
1992
|
+
rawScores[i] = (rawScores[i] ?? 0) + this.learningRate * Number(treePred.data[treePred.offset + i]);
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
return { estimators, initPred };
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Compute raw scores for a single binary ensemble.
|
|
1999
|
+
*/
|
|
2000
|
+
predictRawBinary(X, classIdx) {
|
|
2001
|
+
const nSamples = X.shape[0] ?? 0;
|
|
2002
|
+
const rawScores = new Array(nSamples).fill(this.initPredictions[classIdx] ?? 0);
|
|
2003
|
+
const estimators = this.estimatorsPerClass[classIdx] ?? [];
|
|
2004
|
+
for (const tree of estimators) {
|
|
2005
|
+
const treePred = tree.predict(X);
|
|
2006
|
+
for (let i = 0; i < nSamples; i++) {
|
|
2007
|
+
rawScores[i] = (rawScores[i] ?? 0) + this.learningRate * Number(treePred.data[treePred.offset + i]);
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
return rawScores;
|
|
2011
|
+
}
|
|
1950
2012
|
/**
|
|
1951
2013
|
* Fit the gradient boosting classifier on training data.
|
|
1952
2014
|
*
|
|
1953
2015
|
* Builds an additive model by sequentially fitting regression trees
|
|
1954
2016
|
* to the pseudo-residuals (gradient of log loss).
|
|
2017
|
+
* Supports binary (2 classes) and multiclass (>2 classes via OvR).
|
|
1955
2018
|
*
|
|
1956
2019
|
* @param X - Training data of shape (n_samples, n_features)
|
|
1957
|
-
* @param y - Target class labels of shape (n_samples,). Must contain
|
|
2020
|
+
* @param y - Target class labels of shape (n_samples,). Must contain at least 2 classes.
|
|
1958
2021
|
* @returns this - The fitted estimator
|
|
1959
2022
|
* @throws {ShapeError} If X is not 2D or y is not 1D
|
|
1960
2023
|
* @throws {ShapeError} If X and y have different number of samples
|
|
1961
2024
|
* @throws {DataValidationError} If X or y contain NaN/Inf values
|
|
1962
|
-
* @throws {InvalidParameterError} If y does not contain
|
|
2025
|
+
* @throws {InvalidParameterError} If y does not contain at least 2 classes
|
|
1963
2026
|
*/
|
|
1964
2027
|
fit(X, y) {
|
|
1965
2028
|
validateFitInputs(X, y);
|
|
@@ -1971,36 +2034,26 @@ var GradientBoostingClassifier = class {
|
|
|
1971
2034
|
yData.push(Number(y.data[y.offset + i]));
|
|
1972
2035
|
}
|
|
1973
2036
|
this.classLabels = [...new Set(yData)].sort((a, b) => a - b);
|
|
1974
|
-
if (this.classLabels.length
|
|
2037
|
+
if (this.classLabels.length < 2) {
|
|
1975
2038
|
throw new InvalidParameterError(
|
|
1976
|
-
"GradientBoostingClassifier requires
|
|
2039
|
+
"GradientBoostingClassifier requires at least 2 classes",
|
|
1977
2040
|
"y",
|
|
1978
2041
|
this.classLabels.length
|
|
1979
2042
|
);
|
|
1980
2043
|
}
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
for (
|
|
1990
|
-
const
|
|
1991
|
-
const
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
const tree = new DecisionTreeRegressor({
|
|
1995
|
-
maxDepth: this.maxDepth,
|
|
1996
|
-
minSamplesSplit: this.minSamplesSplit,
|
|
1997
|
-
minSamplesLeaf: 1
|
|
1998
|
-
});
|
|
1999
|
-
tree.fit(X, tensor(residuals));
|
|
2000
|
-
this.estimators.push(tree);
|
|
2001
|
-
const treePred = tree.predict(X);
|
|
2002
|
-
for (let i = 0; i < nSamples; i++) {
|
|
2003
|
-
rawScores[i] = (rawScores[i] ?? 0) + this.learningRate * Number(treePred.data[treePred.offset + i]);
|
|
2044
|
+
this.estimatorsPerClass = [];
|
|
2045
|
+
this.initPredictions = [];
|
|
2046
|
+
if (this.classLabels.length === 2) {
|
|
2047
|
+
const yBinary = yData.map((label) => label === this.classLabels[0] ? 0 : 1);
|
|
2048
|
+
const { estimators, initPred } = this.fitBinary(X, yBinary, nSamples);
|
|
2049
|
+
this.estimatorsPerClass.push(estimators);
|
|
2050
|
+
this.initPredictions.push(initPred);
|
|
2051
|
+
} else {
|
|
2052
|
+
for (const classLabel of this.classLabels) {
|
|
2053
|
+
const yBinary = yData.map((label) => label === classLabel ? 1 : 0);
|
|
2054
|
+
const { estimators, initPred } = this.fitBinary(X, yBinary, nSamples);
|
|
2055
|
+
this.estimatorsPerClass.push(estimators);
|
|
2056
|
+
this.initPredictions.push(initPred);
|
|
2004
2057
|
}
|
|
2005
2058
|
}
|
|
2006
2059
|
this.fitted = true;
|
|
@@ -2021,29 +2074,40 @@ var GradientBoostingClassifier = class {
|
|
|
2021
2074
|
}
|
|
2022
2075
|
validatePredictInputs(X, this.nFeatures ?? 0, "GradientBoostingClassifier");
|
|
2023
2076
|
const nSamples = X.shape[0] ?? 0;
|
|
2024
|
-
const
|
|
2025
|
-
|
|
2026
|
-
const
|
|
2077
|
+
const predictions = [];
|
|
2078
|
+
if (this.classLabels.length === 2) {
|
|
2079
|
+
const rawScores = this.predictRawBinary(X, 0);
|
|
2027
2080
|
for (let i = 0; i < nSamples; i++) {
|
|
2028
|
-
|
|
2081
|
+
const prob = 1 / (1 + Math.exp(-(rawScores[i] ?? 0)));
|
|
2082
|
+
predictions.push(prob >= 0.5 ? this.classLabels[1] ?? 0 : this.classLabels[0] ?? 0);
|
|
2083
|
+
}
|
|
2084
|
+
} else {
|
|
2085
|
+
const allScores = [];
|
|
2086
|
+
for (let c = 0; c < this.classLabels.length; c++) {
|
|
2087
|
+
allScores.push(this.predictRawBinary(X, c));
|
|
2088
|
+
}
|
|
2089
|
+
for (let i = 0; i < nSamples; i++) {
|
|
2090
|
+
let bestClass = 0;
|
|
2091
|
+
let bestScore = -Infinity;
|
|
2092
|
+
for (let c = 0; c < this.classLabels.length; c++) {
|
|
2093
|
+
const score = allScores[c]?.[i] ?? 0;
|
|
2094
|
+
if (score > bestScore) {
|
|
2095
|
+
bestScore = score;
|
|
2096
|
+
bestClass = c;
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
predictions.push(this.classLabels[bestClass] ?? 0);
|
|
2029
2100
|
}
|
|
2030
|
-
}
|
|
2031
|
-
const predictions = [];
|
|
2032
|
-
for (let i = 0; i < nSamples; i++) {
|
|
2033
|
-
const prob = 1 / (1 + Math.exp(-(rawScores[i] ?? 0)));
|
|
2034
|
-
const predictedClass = prob >= 0.5 ? this.classLabels[1] : this.classLabels[0];
|
|
2035
|
-
predictions.push(predictedClass ?? 0);
|
|
2036
2101
|
}
|
|
2037
2102
|
return tensor(predictions, { dtype: "int32" });
|
|
2038
2103
|
}
|
|
2039
2104
|
/**
|
|
2040
2105
|
* Predict class probabilities for samples in X.
|
|
2041
2106
|
*
|
|
2042
|
-
* Returns a matrix of shape (n_samples,
|
|
2043
|
-
* [P(class_0), P(class_1)].
|
|
2107
|
+
* Returns a matrix of shape (n_samples, n_classes).
|
|
2044
2108
|
*
|
|
2045
2109
|
* @param X - Samples of shape (n_samples, n_features)
|
|
2046
|
-
* @returns Class probability matrix of shape (n_samples,
|
|
2110
|
+
* @returns Class probability matrix of shape (n_samples, n_classes)
|
|
2047
2111
|
* @throws {NotFittedError} If the model has not been fitted
|
|
2048
2112
|
* @throws {ShapeError} If X has wrong dimensions or feature count
|
|
2049
2113
|
* @throws {DataValidationError} If X contains NaN/Inf values
|
|
@@ -2054,17 +2118,27 @@ var GradientBoostingClassifier = class {
|
|
|
2054
2118
|
}
|
|
2055
2119
|
validatePredictInputs(X, this.nFeatures ?? 0, "GradientBoostingClassifier");
|
|
2056
2120
|
const nSamples = X.shape[0] ?? 0;
|
|
2057
|
-
const
|
|
2058
|
-
|
|
2059
|
-
|
|
2121
|
+
const nClasses = this.classLabels.length;
|
|
2122
|
+
const proba = [];
|
|
2123
|
+
if (nClasses === 2) {
|
|
2124
|
+
const rawScores = this.predictRawBinary(X, 0);
|
|
2060
2125
|
for (let i = 0; i < nSamples; i++) {
|
|
2061
|
-
|
|
2126
|
+
const prob = 1 / (1 + Math.exp(-(rawScores[i] ?? 0)));
|
|
2127
|
+
proba.push([1 - prob, prob]);
|
|
2128
|
+
}
|
|
2129
|
+
} else {
|
|
2130
|
+
const allScores = [];
|
|
2131
|
+
for (let c = 0; c < nClasses; c++) {
|
|
2132
|
+
allScores.push(this.predictRawBinary(X, c));
|
|
2133
|
+
}
|
|
2134
|
+
for (let i = 0; i < nSamples; i++) {
|
|
2135
|
+
const sigScores = [];
|
|
2136
|
+
for (let c = 0; c < nClasses; c++) {
|
|
2137
|
+
sigScores.push(1 / (1 + Math.exp(-(allScores[c]?.[i] ?? 0))));
|
|
2138
|
+
}
|
|
2139
|
+
const total = sigScores.reduce((s, v) => s + v, 0) || 1;
|
|
2140
|
+
proba.push(sigScores.map((v) => v / total));
|
|
2062
2141
|
}
|
|
2063
|
-
}
|
|
2064
|
-
const proba = [];
|
|
2065
|
-
for (let i = 0; i < nSamples; i++) {
|
|
2066
|
-
const prob = 1 / (1 + Math.exp(-(rawScores[i] ?? 0)));
|
|
2067
|
-
proba.push([1 - prob, prob]);
|
|
2068
2142
|
}
|
|
2069
2143
|
return tensor(proba);
|
|
2070
2144
|
}
|
|
@@ -4699,6 +4773,19 @@ var TSNE = class {
|
|
|
4699
4773
|
this.fitTransform(X);
|
|
4700
4774
|
return this;
|
|
4701
4775
|
}
|
|
4776
|
+
/**
|
|
4777
|
+
* Return the fitted embedding. For t-SNE, transform is equivalent to
|
|
4778
|
+
* returning the already-computed embedding (t-SNE is non-parametric).
|
|
4779
|
+
*
|
|
4780
|
+
* @param _X - Ignored, present for API compatibility
|
|
4781
|
+
* @returns Low-dimensional embedding of shape (n_samples, n_components)
|
|
4782
|
+
*/
|
|
4783
|
+
transform(_X) {
|
|
4784
|
+
if (!this.fitted) {
|
|
4785
|
+
throw new NotFittedError("TSNE must be fitted before transform");
|
|
4786
|
+
}
|
|
4787
|
+
return tensor(this.embedding);
|
|
4788
|
+
}
|
|
4702
4789
|
/**
|
|
4703
4790
|
* Get the embedding.
|
|
4704
4791
|
*/
|
|
@@ -5332,13 +5419,13 @@ var LinearSVC = class {
|
|
|
5332
5419
|
maxIter;
|
|
5333
5420
|
/** Tolerance for stopping criterion */
|
|
5334
5421
|
tol;
|
|
5335
|
-
/**
|
|
5336
|
-
|
|
5337
|
-
/**
|
|
5338
|
-
|
|
5422
|
+
/** Per-class weight vectors (OvR for multiclass, single for binary) */
|
|
5423
|
+
weightsPerClass = [];
|
|
5424
|
+
/** Per-class bias terms */
|
|
5425
|
+
biasPerClass = [];
|
|
5339
5426
|
/** Number of features seen during fit */
|
|
5340
5427
|
nFeatures = 0;
|
|
5341
|
-
/** Unique class labels
|
|
5428
|
+
/** Unique class labels */
|
|
5342
5429
|
classLabels = [];
|
|
5343
5430
|
/** Whether the model has been fitted */
|
|
5344
5431
|
fitted = false;
|
|
@@ -5368,19 +5455,69 @@ var LinearSVC = class {
|
|
|
5368
5455
|
throw new InvalidParameterError("tol must be >= 0", "tol", this.tol);
|
|
5369
5456
|
}
|
|
5370
5457
|
}
|
|
5458
|
+
/**
|
|
5459
|
+
* Fit a single binary SVM using sub-gradient descent on hinge loss.
|
|
5460
|
+
* Maps labels to {-1, +1} and returns learned weights + bias.
|
|
5461
|
+
*/
|
|
5462
|
+
fitBinary(XData, yMapped, nSamples, nFeatures) {
|
|
5463
|
+
const weights = new Array(nFeatures).fill(0);
|
|
5464
|
+
let bias = 0;
|
|
5465
|
+
const learningRate = 0.01;
|
|
5466
|
+
for (let iter = 0; iter < this.maxIter; iter++) {
|
|
5467
|
+
let maxViolation = 0;
|
|
5468
|
+
for (let i = 0; i < nSamples; i++) {
|
|
5469
|
+
const xi = XData[i];
|
|
5470
|
+
const yi = yMapped[i];
|
|
5471
|
+
if (xi === void 0 || yi === void 0) continue;
|
|
5472
|
+
let decision = bias;
|
|
5473
|
+
for (let j = 0; j < nFeatures; j++) {
|
|
5474
|
+
decision += (weights[j] ?? 0) * (xi[j] ?? 0);
|
|
5475
|
+
}
|
|
5476
|
+
const margin = yi * decision;
|
|
5477
|
+
if (margin < 1) {
|
|
5478
|
+
maxViolation = Math.max(maxViolation, 1 - margin);
|
|
5479
|
+
}
|
|
5480
|
+
const effectiveLR = Math.min(learningRate, 1 / (this.C * 10));
|
|
5481
|
+
if (margin < 1) {
|
|
5482
|
+
for (let j = 0; j < nFeatures; j++) {
|
|
5483
|
+
weights[j] = (weights[j] ?? 0) * (1 - effectiveLR) + effectiveLR * this.C * yi * (xi[j] ?? 0);
|
|
5484
|
+
}
|
|
5485
|
+
bias += effectiveLR * this.C * yi;
|
|
5486
|
+
} else {
|
|
5487
|
+
for (let j = 0; j < nFeatures; j++) {
|
|
5488
|
+
weights[j] = (weights[j] ?? 0) * (1 - effectiveLR);
|
|
5489
|
+
}
|
|
5490
|
+
}
|
|
5491
|
+
}
|
|
5492
|
+
if (maxViolation < this.tol) break;
|
|
5493
|
+
}
|
|
5494
|
+
return { weights, bias };
|
|
5495
|
+
}
|
|
5496
|
+
/**
|
|
5497
|
+
* Compute decision value for a single binary classifier.
|
|
5498
|
+
*/
|
|
5499
|
+
decisionBinary(x, classIdx) {
|
|
5500
|
+
const w = this.weightsPerClass[classIdx];
|
|
5501
|
+
let d = this.biasPerClass[classIdx] ?? 0;
|
|
5502
|
+
if (w) {
|
|
5503
|
+
for (let j = 0; j < w.length; j++) {
|
|
5504
|
+
d += (w[j] ?? 0) * (x[j] ?? 0);
|
|
5505
|
+
}
|
|
5506
|
+
}
|
|
5507
|
+
return d;
|
|
5508
|
+
}
|
|
5371
5509
|
/**
|
|
5372
5510
|
* Fit the SVM classifier using sub-gradient descent.
|
|
5373
5511
|
*
|
|
5374
|
-
*
|
|
5375
|
-
* Objective: minimize (1/2)||w||² + C * Σmax(0, 1 - y_i(w · x_i + b))
|
|
5512
|
+
* Supports both binary and multiclass classification (via OvR).
|
|
5376
5513
|
*
|
|
5377
5514
|
* @param X - Training data of shape (n_samples, n_features)
|
|
5378
|
-
* @param y - Target labels of shape (n_samples,). Must contain
|
|
5515
|
+
* @param y - Target labels of shape (n_samples,). Must contain at least 2 classes.
|
|
5379
5516
|
* @returns this - The fitted estimator
|
|
5380
5517
|
* @throws {ShapeError} If X is not 2D or y is not 1D
|
|
5381
5518
|
* @throws {ShapeError} If X and y have different number of samples
|
|
5382
5519
|
* @throws {DataValidationError} If X or y contain NaN/Inf values
|
|
5383
|
-
* @throws {InvalidParameterError} If y does not contain
|
|
5520
|
+
* @throws {InvalidParameterError} If y does not contain at least 2 classes
|
|
5384
5521
|
*/
|
|
5385
5522
|
fit(X, y) {
|
|
5386
5523
|
validateFitInputs(X, y);
|
|
@@ -5398,45 +5535,26 @@ var LinearSVC = class {
|
|
|
5398
5535
|
yData.push(Number(y.data[y.offset + i]));
|
|
5399
5536
|
}
|
|
5400
5537
|
this.classLabels = [...new Set(yData)].sort((a, b) => a - b);
|
|
5401
|
-
if (this.classLabels.length
|
|
5538
|
+
if (this.classLabels.length < 2) {
|
|
5402
5539
|
throw new InvalidParameterError(
|
|
5403
|
-
"LinearSVC requires
|
|
5540
|
+
"LinearSVC requires at least 2 classes",
|
|
5404
5541
|
"y",
|
|
5405
5542
|
this.classLabels.length
|
|
5406
5543
|
);
|
|
5407
5544
|
}
|
|
5408
|
-
|
|
5409
|
-
this.
|
|
5410
|
-
this.
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
}
|
|
5422
|
-
const margin = yi * decision;
|
|
5423
|
-
if (margin < 1) {
|
|
5424
|
-
maxViolation = Math.max(maxViolation, 1 - margin);
|
|
5425
|
-
}
|
|
5426
|
-
const effectiveLR = Math.min(learningRate, 1 / (this.C * 10));
|
|
5427
|
-
if (margin < 1) {
|
|
5428
|
-
for (let j = 0; j < nFeatures; j++) {
|
|
5429
|
-
this.weights[j] = (this.weights[j] ?? 0) * (1 - effectiveLR) + effectiveLR * this.C * yi * (xi[j] ?? 0);
|
|
5430
|
-
}
|
|
5431
|
-
this.bias += effectiveLR * this.C * yi;
|
|
5432
|
-
} else {
|
|
5433
|
-
for (let j = 0; j < nFeatures; j++) {
|
|
5434
|
-
this.weights[j] = (this.weights[j] ?? 0) * (1 - effectiveLR);
|
|
5435
|
-
}
|
|
5436
|
-
}
|
|
5437
|
-
}
|
|
5438
|
-
if (maxViolation < this.tol) {
|
|
5439
|
-
break;
|
|
5545
|
+
this.weightsPerClass = [];
|
|
5546
|
+
this.biasPerClass = [];
|
|
5547
|
+
if (this.classLabels.length === 2) {
|
|
5548
|
+
const yMapped = yData.map((label) => label === this.classLabels[0] ? -1 : 1);
|
|
5549
|
+
const { weights, bias } = this.fitBinary(XData, yMapped, nSamples, nFeatures);
|
|
5550
|
+
this.weightsPerClass.push(weights);
|
|
5551
|
+
this.biasPerClass.push(bias);
|
|
5552
|
+
} else {
|
|
5553
|
+
for (const classLabel of this.classLabels) {
|
|
5554
|
+
const yMapped = yData.map((label) => label === classLabel ? 1 : -1);
|
|
5555
|
+
const { weights, bias } = this.fitBinary(XData, yMapped, nSamples, nFeatures);
|
|
5556
|
+
this.weightsPerClass.push(weights);
|
|
5557
|
+
this.biasPerClass.push(bias);
|
|
5440
5558
|
}
|
|
5441
5559
|
}
|
|
5442
5560
|
this.fitted = true;
|
|
@@ -5460,12 +5578,25 @@ var LinearSVC = class {
|
|
|
5460
5578
|
const nFeatures = X.shape[1] ?? 0;
|
|
5461
5579
|
const predictions = [];
|
|
5462
5580
|
for (let i = 0; i < nSamples; i++) {
|
|
5463
|
-
|
|
5581
|
+
const xi = [];
|
|
5464
5582
|
for (let j = 0; j < nFeatures; j++) {
|
|
5465
|
-
|
|
5583
|
+
xi.push(Number(X.data[X.offset + i * nFeatures + j]));
|
|
5584
|
+
}
|
|
5585
|
+
if (this.classLabels.length === 2) {
|
|
5586
|
+
const d = this.decisionBinary(xi, 0);
|
|
5587
|
+
predictions.push(d >= 0 ? this.classLabels[1] ?? 0 : this.classLabels[0] ?? 0);
|
|
5588
|
+
} else {
|
|
5589
|
+
let bestClass = 0;
|
|
5590
|
+
let bestScore = -Infinity;
|
|
5591
|
+
for (let c = 0; c < this.classLabels.length; c++) {
|
|
5592
|
+
const score = this.decisionBinary(xi, c);
|
|
5593
|
+
if (score > bestScore) {
|
|
5594
|
+
bestScore = score;
|
|
5595
|
+
bestClass = c;
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
predictions.push(this.classLabels[bestClass] ?? 0);
|
|
5466
5599
|
}
|
|
5467
|
-
const predictedClass = decision >= 0 ? this.classLabels[1] : this.classLabels[0];
|
|
5468
|
-
predictions.push(predictedClass ?? 0);
|
|
5469
5600
|
}
|
|
5470
5601
|
return tensor(predictions, { dtype: "int32" });
|
|
5471
5602
|
}
|
|
@@ -5485,14 +5616,25 @@ var LinearSVC = class {
|
|
|
5485
5616
|
validatePredictInputs(X, this.nFeatures ?? 0, "LinearSVC");
|
|
5486
5617
|
const nSamples = X.shape[0] ?? 0;
|
|
5487
5618
|
const nFeatures = X.shape[1] ?? 0;
|
|
5619
|
+
const nClasses = this.classLabels.length;
|
|
5488
5620
|
const proba = [];
|
|
5489
5621
|
for (let i = 0; i < nSamples; i++) {
|
|
5490
|
-
|
|
5622
|
+
const xi = [];
|
|
5491
5623
|
for (let j = 0; j < nFeatures; j++) {
|
|
5492
|
-
|
|
5624
|
+
xi.push(Number(X.data[X.offset + i * nFeatures + j]));
|
|
5625
|
+
}
|
|
5626
|
+
if (nClasses === 2) {
|
|
5627
|
+
const d = this.decisionBinary(xi, 0);
|
|
5628
|
+
const p1 = 1 / (1 + Math.exp(-d));
|
|
5629
|
+
proba.push([1 - p1, p1]);
|
|
5630
|
+
} else {
|
|
5631
|
+
const sigScores = [];
|
|
5632
|
+
for (let c = 0; c < nClasses; c++) {
|
|
5633
|
+
sigScores.push(1 / (1 + Math.exp(-this.decisionBinary(xi, c))));
|
|
5634
|
+
}
|
|
5635
|
+
const total = sigScores.reduce((s, v) => s + v, 0) || 1;
|
|
5636
|
+
proba.push(sigScores.map((v) => v / total));
|
|
5493
5637
|
}
|
|
5494
|
-
const p1 = 1 / (1 + Math.exp(-decision));
|
|
5495
|
-
proba.push([1 - p1, p1]);
|
|
5496
5638
|
}
|
|
5497
5639
|
return tensor(proba);
|
|
5498
5640
|
}
|
|
@@ -5541,19 +5683,19 @@ var LinearSVC = class {
|
|
|
5541
5683
|
if (!this.fitted) {
|
|
5542
5684
|
throw new NotFittedError("LinearSVC must be fitted to access coefficients");
|
|
5543
5685
|
}
|
|
5544
|
-
return tensor(
|
|
5686
|
+
return tensor(this.weightsPerClass);
|
|
5545
5687
|
}
|
|
5546
5688
|
/**
|
|
5547
|
-
* Get the bias
|
|
5689
|
+
* Get the bias terms.
|
|
5548
5690
|
*
|
|
5549
|
-
* @returns Bias
|
|
5691
|
+
* @returns Bias values as tensor
|
|
5550
5692
|
* @throws {NotFittedError} If the model has not been fitted
|
|
5551
5693
|
*/
|
|
5552
5694
|
get intercept() {
|
|
5553
5695
|
if (!this.fitted) {
|
|
5554
5696
|
throw new NotFittedError("LinearSVC must be fitted to access intercept");
|
|
5555
5697
|
}
|
|
5556
|
-
return this.
|
|
5698
|
+
return tensor(this.biasPerClass);
|
|
5557
5699
|
}
|
|
5558
5700
|
/**
|
|
5559
5701
|
* Get hyperparameters for this estimator.
|
|
@@ -6375,5 +6517,5 @@ var RandomForestRegressor = class {
|
|
|
6375
6517
|
};
|
|
6376
6518
|
|
|
6377
6519
|
export { DBSCAN, DecisionTreeClassifier, DecisionTreeRegressor, GaussianNB, GradientBoostingClassifier, GradientBoostingRegressor, KMeans, KNeighborsClassifier, KNeighborsRegressor, Lasso, LinearRegression, LinearSVC, LinearSVR, LogisticRegression, PCA, RandomForestClassifier, RandomForestRegressor, Ridge, TSNE, ml_exports };
|
|
6378
|
-
//# sourceMappingURL=chunk-
|
|
6379
|
-
//# sourceMappingURL=chunk-
|
|
6520
|
+
//# sourceMappingURL=chunk-H3JR7SV2.js.map
|
|
6521
|
+
//# sourceMappingURL=chunk-H3JR7SV2.js.map
|