Skip to content

deepbox

Release Notes

What changed in Deepbox 1.5.0, released 2026-10-03.

  • v1.5.0
  • 2026-10-03

A quality release. Every source file was reviewed line by line, and the results were checked against NumPy, SciPy, scikit-learn, PyTorch and pandas. About 1,500 issues were fixed, many of them wrong results in 1.0.0. The release also makes the API more consistent: tensors share one method surface, training works on plain tensors, mixed dtypes promote instead of throwing, and every export has a camelCase name.

No export, option or method was removed or renamed. Some results change because they were wrong before, some dtypes change because of the new dtype rules, and one type changed (forward(Tensor) on layers); all of this is listed under "Upgrading from 1.0".

Upgrading from 1.0

The migration notes have their own page: Upgrading from 1.0.

Added

  • Tensor methods. Tensor and GradTensor share one method surface, so code reads the same with or without gradient tracking: t.add(1).mul(2).sum(), t.T, t.matmul(w), t.softmax(-1), t.argmax(1), comparisons, rounding, sort, flip, squeeze, unsqueeze, gather, item() and more. Plain tensors also have requiresGrad (false), grad (null) and a backward() that explains why it cannot run.
  • ndarray: argmax, argmin, nonzero, argwhere, countNonzero, takeAlongAxis, putAlongAxis, nanvar, nanmedian, nanprod, nanargmin, nanargmax, nancumsum, nanquantile; unique options (returnIndex, returnInverse, returnCounts, axis); batched cross; dot and matmul broadcast batch dimensions like numpy.matmul; activations relu6, selu, celu, softsign, hardsigmoid, hardswish, logSigmoid, hardshrink, softshrink; exact GELU through gelu(t, { approximate: "none" }). New differentiable GradTensor methods (sin, cos, tan, log1p, expm1, maximum, minimum, cumsum, prod, std, var, softplus, mish, swish, selu, clone) and multi-axis reductions.
  • core: promoteTypes.
  • nn: MultiheadAttention options needWeights and keyPaddingMask; Transformer layers activation ("relu" or "gelu") and normFirst; convolution dilation, groups and padding: "same" | "valid"; pooling ceilMode; layers ReLU6, LogSigmoid, CELU, Softshrink, Hardshrink and Threshold; Trainer options accumulationSteps and restoreBestWeights; tripletMarginLoss supports autograd and a swap option; loss functions accept the output of Module.forward directly.
  • metrics: multiclass rocAucScore (multiClass: "ovr" | "ovo"), logLoss, jaccardScore and matthewsCorrcoef; an options object { average, labels, zeroDivision, sampleWeight } for precision, recall, f1Score, fbetaScore and jaccardScore; sampleWeight for the common classification and regression metrics; meanAbsolutePercentageError (scikit-learn semantics, a fraction).
  • dataframe: fillna with per-column values and method: "ffill" | "bfill", plus ffill() and bfill(); corr with method ("pearson", "spearman", "kendall") and minPeriods; sample with frac, replace and weights; groupBy with getGroup, nunique, quantile, transform and named aggregation; rolling with minPeriods and center; concat with join and ignoreIndex; valueCounts with normalize and dropna.
  • ml: trees and forests accept sampleWeight, classWeight, minImpurityDecrease, maxLeafNodes and ccpAlpha; every estimator has clone(); Ridge with alpha: 0 on rank-deficient input returns the minimum-norm solution, as scikit-learn does.
  • stats: an alternative option on pearsonr, spearmanr, kendalltau and pointbiserialr; kendalltau variant and method; wilcoxon zeroMethod; benjaminiYekutieli and hochberg.
  • datasets: fetch20Newsgroups and fetchIMDB load the official archives by default (the 1.0.0 default URLs returned 404).
  • Names. Every snake_case export now has a camelCase name, for example matrixPower, blockDiag, solveBanded, toDatetime, dateRange, crossValScore, crossValidate, exportText, multivariateNormal, studentT, gaussianKde, ttest1samp, checkXY and checkArray. The same holds for methods (DataFrame.dropDuplicates, resetIndex, setIndex, pctChange, valueCounts, memoryUsage and pivotTable; the dt accessor's isLeapYear, dayName, dayOfWeek and friends; str.getDummies; style.highlightMax, highlightMin, highlightNull and backgroundGradient) and for options (leftOn and rightOn in DataFrame.merge, bwMethod in kdeplot). When both spellings of an option are given, the camelCase one wins.
  • Tooling: typecheck:docs type-checks every example and project against the source, and prose:check keeps em dashes out of the repository. Both run in validate:all.

Deprecated

  • The snake_case names that now have camelCase equivalents, and the lowercase dt names dayofweek, dayofyear, weekofyear and daysinmonth. They keep working and are marked @deprecated in the type declarations.

Fixed

The list below names the most significant fixes. Every module received many smaller ones (edge cases, validation, error messages, strided views, int64 input, documentation).

  • nn: Trainer passed plain tensors to the model, so layers returned untracked results, no gradients reached the optimizer, and real models never trained. MultiheadAttention and the Transformer layers threw for float64 or float16 input. EarlyStopping kept state between fit calls. Init functions wrote to the wrong elements of non-contiguous tensors.
  • ml: OneClassSVM flagged most training rows as outliers (88 percent with nu = 0.1; scikit-learn: 10 percent). SVC predictions, PCA projections, HuberRegressor, LocalOutlierFactor scores, IsolationForest thresholds, CalibratedClassifierCV (Platt and isotonic), and random forest bootstrapping and maxFeatures (which was ignored) now match scikit-learn. Estimators accept int64 input. Trees and forests return float64 results.
  • ndarray: cumsum and cumprod without an axis returned the wrong shape; median rejected multiple axes; leaf gradients could share one buffer, so gradient clipping scaled it several times; max and min backward failed for float32; floorDiv and mod disagreed with NumPy for large or fractional values; int32 multiplication lost low bits; corrcoef, cov and tensordot returned silent garbage on bad input.
  • linalg: non-symmetric eig (now a real Francis double-shift QR), Hessenberg and QR on matrices with tiny entries, the symmetry test used by eig, and float64 results for trace, matrixPower, expm, logm and sqrtm.
  • stats: special functions are accurate to about 1e-14 (the old erf was accurate to about 1e-7); p-value tails no longer underflow; binomial, Poisson and related pmfs use the saddle-point method; kstest, ks_2samp, anderson, mannwhitneyu and wilcoxon match SciPy 1.17, including exact small-sample p-values; Welch degrees of freedom are no longer rounded down.
  • metrics: metrics read strided and transposed tensors correctly, reject NaN labels, and match scikit-learn for hingeLoss, coverageError, adjustedMutualInfoScore and fbetaScore on multiclass input.
  • preprocess: TargetEncoder leaked the target across folds; RFE and RFECV ranked eliminated features in reverse and did not work with the library's own tree models; KBinsDiscretizer put values on bin edges in the wrong bin; the seeded generator cycled after about 16,000 values.
  • dataframe: tail(n) with n larger than the frame, fromTensor on views, sorting with infinities, query operator precedence, eval parsing, cumulative operations with NaN, round (now half-to-even), ewm with missing rows, str.match (now anchored like pandas) and nearest interpolation.
  • optim: state dicts were live references, loaded non-atomically and could pair state with the wrong parameter; tied weights were updated twice per step; strided parameters were updated in the wrong elements; LBFGS ignored lineSearchFn: "strong_wolfe"; centered RMSprop and RAdam now match PyTorch exactly.
  • random: shuffling a view changed elements outside it; categorical without replacement could loop forever; dirichlet with small concentrations returned uniform rows; multivariateNormal accepted invalid covariances.
  • datasets: one value in the bundled data tables was wrong (all five now equal scikit-learn's); makeFriedman2, makeFriedman3, makeSparseUncorrelated and makeLowRankMatrix follow scikit-learn's definitions; parseCSV read empty cells as 0; DataLoader.length ignored the sampler; dataset ids are validated before they reach a URL.
  • plot: PNG output now draws grids and text and blends translucent colors; fill_between, area, stackedBar and groupedBar draw correctly; twinx shares the x axis; log-scale ranges; animated SVG timelines; tick labels (2.5 was drawn as "3").
  • core: toJSON turned NaN, Infinity and -0 into other values; setConfig reseeded the global generator on every call; WorkerPool.reduce applied the initial value once per chunk, and an invalid maxWorkers could hang the process. On WebGPU, NaN handling, tanh and gelu for large inputs, average-pool backward, and launches above 16.7 million elements (which returned zeros) are fixed.

Performance

Hot paths in reductions, sorting, trees, metrics, DataFrame operations and autograd were reworked where results stay identical, for example an O(n log n) Kendall tau and a three-way quickselect that no longer degrades to quadratic time on constant input. binomial uses BTPE (as NumPy does) for means of 30 and above: a draw with n = 1e12 went from about 2.5 ms to a few microseconds, with exact results.

Verification

Beyond the unit tests (13,000+), every module was checked against its reference library with randomized differential tests: reductions against NumPy, estimators and metrics against scikit-learn, layers, gradients and optimizers against PyTorch, DataFrame operations against pandas, and statistics against SciPy. The unchanged 1.0.0 test suite was also run against this release, and every difference is one of the changes listed above.

Documentation

README, SKILL.md, all examples and projects were updated to the 1.5.0 API and rewritten in plainer language. Defaults that differ from NumPy, pandas, scikit-learn and PyTorch are documented where they apply.