tensorstudio 1.3.3__tar.gz → 1.3.4__tar.gz

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.
Files changed (152) hide show
  1. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/CHANGELOG.md +12 -0
  2. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/PKG-INFO +4 -4
  3. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/README.md +3 -3
  4. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Autograde/index.md +1 -1
  5. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Benchmarks/index.md +1 -1
  6. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Hardware/cpu-backend.md +1 -1
  7. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Neural Networks/training.md +1 -1
  8. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Roadmap/index.md +17 -2
  9. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/api.md +7 -0
  10. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/interchange.md +1 -1
  11. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/serialization.md +1 -1
  12. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/tensors.md +3 -2
  13. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/index.md +4 -4
  14. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/publishing.md +4 -4
  15. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/quickstart.md +2 -1
  16. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/version.hpp +1 -1
  17. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/pyproject.toml +1 -1
  18. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/_C.pyi +10 -8
  19. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/_version.py +1 -1
  20. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/math.py +40 -15
  21. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/ops.py +5 -4
  22. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bind_ops.cpp +22 -16
  23. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bind_tensor.cpp +83 -16
  24. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bindings.hpp +10 -0
  25. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_autograd.py +25 -0
  26. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_import.py +1 -1
  27. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_ops.py +53 -0
  28. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/.github/workflows/ci.yml +0 -0
  29. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/.github/workflows/publish-testpypi.yml +0 -0
  30. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/.github/workflows/publish.yml +0 -0
  31. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/.github/workflows/wheels.yml +0 -0
  32. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/.gitignore +0 -0
  33. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/.pre-commit-config.yaml +0 -0
  34. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/CMakeLists.txt +0 -0
  35. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/CONTRIBUTING.md +0 -0
  36. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/LICENSE +0 -0
  37. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/SECURITY.md +0 -0
  38. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmark_all.py +0 -0
  39. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/__init__.py +0 -0
  40. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_activations.py +0 -0
  41. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_autograd.py +0 -0
  42. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_conv2d.py +0 -0
  43. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_elementwise.py +0 -0
  44. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_matmul.py +0 -0
  45. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_pooling.py +0 -0
  46. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_reductions.py +0 -0
  47. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_tensor_ops.py +0 -0
  48. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/bench_training_loop.py +0 -0
  49. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/benchmark_report.py +0 -0
  50. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/results.md +0 -0
  51. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/results_conv2d.md +0 -0
  52. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/results_matmul.md +0 -0
  53. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/results_pooling.md +0 -0
  54. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/results_reductions.md +0 -0
  55. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/benchmarks/results_tensor_ops.md +0 -0
  56. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Autograde/autograd.md +0 -0
  57. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Hardware/linux.md +0 -0
  58. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Hardware/macos.md +0 -0
  59. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Hardware/windows.md +0 -0
  60. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Neural Networks/modules.md +0 -0
  61. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Neural Networks/nn.md +0 -0
  62. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Projects/index.md +0 -0
  63. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/data.md +0 -0
  64. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/numpy-interop.md +0 -0
  65. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Usage/optim.md +0 -0
  66. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/Vision/index.md +0 -0
  67. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/development.md +0 -0
  68. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/docs/serialization.md +0 -0
  69. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/basic_tensor_ops.py +0 -0
  70. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/export_onnx.py +0 -0
  71. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/image_folder_classification.py +0 -0
  72. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/linear_regression.py +0 -0
  73. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/project_training.py +0 -0
  74. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/save_load_model.py +0 -0
  75. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/tiny_mlp.py +0 -0
  76. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/examples/vision_classifier.py +0 -0
  77. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/autograd.hpp +0 -0
  78. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/device.hpp +0 -0
  79. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/dtype.hpp +0 -0
  80. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/errors.hpp +0 -0
  81. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/module.hpp +0 -0
  82. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/ops.hpp +0 -0
  83. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/optim.hpp +0 -0
  84. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/random.hpp +0 -0
  85. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/serialization.hpp +0 -0
  86. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/shape.hpp +0 -0
  87. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/storage.hpp +0 -0
  88. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/include/tensorstudio/tensor.hpp +0 -0
  89. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/mkdocs.yml +0 -0
  90. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/__init__.py +0 -0
  91. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/autograd.py +0 -0
  92. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/data/__init__.py +0 -0
  93. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/data/dataloader.py +0 -0
  94. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/data/dataset.py +0 -0
  95. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/dtypes.py +0 -0
  96. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/errors.py +0 -0
  97. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/grad_mode.py +0 -0
  98. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/interchange/__init__.py +0 -0
  99. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/interchange/onnx.py +0 -0
  100. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/nn/__init__.py +0 -0
  101. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/nn/functional.py +0 -0
  102. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/nn/losses.py +0 -0
  103. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/nn/modules.py +0 -0
  104. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/optim/__init__.py +0 -0
  105. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/optim/adam.py +0 -0
  106. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/optim/adamw.py +0 -0
  107. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/optim/lr_scheduler.py +0 -0
  108. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/optim/sgd.py +0 -0
  109. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/optim/utils.py +0 -0
  110. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/project/__init__.py +0 -0
  111. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/project/checkpoint.py +0 -0
  112. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/project/config.py +0 -0
  113. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/project/trainer.py +0 -0
  114. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/py.typed +0 -0
  115. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/serialization.py +0 -0
  116. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/tensor.py +0 -0
  117. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/typing.py +0 -0
  118. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/__init__.py +0 -0
  119. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/datasets.py +0 -0
  120. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/io.py +0 -0
  121. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/metrics.py +0 -0
  122. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/models.py +0 -0
  123. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/transforms.py +0 -0
  124. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/python/tensorstudio/vision/visualization.py +0 -0
  125. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bind_autograd.cpp +0 -0
  126. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bind_nn.cpp +0 -0
  127. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bind_optim.cpp +0 -0
  128. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/bindings/bindings.cpp +0 -0
  129. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/autograd.cpp +0 -0
  130. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/device.cpp +0 -0
  131. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/dtype.cpp +0 -0
  132. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/errors.cpp +0 -0
  133. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/module.cpp +0 -0
  134. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/ops.cpp +0 -0
  135. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/optim.cpp +0 -0
  136. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/random.cpp +0 -0
  137. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/serialization.cpp +0 -0
  138. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/shape.cpp +0 -0
  139. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/storage.cpp +0 -0
  140. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/src/core/tensor.cpp +0 -0
  141. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/test_all.py +0 -0
  142. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_benchmark_report.py +0 -0
  143. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_broadcasting.py +0 -0
  144. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_data.py +0 -0
  145. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_interchange.py +0 -0
  146. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_nn.py +0 -0
  147. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_numpy_interop.py +0 -0
  148. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_optim.py +0 -0
  149. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_project.py +0 -0
  150. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_serialization.py +0 -0
  151. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_tensor.py +0 -0
  152. {tensorstudio-1.3.3 → tensorstudio-1.3.4}/tests/test_vision.py +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 1.3.4 - 2026-07-07
6
+
7
+ - Completed the next ordered correctness-roadmap item with tuple/list-axis
8
+ reductions for `sum`, `mean`, `max`, and `min`.
9
+ - Added C++ binding-layer axis normalization for reduction methods and
10
+ functional ops, including negative-axis handling, duplicate-axis errors, and
11
+ `axis=()` no-op behavior.
12
+ - Added NumPy parity tests and autograd coverage for tuple-axis reductions.
13
+ - Added ordered roadmap entries for supported ONNX/model metadata extraction,
14
+ supported ONNX import/execution, safe model-format research, and image/tensor
15
+ dataset creation helpers.
16
+
5
17
  ## 1.3.3 - 2026-07-07
6
18
 
7
19
  - Hardened CI type checks for newer Python/mypy combinations by annotating
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tensorstudio
3
- Version: 1.3.3
3
+ Version: 1.3.4
4
4
  Summary: TensorStudio is a compact C++ tensor and autograd engine with a Python API for learning, experimentation, and lightweight ML workloads.
5
5
  Keywords: tensor,autograd,machine-learning,cpp,pybind11
6
6
  Author: TensorStudio contributors
@@ -71,7 +71,7 @@ Description-Content-Type: text/markdown
71
71
  TensorStudio is a compact C++ tensor and autograd engine with a Python API for
72
72
  learning, experimentation, and lightweight ML workloads.
73
73
 
74
- TensorStudio `1.3.3` is a CPU-only stable API foundation. It is eager-only,
74
+ TensorStudio `1.3.4` is a CPU-only stable API foundation. It is eager-only,
75
75
  intentionally small, and not a replacement for mature ML frameworks.
76
76
 
77
77
  ## Install
@@ -472,8 +472,8 @@ tokens or print secrets.
472
472
  pretrained model zoos, detection/segmentation training stacks, video IO, or
473
473
  GPU image kernels yet.
474
474
  - ONNX support is export-only for a limited set of TensorStudio modules.
475
- - Reductions support all-element or single-axis reductions, not tuple-axis
476
- reductions yet.
475
+ - Reductions support all-element, single-axis, and tuple/list-axis reductions
476
+ for `sum`, `mean`, `max`, and `min`.
477
477
  - No sparse tensors or advanced indexing.
478
478
  - Dtype casting is basic and does not include a full promotion/casting policy.
479
479
  - Experimental performance; benchmarks are local references only.
@@ -7,7 +7,7 @@
7
7
  TensorStudio is a compact C++ tensor and autograd engine with a Python API for
8
8
  learning, experimentation, and lightweight ML workloads.
9
9
 
10
- TensorStudio `1.3.3` is a CPU-only stable API foundation. It is eager-only,
10
+ TensorStudio `1.3.4` is a CPU-only stable API foundation. It is eager-only,
11
11
  intentionally small, and not a replacement for mature ML frameworks.
12
12
 
13
13
  ## Install
@@ -408,8 +408,8 @@ tokens or print secrets.
408
408
  pretrained model zoos, detection/segmentation training stacks, video IO, or
409
409
  GPU image kernels yet.
410
410
  - ONNX support is export-only for a limited set of TensorStudio modules.
411
- - Reductions support all-element or single-axis reductions, not tuple-axis
412
- reductions yet.
411
+ - Reductions support all-element, single-axis, and tuple/list-axis reductions
412
+ for `sum`, `mean`, `max`, and `min`.
413
413
  - No sparse tensors or advanced indexing.
414
414
  - Dtype casting is basic and does not include a full promotion/casting policy.
415
415
  - Experimental performance; benchmarks are local references only.
@@ -40,7 +40,7 @@ Calling `backward()`:
40
40
 
41
41
  ## Supported Gradient Operations
42
42
 
43
- `1.3.3` supports gradients for:
43
+ `1.3.4` supports gradients for:
44
44
 
45
45
  - `add`
46
46
  - `sub`
@@ -55,7 +55,7 @@ equivalents where available.
55
55
  ## Interpreting Results
56
56
 
57
57
  Expect NumPy and PyTorch to be faster for many medium and large operations
58
- because they use highly optimized native kernels. TensorStudio `1.3.3` still
58
+ because they use highly optimized native kernels. TensorStudio `1.3.4` still
59
59
  favors clarity, portability, and a compact C++ implementation over full kernel
60
60
  library performance.
61
61
 
@@ -1,6 +1,6 @@
1
1
  # CPU Backend
2
2
 
3
- TensorStudio `1.3.3` supports CPU tensors only.
3
+ TensorStudio `1.3.4` supports CPU tensors only.
4
4
 
5
5
  ## Device Abstraction
6
6
 
@@ -80,7 +80,7 @@ w = ts.randn((4, 4), seed=123)
80
80
 
81
81
  ## Practical Tips
82
82
 
83
- - Keep tensors modest in `1.3.3`; kernels are simple CPU loops.
83
+ - Keep tensors modest in `1.3.4`; kernels are simple CPU loops.
84
84
  - Prefer `float32` unless you need `float64`.
85
85
  - Compare with NumPy in tests for expected numerical values.
86
86
  - Watch shape errors carefully around broadcasting and matrix multiplication.
@@ -1,6 +1,6 @@
1
1
  # Roadmap
2
2
 
3
- TensorStudio `1.3.3` is a CPU-first tensor, autograd, neural-network, vision,
3
+ TensorStudio `1.3.4` is a CPU-first tensor, autograd, neural-network, vision,
4
4
  project, serialization, and ONNX-export foundation. The long-term direction is
5
5
  to become a strong compact ML framework for learning, experimentation, and
6
6
  lightweight workloads while staying honest about the scale of mature systems
@@ -21,7 +21,8 @@ tensor semantics.
21
21
  - Completed in `1.3.2`: add exhaustive broadcasting tests for every binary
22
22
  elementwise arithmetic and comparison operation, including functional and
23
23
  operator overload paths.
24
- - Add tuple-axis reductions for `sum`, `mean`, `max`, and `min`.
24
+ - Completed in `1.3.4`: add tuple-axis reductions for `sum`, `mean`,
25
+ `max`, and `min`.
25
26
  - Add arg reductions: `argmax` and `argmin`.
26
27
  - Add `where`, `maximum`, `minimum`, `clip`, and richer comparison helpers.
27
28
  - Add full NumPy-style indexing and slicing for common cases.
@@ -95,6 +96,9 @@ families.
95
96
  The project utilities should evolve into a clean small-project workflow without
96
97
  becoming an opaque training framework.
97
98
 
99
+ - Add dataset creation helpers for images, tabular arrays, labels, and
100
+ TensorStudio tensors, with deterministic train/validation splitting and
101
+ metadata summaries.
98
102
  - Add callbacks for checkpointing, early stopping, CSV logging, and learning
99
103
  rate logging.
100
104
  - Add a metrics package for regression, classification, and multilabel tasks.
@@ -131,7 +135,18 @@ compatibility.
131
135
  - Expand NPZ metadata for richer model and optimizer state.
132
136
  - Add `safetensors` support for safe tensor weight storage.
133
137
  - Expand ONNX export coverage for more TensorStudio modules and ops.
138
+ - Add ONNX metadata inspection for supported files, including graph inputs,
139
+ outputs, opset, initializer summaries, node counts, and model producer
140
+ fields.
134
141
  - Add ONNX import for a supported subset of static graphs.
142
+ - Add execution support for imported ONNX graphs only where TensorStudio has
143
+ correct matching tensor ops; clearly reject unsupported operators and dynamic
144
+ graph features.
145
+ - Add model metadata extraction for TensorStudio checkpoints, NPZ bundles, and
146
+ supported ONNX files. Do not advertise metadata support for formats that
147
+ cannot be parsed safely or accurately.
148
+ - Add import/export research for practical neural-network model formats that
149
+ can be supported without unsafe execution or fake compatibility layers.
135
150
  - Add versioned checkpoint metadata and compatibility checks.
136
151
  - Add model card or metadata export for packaged examples.
137
152
  - Consider DLPack-style interop after tensor/device semantics are mature.
@@ -146,6 +146,10 @@ Math:
146
146
  - `mean(axis=None, keepdims=False)`
147
147
  - `max(axis=None, keepdims=False)`
148
148
  - `min(axis=None, keepdims=False)`
149
+
150
+ For reductions, `axis` may be `None`, an int, or a tuple/list of ints.
151
+ Negative axes are normalized against the input rank, duplicate axes are
152
+ rejected, and `axis=()` is a no-op identity.
149
153
  - `relu()`
150
154
  - `sigmoid()`
151
155
  - `tanh()`
@@ -295,6 +299,9 @@ Optimizers implement `zero_grad`, `step`, `state_dict`, and `load_state_dict`.
295
299
  - `std(input, axis=None, keepdims=False, correction=0)`
296
300
  - `norm(input, ord=2, axis=None, keepdims=False)`
297
301
 
302
+ These helpers accept the same reduction axis forms as native reductions:
303
+ `None`, an int, or a tuple/list of ints.
304
+
298
305
  These helpers compose TensorStudio tensors and keep autograd support.
299
306
 
300
307
  ## `tensorstudio.project`
@@ -1,6 +1,6 @@
1
1
  # ONNX Interchange
2
2
 
3
- TensorStudio `1.3.3` includes a limited ONNX exporter for supported
3
+ TensorStudio `1.3.4` includes a limited ONNX exporter for supported
4
4
  TensorStudio module stacks.
5
5
 
6
6
  Install the optional dependency:
@@ -1,6 +1,6 @@
1
1
  # Serialization
2
2
 
3
- TensorStudio `1.3.3` provides two serialization paths: trusted pickle
3
+ TensorStudio `1.3.4` provides two serialization paths: trusted pickle
4
4
  roundtrips for internal objects and non-pickle NPZ files for tensor/state_dict
5
5
  interchange.
6
6
 
@@ -185,14 +185,15 @@ Matrix and reductions:
185
185
  - `max`
186
186
  - `min`
187
187
 
188
- Reductions operate over all elements by default and support one axis at a time
189
- with `keepdims`:
188
+ Reductions operate over all elements by default and support an int axis or a
189
+ tuple/list of axes with `keepdims`:
190
190
 
191
191
  ```python
192
192
  x = ts.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
193
193
  x.sum(axis=1)
194
194
  x.mean(axis=0, keepdims=True)
195
195
  x.max(axis=-1)
196
+ x.reshape((1, 2, 3)).sum(axis=(0, 2))
196
197
  ```
197
198
 
198
199
  Higher-level helpers in `tensorstudio.math` include variance, standard
@@ -3,7 +3,7 @@
3
3
  TensorStudio is a compact C++ tensor and autograd engine with a Python API for
4
4
  learning, experimentation, and lightweight ML workloads.
5
5
 
6
- `1.3.3` is a CPU-only stable API foundation for the tensor, autograd,
6
+ `1.3.4` is a CPU-only stable API foundation for the tensor, autograd,
7
7
  neural-network, optimizer, data, project, serialization, ONNX export, vision,
8
8
  docs, packaging, and wheel workflows.
9
9
 
@@ -26,8 +26,8 @@ TensorStudio is:
26
26
  `empty`, `rand`, `randn`, `arange`, `eye`, `linspace`, and matching
27
27
  `*_like` helpers.
28
28
  - NumPy-style broadcasting for binary elementwise operations.
29
- - Arithmetic, comparisons, matrix multiplication, all-element and single-axis
30
- reductions, common activations, trigonometric functions, inverse
29
+ - Arithmetic, comparisons, matrix multiplication, all-element, single-axis, and
30
+ tuple-axis reductions, common activations, trigonometric functions, inverse
31
31
  trigonometric functions, `log1p`, `sqrt`, `rsqrt`, `abs`, `clamp`, CPU NCHW
32
32
  `conv2d`, `max_pool2d`, `avg_pool2d`, reshape, flatten, and 2D transpose.
33
33
  - Higher-level `tensorstudio.math` helpers for variance, standard deviation,
@@ -61,7 +61,7 @@ TensorStudio prioritizes:
61
61
 
62
62
  TensorStudio does not currently include CUDA, Metal, distributed execution,
63
63
  graph compilation, grouped convolution, adaptive/global pooling, advanced
64
- indexing, sparse tensors, mixed precision, tuple-axis reductions, a high
64
+ indexing, sparse tensors, mixed precision, a high
65
65
  performance kernel library, pretrained vision model zoo, detection/segmentation
66
66
  training stack, video IO, an ONNX runtime, or ONNX import. Benchmarks are rough
67
67
  local references only; TensorStudio wins some small eager CPU cases but is not
@@ -22,8 +22,8 @@ Windows, Linux, and macOS.
22
22
  After the release checklist passes, tag the stable release:
23
23
 
24
24
  ```bash
25
- git tag v1.3.3
26
- git push origin v1.3.3
25
+ git tag v1.3.4
26
+ git push origin v1.3.4
27
27
  ```
28
28
 
29
29
  Stable release notes must avoid unsupported performance claims. Publish measured
@@ -63,7 +63,7 @@ clean environment:
63
63
  python -m venv .venv-testpypi
64
64
  . .venv-testpypi/bin/activate
65
65
  python -m pip install -U pip
66
- python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ tensorstudio==1.3.3
66
+ python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ tensorstudio==1.3.4
67
67
  python -c "import tensorstudio as ts; import tensorstudio._C; print(ts.__version__)"
68
68
  deactivate
69
69
  ```
@@ -74,7 +74,7 @@ On Windows PowerShell:
74
74
  python -m venv .venv-testpypi
75
75
  .\.venv-testpypi\Scripts\Activate.ps1
76
76
  python -m pip install -U pip
77
- python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ tensorstudio==1.3.3
77
+ python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ tensorstudio==1.3.4
78
78
  python -c "import tensorstudio as ts; import tensorstudio._C; print(ts.__version__)"
79
79
  deactivate
80
80
  ```
@@ -109,13 +109,14 @@ print(ts.sin(x).tolist())
109
109
  print(ts.math.std(x).item())
110
110
  ```
111
111
 
112
- Reductions can operate over all elements or one axis:
112
+ Reductions can operate over all elements, one axis, or a tuple/list of axes:
113
113
 
114
114
  ```python
115
115
  x = ts.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
116
116
  print(x.sum().item())
117
117
  print(x.mean(axis=0).tolist())
118
118
  print(x.max(axis=1, keepdims=True).tolist())
119
+ print(ts.arange(24).reshape((2, 3, 4)).sum(axis=(0, 2)).tolist())
119
120
  ```
120
121
 
121
122
  Tensors can be cast, concatenated, and stacked:
@@ -2,6 +2,6 @@
2
2
 
3
3
  namespace tensorstudio {
4
4
 
5
- inline constexpr const char* version = "1.3.3";
5
+ inline constexpr const char* version = "1.3.4";
6
6
 
7
7
  } // namespace tensorstudio
@@ -7,7 +7,7 @@ build-backend = "scikit_build_core.build"
7
7
 
8
8
  [project]
9
9
  name = "tensorstudio"
10
- version = "1.3.3"
10
+ version = "1.3.4"
11
11
  description = "TensorStudio is a compact C++ tensor and autograd engine with a Python API for learning, experimentation, and lightweight ML workloads."
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.10"
@@ -4,6 +4,8 @@ from typing import Any
4
4
 
5
5
  import numpy as np
6
6
 
7
+ AxisLike = int | tuple[int, ...] | list[int] | None
8
+
7
9
  class Tensor:
8
10
  requires_grad: bool
9
11
  grad: Tensor | None
@@ -23,10 +25,10 @@ class Tensor:
23
25
  def reshape(self, *shape: Any) -> Tensor: ...
24
26
  def flatten(self) -> Tensor: ...
25
27
  def transpose(self) -> Tensor: ...
26
- def sum(self, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
27
- def mean(self, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
28
- def max(self, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
29
- def min(self, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
28
+ def sum(self, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
29
+ def mean(self, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
30
+ def max(self, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
31
+ def min(self, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
30
32
  def relu(self) -> Tensor: ...
31
33
  def sigmoid(self) -> Tensor: ...
32
34
  def tanh(self) -> Tensor: ...
@@ -140,10 +142,10 @@ def avg_pool2d(
140
142
  padding_w: int = 0,
141
143
  count_include_pad: bool = False,
142
144
  ) -> Tensor: ...
143
- def sum(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
144
- def mean(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
145
- def max(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
146
- def min(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: ...
145
+ def sum(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
146
+ def mean(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
147
+ def max(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
148
+ def min(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: ...
147
149
  def relu(input: Tensor) -> Tensor: ...
148
150
  def sigmoid(input: Tensor) -> Tensor: ...
149
151
  def tanh(input: Tensor) -> Tensor: ...
@@ -1,5 +1,5 @@
1
1
  """Package version."""
2
2
 
3
- __version__ = "1.3.3"
3
+ __version__ = "1.3.4"
4
4
 
5
5
  __all__ = ["__version__"]
@@ -7,6 +7,25 @@ from typing import Literal
7
7
  from .tensor import Tensor
8
8
 
9
9
  NormOrder = Literal[1, 2, "fro", "inf"]
10
+ AxisLike = int | tuple[int, ...] | list[int] | None
11
+
12
+
13
+ def _normalized_axes(axis: AxisLike, ndim: int) -> tuple[int, ...]:
14
+ if axis is None:
15
+ return tuple(range(ndim))
16
+ axes = (axis,) if isinstance(axis, int) else tuple(axis)
17
+
18
+ normalized: list[int] = []
19
+ seen: set[int] = set()
20
+ for value in axes:
21
+ normalized_axis = value if value >= 0 else ndim + value
22
+ if normalized_axis < 0 or normalized_axis >= ndim:
23
+ raise ValueError("axis is out of range")
24
+ if normalized_axis in seen:
25
+ raise ValueError("duplicate reduction axis")
26
+ seen.add(normalized_axis)
27
+ normalized.append(normalized_axis)
28
+ return tuple(normalized)
10
29
 
11
30
 
12
31
  def square(input: Tensor) -> Tensor:
@@ -23,25 +42,23 @@ def reciprocal(input: Tensor) -> Tensor:
23
42
 
24
43
  def variance(
25
44
  input: Tensor,
26
- axis: int | None = None,
45
+ axis: AxisLike = None,
27
46
  keepdims: bool = False,
28
47
  correction: int = 0,
29
48
  ) -> Tensor:
30
- """Compute variance over all elements or one axis.
49
+ """Compute variance over all elements, one axis, or a tuple/list of axes.
31
50
 
32
51
  ``correction=1`` gives the usual sample variance denominator. TensorStudio
33
- currently supports a single optional axis, matching the C++ reduction API.
52
+ uses the product of the reduced axes as the denominator base.
34
53
  """
35
54
 
36
55
  if correction < 0:
37
56
  raise ValueError("correction must be non-negative")
38
- if axis is None:
39
- denom = input.size - correction
40
- else:
41
- normalized_axis = axis if axis >= 0 else input.ndim + axis
42
- if normalized_axis < 0 or normalized_axis >= input.ndim:
43
- raise ValueError("axis is out of range")
44
- denom = input.shape[normalized_axis] - correction
57
+ axes = _normalized_axes(axis, input.ndim)
58
+ denom = 1
59
+ for normalized_axis in axes:
60
+ denom *= input.shape[normalized_axis]
61
+ denom -= correction
45
62
  if denom <= 0:
46
63
  raise ValueError("variance denominator must be positive")
47
64
  mean = input.mean(axis=axis, keepdims=True)
@@ -52,11 +69,11 @@ def variance(
52
69
 
53
70
  def std(
54
71
  input: Tensor,
55
- axis: int | None = None,
72
+ axis: AxisLike = None,
56
73
  keepdims: bool = False,
57
74
  correction: int = 0,
58
75
  ) -> Tensor:
59
- """Compute standard deviation over all elements or one axis."""
76
+ """Compute standard deviation over all elements, one axis, or a tuple/list of axes."""
60
77
 
61
78
  return variance(input, axis=axis, keepdims=keepdims, correction=correction).sqrt()
62
79
 
@@ -64,10 +81,10 @@ def std(
64
81
  def norm(
65
82
  input: Tensor,
66
83
  ord: NormOrder = 2,
67
- axis: int | None = None,
84
+ axis: AxisLike = None,
68
85
  keepdims: bool = False,
69
86
  ) -> Tensor:
70
- """Compute a vector-style norm over all elements or one axis."""
87
+ """Compute a vector-style norm over all elements, one axis, or a tuple/list of axes."""
71
88
 
72
89
  magnitude = input.abs()
73
90
  if ord == 1:
@@ -79,4 +96,12 @@ def norm(
79
96
  raise ValueError("ord must be 1, 2, 'fro', or 'inf'")
80
97
 
81
98
 
82
- __all__ = ["NormOrder", "norm", "reciprocal", "square", "std", "variance"]
99
+ __all__ = [
100
+ "AxisLike",
101
+ "NormOrder",
102
+ "norm",
103
+ "reciprocal",
104
+ "square",
105
+ "std",
106
+ "variance",
107
+ ]
@@ -8,6 +8,7 @@ from . import _C
8
8
  from .tensor import Tensor
9
9
 
10
10
  PairLike = int | tuple[int, int] | list[int]
11
+ AxisLike = int | tuple[int, ...] | list[int] | None
11
12
 
12
13
 
13
14
  def _pair(value: PairLike, name: str) -> tuple[int, int]:
@@ -147,19 +148,19 @@ def avg_pool2d(
147
148
  )
148
149
 
149
150
 
150
- def sum(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: # noqa: A001
151
+ def sum(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: # noqa: A001
151
152
  return _C.sum(input, axis, keepdims)
152
153
 
153
154
 
154
- def mean(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor:
155
+ def mean(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor:
155
156
  return _C.mean(input, axis, keepdims)
156
157
 
157
158
 
158
- def max(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: # noqa: A001
159
+ def max(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: # noqa: A001
159
160
  return _C.max(input, axis, keepdims)
160
161
 
161
162
 
162
- def min(input: Tensor, axis: int | None = None, keepdims: bool = False) -> Tensor: # noqa: A001
163
+ def min(input: Tensor, axis: AxisLike = None, keepdims: bool = False) -> Tensor: # noqa: A001
163
164
  return _C.min(input, axis, keepdims)
164
165
 
165
166
 
@@ -1,5 +1,7 @@
1
1
  #include "bindings.hpp"
2
2
 
3
+ #include <utility>
4
+
3
5
  #include <pybind11/pybind11.h>
4
6
  #include <pybind11/stl.h>
5
7
 
@@ -72,28 +74,32 @@ void bind_ops(py::module_& module) {
72
74
  py::arg("padding_w") = 0,
73
75
  py::arg("count_include_pad") = false);
74
76
  module.def("sum", [](const Tensor& input, py::object axis, bool keepdims) {
75
- if (axis.is_none()) {
76
- return sum(input);
77
- }
78
- return sum(input, py::cast<int64_t>(axis), keepdims);
77
+ return reduce_from_py(input, std::move(axis), keepdims, "sum", [](const Tensor& tensor) {
78
+ return sum(tensor);
79
+ }, [](const Tensor& tensor, int64_t normalized_axis, bool keep) {
80
+ return sum(tensor, normalized_axis, keep);
81
+ });
79
82
  }, py::arg("input"), py::arg("axis") = py::none(), py::arg("keepdims") = false);
80
83
  module.def("mean", [](const Tensor& input, py::object axis, bool keepdims) {
81
- if (axis.is_none()) {
82
- return mean(input);
83
- }
84
- return mean(input, py::cast<int64_t>(axis), keepdims);
84
+ return reduce_from_py(input, std::move(axis), keepdims, "mean", [](const Tensor& tensor) {
85
+ return mean(tensor);
86
+ }, [](const Tensor& tensor, int64_t normalized_axis, bool keep) {
87
+ return mean(tensor, normalized_axis, keep);
88
+ });
85
89
  }, py::arg("input"), py::arg("axis") = py::none(), py::arg("keepdims") = false);
86
90
  module.def("max", [](const Tensor& input, py::object axis, bool keepdims) {
87
- if (axis.is_none()) {
88
- return max(input);
89
- }
90
- return max(input, py::cast<int64_t>(axis), keepdims);
91
+ return reduce_from_py(input, std::move(axis), keepdims, "max", [](const Tensor& tensor) {
92
+ return max(tensor);
93
+ }, [](const Tensor& tensor, int64_t normalized_axis, bool keep) {
94
+ return max(tensor, normalized_axis, keep);
95
+ });
91
96
  }, py::arg("input"), py::arg("axis") = py::none(), py::arg("keepdims") = false);
92
97
  module.def("min", [](const Tensor& input, py::object axis, bool keepdims) {
93
- if (axis.is_none()) {
94
- return min(input);
95
- }
96
- return min(input, py::cast<int64_t>(axis), keepdims);
98
+ return reduce_from_py(input, std::move(axis), keepdims, "min", [](const Tensor& tensor) {
99
+ return min(tensor);
100
+ }, [](const Tensor& tensor, int64_t normalized_axis, bool keep) {
101
+ return min(tensor, normalized_axis, keep);
102
+ });
97
103
  }, py::arg("input"), py::arg("axis") = py::none(), py::arg("keepdims") = false);
98
104
  module.def("relu", &relu);
99
105
  module.def("sigmoid", &sigmoid);