nervecode 0.1.0__py3-none-any.whl
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.
- nervecode/__init__.py +415 -0
- nervecode/_version.py +10 -0
- nervecode/core/__init__.py +19 -0
- nervecode/core/assignment.py +165 -0
- nervecode/core/codebook.py +182 -0
- nervecode/core/shapes.py +107 -0
- nervecode/core/temperature.py +227 -0
- nervecode/core/trace.py +166 -0
- nervecode/core/types.py +116 -0
- nervecode/integration/__init__.py +9 -0
- nervecode/layers/__init__.py +15 -0
- nervecode/layers/base.py +333 -0
- nervecode/layers/conv.py +174 -0
- nervecode/layers/linear.py +176 -0
- nervecode/layers/reducers.py +80 -0
- nervecode/layers/wrap.py +223 -0
- nervecode/scoring/__init__.py +20 -0
- nervecode/scoring/aggregator.py +369 -0
- nervecode/scoring/calibrator.py +396 -0
- nervecode/scoring/types.py +33 -0
- nervecode/training/__init__.py +25 -0
- nervecode/training/diagnostics.py +194 -0
- nervecode/training/loss.py +188 -0
- nervecode/training/updaters.py +168 -0
- nervecode/utils/__init__.py +14 -0
- nervecode/utils/overhead.py +177 -0
- nervecode/utils/seed.py +161 -0
- nervecode-0.1.0.dist-info/METADATA +83 -0
- nervecode-0.1.0.dist-info/RECORD +31 -0
- nervecode-0.1.0.dist-info/WHEEL +4 -0
- nervecode-0.1.0.dist-info/licenses/LICENSE +22 -0
nervecode/utils/seed.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""Seeding helpers to make runs reproducible across local and CI.
|
|
2
|
+
|
|
3
|
+
These utilities intentionally keep a small surface and no hard dependency on
|
|
4
|
+
NumPy. If NumPy is available, its global RNG is also seeded and restored.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import contextlib
|
|
10
|
+
import importlib
|
|
11
|
+
import os
|
|
12
|
+
import random
|
|
13
|
+
import types
|
|
14
|
+
import typing
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _maybe_import_numpy() -> typing.Any | None:
|
|
18
|
+
"""Return NumPy module if available, else None."""
|
|
19
|
+
try:
|
|
20
|
+
return importlib.import_module("numpy")
|
|
21
|
+
except Exception: # pragma: no cover - optional dependency
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _maybe_import_torch() -> typing.Any | None:
|
|
26
|
+
"""Return a torch-like module if available with required attributes, else None."""
|
|
27
|
+
try:
|
|
28
|
+
t = importlib.import_module("torch")
|
|
29
|
+
except Exception: # pragma: no cover - torch missing
|
|
30
|
+
return None
|
|
31
|
+
required = all(hasattr(t, name) for name in ("manual_seed", "get_rng_state", "set_rng_state"))
|
|
32
|
+
return t if required else None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def seed_from_env(
|
|
36
|
+
env_var: str = "NERVECODE_SEED",
|
|
37
|
+
default: int = 1234,
|
|
38
|
+
*,
|
|
39
|
+
set_env_if_missing: bool = False,
|
|
40
|
+
) -> int:
|
|
41
|
+
"""Return an integer seed sourced from an environment variable.
|
|
42
|
+
|
|
43
|
+
- If ``env_var`` is set and parseable as an int, return its value.
|
|
44
|
+
- Otherwise, return ``default``. If ``set_env_if_missing`` is True, also set
|
|
45
|
+
``os.environ[env_var]`` to the default value for downstream tools.
|
|
46
|
+
"""
|
|
47
|
+
raw = os.environ.get(env_var)
|
|
48
|
+
if raw is not None:
|
|
49
|
+
try:
|
|
50
|
+
return int(raw)
|
|
51
|
+
except ValueError: # Fall back to default on malformed input
|
|
52
|
+
pass
|
|
53
|
+
if set_env_if_missing:
|
|
54
|
+
os.environ[env_var] = str(default)
|
|
55
|
+
return default
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def seed_everything(seed: int, *, deterministic: bool = True) -> None:
|
|
59
|
+
"""Seed Python, optional NumPy, and PyTorch RNGs.
|
|
60
|
+
|
|
61
|
+
Also toggles PyTorch deterministic settings when ``deterministic`` is True to
|
|
62
|
+
minimize nondeterministic kernels. On CUDA setups, call this as early as
|
|
63
|
+
possible in process startup for best effect.
|
|
64
|
+
"""
|
|
65
|
+
# Hash-based ops reproducibility (effective at interpreter start;
|
|
66
|
+
# set anyway for child processes invoked by test runners)
|
|
67
|
+
os.environ["PYTHONHASHSEED"] = str(seed)
|
|
68
|
+
|
|
69
|
+
random.seed(seed)
|
|
70
|
+
|
|
71
|
+
np = _maybe_import_numpy()
|
|
72
|
+
if np is not None: # pragma: no branch - trivial branch
|
|
73
|
+
np.random.seed(seed)
|
|
74
|
+
|
|
75
|
+
t = _maybe_import_torch()
|
|
76
|
+
if t is not None:
|
|
77
|
+
t.manual_seed(seed)
|
|
78
|
+
if hasattr(t, "cuda") and t.cuda.is_available(): # pragma: no cover
|
|
79
|
+
t.cuda.manual_seed_all(seed)
|
|
80
|
+
|
|
81
|
+
# Configure PyTorch deterministic behavior as far as feasible.
|
|
82
|
+
t = _maybe_import_torch()
|
|
83
|
+
if t is not None and hasattr(t, "use_deterministic_algorithms"):
|
|
84
|
+
# warn_only=True avoids raising on ops without deterministic kernels
|
|
85
|
+
with contextlib.suppress(Exception): # pragma: no cover - older/newer API differences
|
|
86
|
+
t.use_deterministic_algorithms(bool(deterministic), warn_only=True)
|
|
87
|
+
|
|
88
|
+
# cuDNN knobs (safe on CPU-only builds; no-ops)
|
|
89
|
+
# cuDNN knobs (safe on CPU-only builds; no-ops)
|
|
90
|
+
try:
|
|
91
|
+
cudnn = importlib.import_module("torch.backends.cudnn")
|
|
92
|
+
except Exception: # pragma: no cover - backend not available
|
|
93
|
+
cudnn = None
|
|
94
|
+
if cudnn is not None: # pragma: no branch
|
|
95
|
+
cudnn_mod: typing.Any = cudnn
|
|
96
|
+
try:
|
|
97
|
+
cudnn_mod.deterministic = bool(deterministic)
|
|
98
|
+
cudnn_mod.benchmark = not bool(deterministic)
|
|
99
|
+
except Exception: # pragma: no cover - attributes may be missing
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class temp_seed(contextlib.AbstractContextManager[None]):
|
|
104
|
+
"""Temporarily set RNG seeds and restore previous states on exit.
|
|
105
|
+
|
|
106
|
+
This context manager saves Python's ``random`` state, optional NumPy's global
|
|
107
|
+
RNG state, and PyTorch CPU/CUDA RNG states. It then calls ``seed_everything``
|
|
108
|
+
with the provided seed and restores the saved states when leaving the context.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def __init__(self, seed: int, *, deterministic: bool = True) -> None:
|
|
112
|
+
self._seed = int(seed)
|
|
113
|
+
self._deterministic = bool(deterministic)
|
|
114
|
+
|
|
115
|
+
self._py_state: tuple[typing.Any, ...] | None = None
|
|
116
|
+
self._np_state: typing.Any | None = None
|
|
117
|
+
self._torch_cpu_state: typing.Any | None = None
|
|
118
|
+
self._torch_cuda_states: typing.Any | None = None
|
|
119
|
+
|
|
120
|
+
def __enter__(self) -> None:
|
|
121
|
+
# Save current states
|
|
122
|
+
self._py_state = random.getstate()
|
|
123
|
+
np = _maybe_import_numpy()
|
|
124
|
+
if np is not None: # pragma: no branch
|
|
125
|
+
self._np_state = np.random.get_state()
|
|
126
|
+
t = _maybe_import_torch()
|
|
127
|
+
if t is not None:
|
|
128
|
+
self._torch_cpu_state = t.get_rng_state()
|
|
129
|
+
if hasattr(t, "cuda") and t.cuda.is_available(): # pragma: no cover
|
|
130
|
+
self._torch_cuda_states = t.cuda.get_rng_state_all()
|
|
131
|
+
# Apply temporary seed
|
|
132
|
+
seed_everything(self._seed, deterministic=self._deterministic)
|
|
133
|
+
return None
|
|
134
|
+
|
|
135
|
+
def __exit__(
|
|
136
|
+
self,
|
|
137
|
+
exc_type: type[BaseException] | None,
|
|
138
|
+
exc: BaseException | None,
|
|
139
|
+
tb: types.TracebackType | None,
|
|
140
|
+
) -> None:
|
|
141
|
+
# Restore saved states
|
|
142
|
+
if self._py_state is not None:
|
|
143
|
+
random.setstate(self._py_state)
|
|
144
|
+
np = _maybe_import_numpy()
|
|
145
|
+
if np is not None and self._np_state is not None: # pragma: no branch
|
|
146
|
+
np.random.set_state(self._np_state)
|
|
147
|
+
t = _maybe_import_torch()
|
|
148
|
+
if t is not None and self._torch_cpu_state is not None:
|
|
149
|
+
t.set_rng_state(self._torch_cpu_state)
|
|
150
|
+
if (
|
|
151
|
+
hasattr(t, "cuda") and self._torch_cuda_states is not None and t.cuda.is_available()
|
|
152
|
+
): # pragma: no cover
|
|
153
|
+
t.cuda.set_rng_state_all(self._torch_cuda_states)
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
__all__ = [
|
|
158
|
+
"seed_everything",
|
|
159
|
+
"seed_from_env",
|
|
160
|
+
"temp_seed",
|
|
161
|
+
]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nervecode
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Intrinsic surprise scoring for PyTorch via statistical coding.
|
|
5
|
+
Project-URL: Homepage, https://gitlab.com/domezsolt/nervecode
|
|
6
|
+
Project-URL: Repository, https://gitlab.com/domezsolt/nervecode
|
|
7
|
+
Author: Zsolt Döme
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Nervecode Maintainers
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: coding,ml,pytorch,research,surprise
|
|
32
|
+
Requires-Python: >=3.10
|
|
33
|
+
Requires-Dist: torch>=2.0
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
36
|
+
Requires-Dist: pre-commit>=3.6; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.3; extra == 'dev'
|
|
39
|
+
Provides-Extra: docs
|
|
40
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
41
|
+
Requires-Dist: mkdocs>=1.5; extra == 'docs'
|
|
42
|
+
Provides-Extra: logging
|
|
43
|
+
Requires-Dist: loguru>=0.7; extra == 'logging'
|
|
44
|
+
Requires-Dist: rich>=13; extra == 'logging'
|
|
45
|
+
Provides-Extra: viz
|
|
46
|
+
Requires-Dist: matplotlib>=3.7; extra == 'viz'
|
|
47
|
+
Requires-Dist: seaborn>=0.13; extra == 'viz'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# Nervecode Docs
|
|
51
|
+
|
|
52
|
+
This directory will contain documentation for the Nervecode project.
|
|
53
|
+
|
|
54
|
+
## Developer Setup
|
|
55
|
+
|
|
56
|
+
- Install dev tools (in your virtualenv): `pip install -e .[dev]`
|
|
57
|
+
- Install git hooks: `pre-commit install`
|
|
58
|
+
- Run on all files once: `pre-commit run --all-files`
|
|
59
|
+
|
|
60
|
+
Included hooks:
|
|
61
|
+
- Formatting: `ruff-format`
|
|
62
|
+
- Linting and import sorting: `ruff` (with `--fix`)
|
|
63
|
+
- Type-checking: `mypy`
|
|
64
|
+
|
|
65
|
+
## Tests
|
|
66
|
+
|
|
67
|
+
- Unit tests: `pytest tests/unit` (fast correctness checks)
|
|
68
|
+
- Integration tests: `pytest tests/integration` (heavier, cross-module)
|
|
69
|
+
- Smoke tests: `pytest tests/smoke` (repo wiring and API surface)
|
|
70
|
+
|
|
71
|
+
### Deterministic runs
|
|
72
|
+
|
|
73
|
+
- Tests auto-seed RNGs per test using `NERVECODE_SEED` (default: `1234`).
|
|
74
|
+
- You can control reproducibility in your own scripts via:
|
|
75
|
+
```python
|
|
76
|
+
from nervecode.utils.seed import seed_everything, seed_from_env
|
|
77
|
+
seed_everything(seed_from_env())
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Performance Notes
|
|
81
|
+
|
|
82
|
+
- Overhead estimates and guidance for pooled Conv2d coding: see `docs/overhead.md`.
|
|
83
|
+
- Scaling and tradeoffs for layer selection and coding dimension: see `docs/scaling.md`.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
nervecode/__init__.py,sha256=xPUsGwV4JD71a5lClC6TqiOzEVWkTdwh8RRtaz53kNE,17734
|
|
2
|
+
nervecode/_version.py,sha256=MtrcXrZW_diNtg4lJtIVD5xrp0F8fhI_Q-Y-TLVm3ws,280
|
|
3
|
+
nervecode/core/__init__.py,sha256=MG6Q-13HOQ8HeN6CsisffNqUOsnCDywiUFHKzgJHFVQ,497
|
|
4
|
+
nervecode/core/assignment.py,sha256=wS8_I9Exb63dg1VAm6OP8QgUhDxRT2hWr_aHhp81z54,7080
|
|
5
|
+
nervecode/core/codebook.py,sha256=M6KaE71w5lQE3QdgCzwnRa6_trLebrDppnYQFP1ih6Y,7327
|
|
6
|
+
nervecode/core/shapes.py,sha256=wBjGh_Gk4Xt6nITsYJS0wf-v-WR7YFSkzI-lhUk2OL0,3612
|
|
7
|
+
nervecode/core/temperature.py,sha256=kBL99jxRFjZe_oiCL-NzveTVCxHoDBmX8JfvtHjePIY,7930
|
|
8
|
+
nervecode/core/trace.py,sha256=EyTlthcaCDDKamtLhcC35sESHt8LauUKZ2exquAmwkE,6936
|
|
9
|
+
nervecode/core/types.py,sha256=YJylBQiqICQCjU4Y_DfmVbvIl8yCXtLa_Dcedmne7cM,4805
|
|
10
|
+
nervecode/integration/__init__.py,sha256=eDP_VIlczERiMmIxaggtzvsDsbamI5WZWIlG-R0VJJM,243
|
|
11
|
+
nervecode/layers/__init__.py,sha256=DRYdTi2uSlp9m1wq8-Zbphm6c0PgwDaIsZWsCHdRPeM,374
|
|
12
|
+
nervecode/layers/base.py,sha256=9QOqCpa926EdotVhRp6apLZyrBApGDtlik_d4TVf4tg,12161
|
|
13
|
+
nervecode/layers/conv.py,sha256=ROKyq1bMbjwmltRwHN5oMh3ljnO_CsIs4rPU9c-QteI,7095
|
|
14
|
+
nervecode/layers/linear.py,sha256=YXX-0iNQ0r05ExD4JPkR3R2FJZsqPHJtfDB5SFwKLsQ,7383
|
|
15
|
+
nervecode/layers/reducers.py,sha256=7PN2ZO2hsJr5aXQye3d03nvM0fXY40uYd5TCMYwg53A,2879
|
|
16
|
+
nervecode/layers/wrap.py,sha256=UEhkFLw8U54ZLl0BjrfsZiMH1_7nlQQLAcWhhbEIHb0,7928
|
|
17
|
+
nervecode/scoring/__init__.py,sha256=ULUQbzb51OpakpLC_o8Ra6DC6CflmuxM-t3GmI0IWuU,583
|
|
18
|
+
nervecode/scoring/aggregator.py,sha256=cSv8vfpgRWfWExJIQ6bPqHbjMu_uCJCnNnW2Gd8Cb8Y,13297
|
|
19
|
+
nervecode/scoring/calibrator.py,sha256=-Wm6te9XzpTYX0uLV_qBgEHSfcM403Ilw_4gmaWiRlg,16326
|
|
20
|
+
nervecode/scoring/types.py,sha256=EmK0NO0muvjb5Ah272-g_y6Iuzc7WkCoZMolbSrvbxM,1087
|
|
21
|
+
nervecode/training/__init__.py,sha256=_YW_FlGgsTHNFaKm7frK9XemV7a-XWoeBcRSrePzadI,580
|
|
22
|
+
nervecode/training/diagnostics.py,sha256=0Peh4pOTnPSvJ4_UNXHKVPwf_dunOpq_vg7EjcCijRc,6606
|
|
23
|
+
nervecode/training/loss.py,sha256=rxreNiBu9LlxlHHdXhcH207o68VSGZRuBqQ6-xwTFwU,7278
|
|
24
|
+
nervecode/training/updaters.py,sha256=pSzbvjAacN8wTWXUboBRKrlgjoX4rX-3KquMAB7D1s4,7072
|
|
25
|
+
nervecode/utils/__init__.py,sha256=KUAQvrOQuAaTlPRmy3UuebKSO7FJZd5dF65s0fsfKRw,309
|
|
26
|
+
nervecode/utils/overhead.py,sha256=3hr3JwNKkDphPMOAs1Vkrq7CTRxR6X_qwfUx5nUDlxI,6606
|
|
27
|
+
nervecode/utils/seed.py,sha256=VMj2Vtr8OYEz0Gc0PJWdxow4He6Wv8tEoq9MgGb0mZk,5867
|
|
28
|
+
nervecode-0.1.0.dist-info/METADATA,sha256=oM2aV6Vsau0cjAq6XRzxilZ7c943q7zAocikHVbiPaQ,3294
|
|
29
|
+
nervecode-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
30
|
+
nervecode-0.1.0.dist-info/licenses/LICENSE,sha256=WP83ux1S7U3IyieW0mPA_Q1mpbJHK5ipX3_bniUAgYM,1079
|
|
31
|
+
nervecode-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nervecode Maintainers
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|