lucid-dl 2.11.0__tar.gz → 2.11.2__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.
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/PKG-INFO +7 -5
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/README.md +5 -3
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/__init__.py +4 -2
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_backend/core.py +89 -9
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_backend/metal.py +5 -1
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_func/__init__.py +162 -0
- lucid_dl-2.11.0/lucid/_tensor/tensor_ops.py → lucid_dl-2.11.2/lucid/_tensor/base.py +64 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_tensor/tensor.py +63 -19
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/autograd/__init__.py +4 -1
- lucid_dl-2.11.2/lucid/datasets/mnist.py +242 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imggen/__init__.py +1 -0
- lucid_dl-2.11.2/lucid/models/imggen/ncsn.py +402 -0
- lucid_dl-2.11.2/lucid/nn/_kernel/__init__.py +1 -0
- lucid_dl-2.11.2/lucid/nn/_kernel/activation.py +188 -0
- lucid_dl-2.11.2/lucid/nn/_kernel/attention.py +125 -0
- {lucid_dl-2.11.0/lucid/_backend → lucid_dl-2.11.2/lucid/nn/_kernel}/conv.py +4 -13
- lucid_dl-2.11.2/lucid/nn/_kernel/embedding.py +72 -0
- lucid_dl-2.11.2/lucid/nn/_kernel/loss.py +416 -0
- lucid_dl-2.11.2/lucid/nn/_kernel/norm.py +365 -0
- {lucid_dl-2.11.0/lucid/_backend → lucid_dl-2.11.2/lucid/nn/_kernel}/pool.py +7 -27
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/__init__.py +4 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_activation.py +19 -13
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_attention.py +9 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_conv.py +5 -16
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_loss.py +31 -32
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_norm.py +60 -69
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_pool.py +7 -7
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_util.py +5 -1
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/init/_dist.py +1 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/types.py +24 -2
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid_dl.egg-info/PKG-INFO +7 -5
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid_dl.egg-info/SOURCES.txt +10 -3
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/setup.py +2 -2
- lucid_dl-2.11.0/lucid/datasets/mnist.py +0 -113
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/LICENSE +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_backend/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_func/bfunc.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_func/gfunc.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_func/ufunc.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_fusion/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_fusion/base.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_fusion/func.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_tensor/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_util/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/_util/func.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/data/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/data/_base.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/data/_util.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/datasets/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/datasets/_base.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/datasets/cifar.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/einops/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/einops/_func.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/error.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/linalg/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/linalg/_func.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/alex.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/coatnet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/convnext.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/crossvit.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/cspnet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/cvt.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/dense.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/efficient.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/efficientformer.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/inception.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/inception_next.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/inception_res.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/lenet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/maxvit.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/mobile.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/pvt.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/resnest.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/resnet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/resnext.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/senet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/sknet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/swin.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/vgg.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/vit.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/xception.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imgclf/zfnet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imggen/ddpm.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/imggen/vae.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/detr.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/efficientdet.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/fast_rcnn.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/faster_rcnn.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/rcnn.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/util.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/yolo/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/yolo/yolo_v1.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/yolo/yolo_v2.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/yolo/yolo_v3.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/objdet/yolo/yolo_v4.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/seq2seq/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/seq2seq/transformer.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/models/util.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_drop.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_linear.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/functional/_spatial.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/fused.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/init/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/module.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/activation.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/attention.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/conv.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/drop.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/einops.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/linear.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/loss.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/norm.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/pool.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/rnn.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/sparse.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/transformer.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/modules/vision.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/parameter.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/nn/util.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/_base.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/ada.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/adam.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/lr_scheduler/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/lr_scheduler/_base.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/lr_scheduler/_schedulers.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/prop.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/optim/sgd.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/port.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/random/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/random/_func.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/transforms/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/transforms/_base.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/transforms/image.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/visual/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/visual/graph.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/weights/__init__.py +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid/weights/__init__.pyi +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid_dl.egg-info/dependency_links.txt +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid_dl.egg-info/requires.txt +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/lucid_dl.egg-info/top_level.txt +0 -0
- {lucid_dl-2.11.0 → lucid_dl-2.11.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lucid-dl
|
|
3
|
-
Version: 2.11.
|
|
3
|
+
Version: 2.11.2
|
|
4
4
|
Summary: Lumerico's Comprehensive Interface for Deep Learning
|
|
5
5
|
Home-page: https://github.com/ChanLumerico/lucid
|
|
6
6
|
Author: ChanLumerico
|
|
@@ -8,7 +8,7 @@ Author-email: greensox284@gmail.com
|
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.14
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
14
|
Requires-Dist: numpy
|
|
@@ -33,7 +33,7 @@ Dynamic: summary
|
|
|
33
33
|
[](https://pepy.tech/projects/lucid-dl)
|
|
34
34
|

|
|
35
35
|

|
|
36
|
-

|
|
37
37
|
|
|
38
38
|
**Lucid** is a minimalist deep learning framework built entirely from scratch in Python. It offers a pedagogically rich environment to explore the foundations of modern deep learning systems, including autodiff, neural network modules, and GPU acceleration — all while staying lightweight, readable, and free of complex dependencies.
|
|
39
39
|
|
|
@@ -48,9 +48,11 @@ Whether you're a student, educator, or an advanced researcher seeking to demysti
|
|
|
48
48
|
|
|
49
49
|
### 🔥 What's New
|
|
50
50
|
|
|
51
|
-
-
|
|
51
|
+
- Added various inplace tensor operations (e.g. `a.add_(b)`, `a.mul_(b)`)
|
|
52
52
|
|
|
53
|
-
-
|
|
53
|
+
- Added **Noise Conditional Score Network(NCSN)** to `lucid.models.NCSN`
|
|
54
|
+
|
|
55
|
+
- Branched a Stand-Alone Autograd Engine as `lucid.autograd`
|
|
54
56
|
|
|
55
57
|
- Provides a generalized API of computing gradients:
|
|
56
58
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://pepy.tech/projects/lucid-dl)
|
|
6
6
|

|
|
7
7
|

|
|
8
|
-

|
|
9
9
|
|
|
10
10
|
**Lucid** is a minimalist deep learning framework built entirely from scratch in Python. It offers a pedagogically rich environment to explore the foundations of modern deep learning systems, including autodiff, neural network modules, and GPU acceleration — all while staying lightweight, readable, and free of complex dependencies.
|
|
11
11
|
|
|
@@ -20,9 +20,11 @@ Whether you're a student, educator, or an advanced researcher seeking to demysti
|
|
|
20
20
|
|
|
21
21
|
### 🔥 What's New
|
|
22
22
|
|
|
23
|
-
-
|
|
23
|
+
- Added various inplace tensor operations (e.g. `a.add_(b)`, `a.mul_(b)`)
|
|
24
24
|
|
|
25
|
-
-
|
|
25
|
+
- Added **Noise Conditional Score Network(NCSN)** to `lucid.models.NCSN`
|
|
26
|
+
|
|
27
|
+
- Branched a Stand-Alone Autograd Engine as `lucid.autograd`
|
|
26
28
|
|
|
27
29
|
- Provides a generalized API of computing gradients:
|
|
28
30
|
|
|
@@ -64,9 +64,11 @@ inf = math.inf
|
|
|
64
64
|
|
|
65
65
|
Int = types.Int
|
|
66
66
|
Int8, Int16, Int32, Int64 = (types.Int8, types.Int16, types.Int32, types.Int64)
|
|
67
|
+
Char, Short, Long = (Int8, Int16, Int64)
|
|
67
68
|
|
|
68
69
|
Float = types.Float
|
|
69
70
|
Float16, Float32, Float64 = (types.Float16, types.Float32, types.Float64)
|
|
71
|
+
Half, Double = (Float16, Float64)
|
|
70
72
|
|
|
71
73
|
Complex = types.Complex
|
|
72
74
|
Complex64 = types.Complex64
|
|
@@ -306,9 +308,9 @@ def register_model(func: _ModuleReturnFunc) -> _ModuleReturnFunc:
|
|
|
306
308
|
|
|
307
309
|
|
|
308
310
|
def _conv_view_limit_mb() -> int:
|
|
309
|
-
from lucid.
|
|
311
|
+
from lucid._kernel import conv as _conv_kernel
|
|
310
312
|
|
|
311
|
-
return
|
|
313
|
+
return _conv_kernel.get_conv_view_limit_mb()
|
|
312
314
|
|
|
313
315
|
|
|
314
316
|
def __getattr__(name: str) -> Any:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import Callable, Tuple, ClassVar
|
|
2
|
+
from typing import Callable, Self, Tuple, ClassVar
|
|
3
3
|
import functools
|
|
4
4
|
import weakref
|
|
5
5
|
|
|
@@ -37,6 +37,7 @@ def func_op(
|
|
|
37
37
|
requires_grad = False
|
|
38
38
|
is_free = True
|
|
39
39
|
dtype_hint: _BuiltinNumeric | Numeric | None = None
|
|
40
|
+
inplace_target: _TensorLike | None = None
|
|
40
41
|
|
|
41
42
|
if n_in is None:
|
|
42
43
|
tensor_args = args
|
|
@@ -68,8 +69,42 @@ def func_op(
|
|
|
68
69
|
+ f"('{type(op_self).__name__}')."
|
|
69
70
|
)
|
|
70
71
|
|
|
72
|
+
if op_self._inplace:
|
|
73
|
+
if n_ret != 1:
|
|
74
|
+
raise ValueError("inplace op must have a single return value.")
|
|
75
|
+
if not (0 <= op_self._inplace_target < len(tensors)):
|
|
76
|
+
raise ValueError("inplace_target is out of range.")
|
|
77
|
+
|
|
78
|
+
target = tensors[op_self._inplace_target]
|
|
79
|
+
if lucid.grad_enabled() and target.requires_grad and target.is_leaf:
|
|
80
|
+
raise RuntimeError(
|
|
81
|
+
"A leaf tensor with 'requires_grad=True' "
|
|
82
|
+
"cannot be subjected to inplace operations."
|
|
83
|
+
)
|
|
84
|
+
inplace_target = target
|
|
85
|
+
|
|
86
|
+
proxy = target.new_tensor()
|
|
87
|
+
proxy._op = target._op
|
|
88
|
+
proxy._prev = list(target._prev)
|
|
89
|
+
proxy._backward_op = target._backward_op
|
|
90
|
+
proxy._backward_hooks = list(target._backward_hooks)
|
|
91
|
+
proxy.grad = None
|
|
92
|
+
proxy._version = target._version
|
|
93
|
+
|
|
94
|
+
if hasattr(target, "_is_free"):
|
|
95
|
+
proxy._is_free = target._is_free
|
|
96
|
+
if hasattr(target, "_is_bool_tensor"):
|
|
97
|
+
proxy._is_bool_tensor = target._is_bool_tensor
|
|
98
|
+
|
|
99
|
+
tensors = (
|
|
100
|
+
tensors[: op_self._inplace_target]
|
|
101
|
+
+ (proxy,)
|
|
102
|
+
+ tensors[op_self._inplace_target + 1 :]
|
|
103
|
+
)
|
|
104
|
+
|
|
71
105
|
non_tensor_args = args[n_in:] if n_in is not None else ()
|
|
72
106
|
new_args = (*tensors, *non_tensor_args)
|
|
107
|
+
|
|
73
108
|
func_return_pairs = forward_func(op_self, *new_args, **kwargs)
|
|
74
109
|
|
|
75
110
|
tensor_refs = tuple(weakref.ref(t) for t in tensors)
|
|
@@ -92,6 +127,25 @@ def func_op(
|
|
|
92
127
|
|
|
93
128
|
if num_returns == 1:
|
|
94
129
|
func_return_pairs: _FuncOpReturnType = (func_return_pairs,)
|
|
130
|
+
elif op_self._inplace:
|
|
131
|
+
raise ValueError("inplace op must have a single return value.")
|
|
132
|
+
|
|
133
|
+
if op_self._inplace:
|
|
134
|
+
(ret_value, grad_func) = func_return_pairs[0]
|
|
135
|
+
target = inplace_target
|
|
136
|
+
if target is None:
|
|
137
|
+
raise RuntimeError("Missing inplace target tensor.")
|
|
138
|
+
target.data = ret_value.data
|
|
139
|
+
|
|
140
|
+
if ret_value.dtype is bool:
|
|
141
|
+
target._is_bool_tensor = True
|
|
142
|
+
target.dtype = bool
|
|
143
|
+
else:
|
|
144
|
+
target._is_bool_tensor = False
|
|
145
|
+
target.dtype = ret_value.dtype
|
|
146
|
+
|
|
147
|
+
target._version += 1
|
|
148
|
+
func_return_pairs = ((target, grad_func),)
|
|
95
149
|
|
|
96
150
|
results: Tuple[_TensorLike, ...] = tuple()
|
|
97
151
|
for result, grad_func in func_return_pairs:
|
|
@@ -113,6 +167,7 @@ def func_op(
|
|
|
113
167
|
forward_op_ref=weakref.ref(op_self),
|
|
114
168
|
grad_func=grad_func,
|
|
115
169
|
tensor_refs=tensor_refs,
|
|
170
|
+
versions=tuple(t._version for t in tensors),
|
|
116
171
|
device=device,
|
|
117
172
|
)
|
|
118
173
|
|
|
@@ -138,15 +193,15 @@ def func_op(
|
|
|
138
193
|
|
|
139
194
|
|
|
140
195
|
def unary_func_op(has_gradient: bool = True, device: _DeviceType = "cpu") -> Callable:
|
|
141
|
-
return func_op(1, 1, has_gradient
|
|
196
|
+
return func_op(1, 1, has_gradient, device)
|
|
142
197
|
|
|
143
198
|
|
|
144
199
|
def binary_func_op(has_gradient: bool = True, device: _DeviceType = "cpu") -> Callable:
|
|
145
|
-
return func_op(2, 1, has_gradient
|
|
200
|
+
return func_op(2, 1, has_gradient, device)
|
|
146
201
|
|
|
147
202
|
|
|
148
203
|
def poly_func_op(has_gradient: bool = True, device: _DeviceType = "cpu") -> Callable:
|
|
149
|
-
return func_op(None, 1, has_gradient
|
|
204
|
+
return func_op(None, 1, has_gradient, device)
|
|
150
205
|
|
|
151
206
|
|
|
152
207
|
class Operation(ABC):
|
|
@@ -154,11 +209,18 @@ class Operation(ABC):
|
|
|
154
209
|
|
|
155
210
|
def __init__(self) -> None:
|
|
156
211
|
self.result: _TensorLike | tuple[_TensorLike, ...] | None = None
|
|
212
|
+
self._inplace: bool = False
|
|
213
|
+
self._inplace_target: int = 0
|
|
157
214
|
self._flops: int | None = None
|
|
158
215
|
|
|
159
216
|
def clear(self) -> None:
|
|
160
217
|
self.result = None
|
|
161
218
|
|
|
219
|
+
def inplace(self, target: int = 0) -> Self:
|
|
220
|
+
self._inplace = True
|
|
221
|
+
self._inplace_target = target
|
|
222
|
+
return self
|
|
223
|
+
|
|
162
224
|
@abstractmethod
|
|
163
225
|
def cpu(self, *args, **kwargs) -> _FuncOpReturnType: ...
|
|
164
226
|
|
|
@@ -201,12 +263,14 @@ class BackwardOperation:
|
|
|
201
263
|
forward_op_ref: weakref.ref[Operation] | None,
|
|
202
264
|
grad_func: _GradFuncType | None,
|
|
203
265
|
tensor_refs: tuple[weakref.ref[_TensorLike]],
|
|
266
|
+
versions: tuple[int, ...] = (),
|
|
204
267
|
device: _DeviceType | None = "cpu",
|
|
205
268
|
custom_closure: Callable[[], None] | None = None,
|
|
206
269
|
) -> None:
|
|
207
270
|
self.forward_op_ref = forward_op_ref
|
|
208
271
|
self.grad_func = grad_func
|
|
209
272
|
self.tensor_refs = tensor_refs
|
|
273
|
+
self.versions = versions
|
|
210
274
|
self.device = device
|
|
211
275
|
|
|
212
276
|
self.custom_closure = custom_closure
|
|
@@ -215,18 +279,36 @@ class BackwardOperation:
|
|
|
215
279
|
if self.grad_func is None and self.custom_closure is None:
|
|
216
280
|
raise ValueError("Either 'grad_func' or 'custom_closure' must be provided.")
|
|
217
281
|
|
|
282
|
+
if len(tensor_refs) != len(versions):
|
|
283
|
+
raise ValueError("Numbers of 'tensor_refs' and 'versions' do not match.")
|
|
284
|
+
|
|
218
285
|
def override_grad_func(self, new_grad_func: _GradFuncType) -> None:
|
|
219
286
|
if self.custom_closure is not None:
|
|
220
287
|
return
|
|
221
288
|
self.grad_func = new_grad_func
|
|
222
289
|
|
|
223
290
|
def override_tensor_refs(
|
|
224
|
-
self,
|
|
291
|
+
self,
|
|
292
|
+
new_tensor_refs: tuple[weakref.ref[_TensorLike]],
|
|
293
|
+
new_versions: tuple[int, ...] | None = None,
|
|
225
294
|
) -> None:
|
|
226
295
|
self.tensor_refs = new_tensor_refs
|
|
227
296
|
self.num_inputs = len(new_tensor_refs)
|
|
297
|
+
if new_versions is not None:
|
|
298
|
+
if len(new_versions) != len(new_tensor_refs):
|
|
299
|
+
raise ValueError(
|
|
300
|
+
"Numbers of 'tensor_refs' and 'versions' do not match."
|
|
301
|
+
)
|
|
302
|
+
self.versions = new_versions
|
|
228
303
|
|
|
229
304
|
def __call__(self) -> None:
|
|
305
|
+
live_tensors = tuple(ref() for ref in self.tensor_refs)
|
|
306
|
+
if not live_tensors or any(t is None for t in live_tensors):
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
if any(ver != t._version for ver, t in zip(self.versions, live_tensors)):
|
|
310
|
+
raise RuntimeError(f"Tensor version mismatch detected.")
|
|
311
|
+
|
|
230
312
|
if self.custom_closure is not None:
|
|
231
313
|
self.custom_closure()
|
|
232
314
|
return
|
|
@@ -240,16 +322,14 @@ class BackwardOperation:
|
|
|
240
322
|
if self.num_inputs == 1 or not isinstance(grads, tuple):
|
|
241
323
|
grads = (grads,)
|
|
242
324
|
|
|
243
|
-
live_tensors = tuple(ref() for ref in self.tensor_refs)
|
|
244
|
-
if any(t is None for t in live_tensors):
|
|
245
|
-
return
|
|
246
|
-
|
|
247
325
|
if len(grads) != len(live_tensors):
|
|
248
326
|
raise ValueError(
|
|
249
327
|
f"Expected {len(live_tensors)} gradients, got {len(grads)}."
|
|
250
328
|
)
|
|
251
329
|
|
|
252
330
|
for tensor, grad in zip(live_tensors, grads):
|
|
331
|
+
if not tensor.requires_grad and grad is None:
|
|
332
|
+
continue
|
|
253
333
|
new_grad = lucid._match_grad_shape(tensor.data, grad, device=self.device)
|
|
254
334
|
lucid._set_tensor_grad(tensor, new_grad)
|
|
255
335
|
|
|
@@ -4,6 +4,8 @@ import platform
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
|
|
7
|
+
from lucid.types import _TensorLike
|
|
8
|
+
|
|
7
9
|
try:
|
|
8
10
|
import mlx.core as mx
|
|
9
11
|
except ModuleNotFoundError as e:
|
|
@@ -105,7 +107,9 @@ def parse_mlx_indexing(index: Any) -> Any:
|
|
|
105
107
|
return index
|
|
106
108
|
|
|
107
109
|
|
|
108
|
-
def post_step_eval(
|
|
110
|
+
def post_step_eval(
|
|
111
|
+
param: _TensorLike | Any, state: Mapping[str, Any] | None = None
|
|
112
|
+
) -> None:
|
|
109
113
|
is_gpu = False
|
|
110
114
|
if hasattr(param, "is_gpu"):
|
|
111
115
|
try:
|
|
@@ -34,18 +34,50 @@ def add(a: Tensor, b: Tensor, /) -> Tensor:
|
|
|
34
34
|
return bfunc.add()(a, b)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
+
def add_(a: Tensor, b: Tensor) -> Tensor:
|
|
38
|
+
return bfunc.add().inplace()(a, b)
|
|
39
|
+
|
|
40
|
+
|
|
37
41
|
def sub(a: Tensor, b: Tensor, /) -> Tensor:
|
|
38
42
|
return bfunc.sub()(a, b)
|
|
39
43
|
|
|
40
44
|
|
|
45
|
+
def sub_(a: Tensor, b: Tensor, /) -> Tensor:
|
|
46
|
+
return bfunc.sub().inplace()(a, b)
|
|
47
|
+
|
|
48
|
+
|
|
41
49
|
def multiply(a: Tensor, b: Tensor, /) -> Tensor:
|
|
42
50
|
return bfunc.multiply()(a, b)
|
|
43
51
|
|
|
44
52
|
|
|
53
|
+
def mul_(a: Tensor, b: Tensor, /) -> Tensor:
|
|
54
|
+
return bfunc.multiply().inplace()(a, b)
|
|
55
|
+
|
|
56
|
+
|
|
45
57
|
def div(a: Tensor, b: Tensor, /, floor: bool = False) -> Tensor:
|
|
46
58
|
return bfunc.truediv()(a, b) if not floor else bfunc.floordiv()(a, b)
|
|
47
59
|
|
|
48
60
|
|
|
61
|
+
def div_(a: Tensor, b: Tensor, /, floor: bool = False) -> Tensor:
|
|
62
|
+
return (
|
|
63
|
+
bfunc.truediv().inplace()(a, b)
|
|
64
|
+
if not floor
|
|
65
|
+
else bfunc.floordiv().inplace()(a, b)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def minimum_(a: Tensor, b: Tensor, /) -> Tensor:
|
|
70
|
+
return bfunc.minimum().inplace()(a, b)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def maximum_(a: Tensor, b: Tensor, /) -> Tensor:
|
|
74
|
+
return bfunc.maximum().inplace()(a, b)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def power_(a: Tensor, b: Tensor, /) -> Tensor:
|
|
78
|
+
return bfunc.power().inplace()(a, b)
|
|
79
|
+
|
|
80
|
+
|
|
49
81
|
def _equal(a: Tensor, b: Tensor, /) -> Tensor:
|
|
50
82
|
return bfunc._equal()(a, b)
|
|
51
83
|
|
|
@@ -237,6 +269,92 @@ def cube(a: Tensor, /) -> Tensor:
|
|
|
237
269
|
return ufunc.cube()(a)
|
|
238
270
|
|
|
239
271
|
|
|
272
|
+
def neg_(a: Tensor, /) -> Tensor:
|
|
273
|
+
return ufunc._neg().inplace()(a)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def exp_(a: Tensor, /) -> Tensor:
|
|
277
|
+
return ufunc.exp().inplace()(a)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def log_(a: Tensor, /) -> Tensor:
|
|
281
|
+
return ufunc.log().inplace()(a)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def log2_(a: Tensor, /) -> Tensor:
|
|
285
|
+
return ufunc.log2().inplace()(a)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def sqrt_(a: Tensor, /) -> Tensor:
|
|
289
|
+
return ufunc.sqrt().inplace()(a)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def sin_(a: Tensor, /) -> Tensor:
|
|
293
|
+
return ufunc.sin().inplace()(a)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def cos_(a: Tensor, /) -> Tensor:
|
|
297
|
+
return ufunc.cos().inplace()(a)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def tan_(a: Tensor, /) -> Tensor:
|
|
301
|
+
return ufunc.tan().inplace()(a)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def arcsin_(a: Tensor, /) -> Tensor:
|
|
305
|
+
return ufunc.arcsin().inplace()(a)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def arccos_(a: Tensor, /) -> Tensor:
|
|
309
|
+
return ufunc.arccos().inplace()(a)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def arctan_(a: Tensor, /) -> Tensor:
|
|
313
|
+
return ufunc.arctan().inplace()(a)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def sinh_(a: Tensor, /) -> Tensor:
|
|
317
|
+
return ufunc.sinh().inplace()(a)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def cosh_(a: Tensor, /) -> Tensor:
|
|
321
|
+
return ufunc.cosh().inplace()(a)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def tanh_(a: Tensor, /) -> Tensor:
|
|
325
|
+
return ufunc.tanh().inplace()(a)
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def clip_(
|
|
329
|
+
a: Tensor, /, min_value: _Scalar | None = None, max_value: _Scalar | None = None
|
|
330
|
+
) -> Tensor:
|
|
331
|
+
if min_value is None:
|
|
332
|
+
min_value = lucid.min(a).item()
|
|
333
|
+
if max_value is None:
|
|
334
|
+
max_value = lucid.max(a).item()
|
|
335
|
+
return ufunc.clip(min_value, max_value).inplace()(a)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def abs_(a: Tensor, /) -> Tensor:
|
|
339
|
+
return ufunc._abs().inplace()(a)
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def sign_(a: Tensor, /) -> Tensor:
|
|
343
|
+
return ufunc.sign().inplace()(a)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def reciprocal_(a: Tensor, /) -> Tensor:
|
|
347
|
+
return ufunc.reciprocal().inplace()(a)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def square_(a: Tensor, /) -> Tensor:
|
|
351
|
+
return ufunc.square().inplace()(a)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def cube_(a: Tensor, /) -> Tensor:
|
|
355
|
+
return ufunc.cube().inplace()(a)
|
|
356
|
+
|
|
357
|
+
|
|
240
358
|
@property
|
|
241
359
|
def _T(a: Tensor, /) -> Tensor:
|
|
242
360
|
return ufunc._T()(a)
|
|
@@ -301,6 +419,18 @@ def ceil(a: Tensor) -> Tensor:
|
|
|
301
419
|
return ufunc.ceil()(a)
|
|
302
420
|
|
|
303
421
|
|
|
422
|
+
def round_(a: Tensor, /, decimals: int = 0) -> Tensor:
|
|
423
|
+
return ufunc.round(decimals).inplace()(a)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def floor_(a: Tensor) -> Tensor:
|
|
427
|
+
return ufunc.floor().inplace()(a)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def ceil_(a: Tensor) -> Tensor:
|
|
431
|
+
return ufunc.ceil().inplace()(a)
|
|
432
|
+
|
|
433
|
+
|
|
304
434
|
def cumprod(a: Tensor, axis: int = -1) -> Tensor:
|
|
305
435
|
return ufunc.cumprod(axis)(a)
|
|
306
436
|
|
|
@@ -595,3 +725,35 @@ Tensor.swapaxes = swapaxes
|
|
|
595
725
|
Tensor.round = round
|
|
596
726
|
Tensor.floor = floor
|
|
597
727
|
Tensor.ceil = ceil
|
|
728
|
+
|
|
729
|
+
Tensor.add_ = add_
|
|
730
|
+
Tensor.sub_ = sub_
|
|
731
|
+
Tensor.mul_ = mul_
|
|
732
|
+
Tensor.div_ = div_
|
|
733
|
+
Tensor.minimum_ = minimum_
|
|
734
|
+
Tensor.maximum_ = maximum_
|
|
735
|
+
Tensor.power_ = power_
|
|
736
|
+
|
|
737
|
+
Tensor.neg_ = neg_
|
|
738
|
+
Tensor.exp_ = exp_
|
|
739
|
+
Tensor.log_ = log_
|
|
740
|
+
Tensor.log2_ = log2_
|
|
741
|
+
Tensor.sqrt_ = sqrt_
|
|
742
|
+
Tensor.sin_ = sin_
|
|
743
|
+
Tensor.cos_ = cos_
|
|
744
|
+
Tensor.tan_ = tan_
|
|
745
|
+
Tensor.arcsin_ = arcsin_
|
|
746
|
+
Tensor.arccos_ = arccos_
|
|
747
|
+
Tensor.arctan_ = arctan_
|
|
748
|
+
Tensor.sinh_ = sinh_
|
|
749
|
+
Tensor.cosh_ = cosh_
|
|
750
|
+
Tensor.tanh_ = tanh_
|
|
751
|
+
Tensor.clip_ = clip_
|
|
752
|
+
Tensor.abs_ = abs_
|
|
753
|
+
Tensor.sign_ = sign_
|
|
754
|
+
Tensor.reciprocal_ = reciprocal_
|
|
755
|
+
Tensor.square_ = square_
|
|
756
|
+
Tensor.cube_ = cube_
|
|
757
|
+
Tensor.round_ = round_
|
|
758
|
+
Tensor.floor_ = floor_
|
|
759
|
+
Tensor.ceil_ = ceil_
|
|
@@ -133,3 +133,67 @@ class _TensorBase:
|
|
|
133
133
|
def nonzero(self) -> Self: ...
|
|
134
134
|
|
|
135
135
|
def diagonal(self, offset: int = 0, axis1: int = 0, axis2: int = 1) -> Self: ...
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class _TensorInplace:
|
|
139
|
+
def add_(self, other: Self) -> Self: ...
|
|
140
|
+
|
|
141
|
+
def sub_(self, other: Self) -> Self: ...
|
|
142
|
+
|
|
143
|
+
def mul_(self, other: Self) -> Self: ...
|
|
144
|
+
|
|
145
|
+
def div_(self, other: Self, /, floor: bool = False) -> Self: ...
|
|
146
|
+
|
|
147
|
+
def minimum_(self, other: Self) -> Self: ...
|
|
148
|
+
|
|
149
|
+
def maximum_(self, other: Self) -> Self: ...
|
|
150
|
+
|
|
151
|
+
def power_(self, other: Self) -> Self: ...
|
|
152
|
+
|
|
153
|
+
def neg_(self) -> Self: ...
|
|
154
|
+
|
|
155
|
+
def exp_(self) -> Self: ...
|
|
156
|
+
|
|
157
|
+
def log_(self) -> Self: ...
|
|
158
|
+
|
|
159
|
+
def log2_(self) -> Self: ...
|
|
160
|
+
|
|
161
|
+
def sqrt_(self) -> Self: ...
|
|
162
|
+
|
|
163
|
+
def sin_(self) -> Self: ...
|
|
164
|
+
|
|
165
|
+
def cos_(self) -> Self: ...
|
|
166
|
+
|
|
167
|
+
def tan_(self) -> Self: ...
|
|
168
|
+
|
|
169
|
+
def arcsin_(self) -> Self: ...
|
|
170
|
+
|
|
171
|
+
def arccos_(self) -> Self: ...
|
|
172
|
+
|
|
173
|
+
def arctan_(self) -> Self: ...
|
|
174
|
+
|
|
175
|
+
def sinh_(self) -> Self: ...
|
|
176
|
+
|
|
177
|
+
def cosh_(self) -> Self: ...
|
|
178
|
+
|
|
179
|
+
def tanh_(self) -> Self: ...
|
|
180
|
+
|
|
181
|
+
def clip_(
|
|
182
|
+
self, min_value: _Scalar | None = None, max_value: _Scalar | None = None
|
|
183
|
+
) -> Self: ...
|
|
184
|
+
|
|
185
|
+
def abs_(self) -> Self: ...
|
|
186
|
+
|
|
187
|
+
def sign_(self) -> Self: ...
|
|
188
|
+
|
|
189
|
+
def reciprocal_(self) -> Self: ...
|
|
190
|
+
|
|
191
|
+
def square_(self) -> Self: ...
|
|
192
|
+
|
|
193
|
+
def cube_(self) -> Self: ...
|
|
194
|
+
|
|
195
|
+
def round_(self, decimals: int = 0) -> Self: ...
|
|
196
|
+
|
|
197
|
+
def floor_(self) -> Self: ...
|
|
198
|
+
|
|
199
|
+
def ceil_(self) -> Self: ...
|