diffract-core 0.2.1__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.
Files changed (193) hide show
  1. diffract/__init__.py +52 -0
  2. diffract/configs/fast_speed_without_disk.ini +48 -0
  3. diffract/configs/hybrid.ini +74 -0
  4. diffract/configs/sqlite.ini +62 -0
  5. diffract/containers.py +405 -0
  6. diffract/core/__init__.py +23 -0
  7. diffract/core/cache/__init__.py +24 -0
  8. diffract/core/cache/containers.py +93 -0
  9. diffract/core/cache/interface.py +117 -0
  10. diffract/core/cache/redis_manager.py +464 -0
  11. diffract/core/cache/simple_manager.py +478 -0
  12. diffract/core/compute/__init__.py +46 -0
  13. diffract/core/compute/config.py +48 -0
  14. diffract/core/compute/containers.py +81 -0
  15. diffract/core/compute/decorator.py +125 -0
  16. diffract/core/compute/exceptions.py +31 -0
  17. diffract/core/compute/execution/__init__.py +14 -0
  18. diffract/core/compute/execution/_types.py +70 -0
  19. diffract/core/compute/execution/aggregation.py +74 -0
  20. diffract/core/compute/execution/aggregation_runner.py +362 -0
  21. diffract/core/compute/execution/enums.py +38 -0
  22. diffract/core/compute/execution/executor.py +125 -0
  23. diffract/core/compute/execution/parameter_runner.py +125 -0
  24. diffract/core/compute/execution/restrictions.py +61 -0
  25. diffract/core/compute/execution/strategy.py +118 -0
  26. diffract/core/compute/execution/utils.py +112 -0
  27. diffract/core/compute/extensions/__init__.py +0 -0
  28. diffract/core/compute/extensions/power_law.py +1051 -0
  29. diffract/core/compute/extensions/rmt.py +150 -0
  30. diffract/core/compute/extensions/utils.py +36 -0
  31. diffract/core/compute/field_signature.py +183 -0
  32. diffract/core/compute/kernels/__init__.py +48 -0
  33. diffract/core/compute/kernels/alignment.py +106 -0
  34. diffract/core/compute/kernels/heavy_tailed.py +394 -0
  35. diffract/core/compute/kernels/marchenko_pastur.py +99 -0
  36. diffract/core/compute/kernels/mat_decomposition.py +101 -0
  37. diffract/core/compute/kernels/mat_properties.py +53 -0
  38. diffract/core/compute/kernels/model_quality.py +27 -0
  39. diffract/core/compute/kernels/norms.py +88 -0
  40. diffract/core/compute/kernels/ranks.py +35 -0
  41. diffract/core/compute/kernels/tracy_widom.py +36 -0
  42. diffract/core/compute/metadata.py +67 -0
  43. diffract/core/compute/registry.py +485 -0
  44. diffract/core/constants.py +147 -0
  45. diffract/core/data/__init__.py +32 -0
  46. diffract/core/data/interface.py +304 -0
  47. diffract/core/data/metadata/__init__.py +15 -0
  48. diffract/core/data/metadata/containers.py +60 -0
  49. diffract/core/data/metadata/interface.py +208 -0
  50. diffract/core/data/metadata/sqlite_index.py +604 -0
  51. diffract/core/data/nn/__init__.py +43 -0
  52. diffract/core/data/nn/aggregates/__init__.py +35 -0
  53. diffract/core/data/nn/aggregates/metadata.py +96 -0
  54. diffract/core/data/nn/aggregates/proxy.py +57 -0
  55. diffract/core/data/nn/aggregates/repository.py +87 -0
  56. diffract/core/data/nn/aggregates/view.py +307 -0
  57. diffract/core/data/nn/containers.py +86 -0
  58. diffract/core/data/nn/extractors/__init__.py +49 -0
  59. diffract/core/data/nn/extractors/base.py +300 -0
  60. diffract/core/data/nn/extractors/factory.py +234 -0
  61. diffract/core/data/nn/extractors/flax.py +112 -0
  62. diffract/core/data/nn/extractors/handlers/__init__.py +39 -0
  63. diffract/core/data/nn/extractors/handlers/base.py +110 -0
  64. diffract/core/data/nn/extractors/handlers/flax_handlers.py +71 -0
  65. diffract/core/data/nn/extractors/handlers/numpy_handlers.py +63 -0
  66. diffract/core/data/nn/extractors/handlers/onnx_handlers.py +67 -0
  67. diffract/core/data/nn/extractors/handlers/tensorflow_handlers.py +82 -0
  68. diffract/core/data/nn/extractors/handlers/torch_handlers.py +124 -0
  69. diffract/core/data/nn/extractors/interface.py +56 -0
  70. diffract/core/data/nn/extractors/numpy.py +94 -0
  71. diffract/core/data/nn/extractors/onnx.py +108 -0
  72. diffract/core/data/nn/extractors/tensorflow.py +99 -0
  73. diffract/core/data/nn/extractors/torch.py +204 -0
  74. diffract/core/data/nn/params/__init__.py +27 -0
  75. diffract/core/data/nn/params/interface.py +402 -0
  76. diffract/core/data/nn/params/metadata.py +110 -0
  77. diffract/core/data/nn/params/proxy.py +93 -0
  78. diffract/core/data/nn/params/repository.py +45 -0
  79. diffract/core/data/nn/params/schema.py +82 -0
  80. diffract/core/data/nn/params/view.py +393 -0
  81. diffract/core/data/proxy.py +246 -0
  82. diffract/core/data/repository.py +227 -0
  83. diffract/core/data/utils.py +33 -0
  84. diffract/core/data/view.py +389 -0
  85. diffract/core/export/__init__.py +27 -0
  86. diffract/core/export/containers.py +47 -0
  87. diffract/core/export/exporters.py +191 -0
  88. diffract/core/export/formatters/__init__.py +23 -0
  89. diffract/core/export/formatters/base.py +68 -0
  90. diffract/core/export/formatters/dict_formatter.py +38 -0
  91. diffract/core/export/formatters/json_formatter.py +58 -0
  92. diffract/core/export/formatters/list_formatter.py +41 -0
  93. diffract/core/export/formatters/pandas_formatter.py +86 -0
  94. diffract/core/export/formatters/polars_formatter.py +86 -0
  95. diffract/core/export/formatters/registry.py +84 -0
  96. diffract/core/export/interface.py +105 -0
  97. diffract/core/parallel/__init__.py +21 -0
  98. diffract/core/parallel/containers.py +57 -0
  99. diffract/core/parallel/execution.py +91 -0
  100. diffract/core/parallel/runtime.py +91 -0
  101. diffract/core/storage/__init__.py +35 -0
  102. diffract/core/storage/base_manager.py +330 -0
  103. diffract/core/storage/containers.py +122 -0
  104. diffract/core/storage/hdf5_manager.py +856 -0
  105. diffract/core/storage/hybrid_manager.py +218 -0
  106. diffract/core/storage/interface.py +222 -0
  107. diffract/core/storage/metadata.py +89 -0
  108. diffract/core/storage/ram_manager.py +159 -0
  109. diffract/core/storage/sqlite_manager.py +1062 -0
  110. diffract/core/storage/zarr_manager.py +992 -0
  111. diffract/core/utils/__init__.py +45 -0
  112. diffract/core/utils/build.py +46 -0
  113. diffract/core/utils/exceptions.py +11 -0
  114. diffract/core/utils/hashing.py +90 -0
  115. diffract/core/utils/imports.py +292 -0
  116. diffract/core/utils/math.py +15 -0
  117. diffract/py.typed +0 -0
  118. diffract/session/__init__.py +24 -0
  119. diffract/session/errors.py +17 -0
  120. diffract/session/field_cache.py +216 -0
  121. diffract/session/namespaces/__init__.py +15 -0
  122. diffract/session/namespaces/compute/__init__.py +219 -0
  123. diffract/session/namespaces/models/__init__.py +282 -0
  124. diffract/session/namespaces/models/parameters/__init__.py +133 -0
  125. diffract/session/namespaces/models/parameters/meta_patcher.py +167 -0
  126. diffract/session/namespaces/results/__init__.py +378 -0
  127. diffract/session/namespaces/results/eraser.py +129 -0
  128. diffract/session/namespaces/results/injester.py +249 -0
  129. diffract/session/namespaces/utils/__init__.py +141 -0
  130. diffract/session/namespaces/utils/merger.py +295 -0
  131. diffract/session/namespaces/viz/__init__.py +91 -0
  132. diffract/session/namespaces/viz/_utils.py +14 -0
  133. diffract/session/namespaces/viz/box.py +207 -0
  134. diffract/session/namespaces/viz/grid.py +160 -0
  135. diffract/session/namespaces/viz/heatmap.py +164 -0
  136. diffract/session/namespaces/viz/scatter.py +202 -0
  137. diffract/session/namespaces/viz/sparkline.py +270 -0
  138. diffract/session/namespaces/viz/violin.py +212 -0
  139. diffract/session/session.py +260 -0
  140. diffract/session/utils.py +81 -0
  141. diffract/viz/__init__.py +42 -0
  142. diffract/viz/data/__init__.py +34 -0
  143. diffract/viz/data/detection.py +57 -0
  144. diffract/viz/data/extraction.py +117 -0
  145. diffract/viz/data/filtering.py +57 -0
  146. diffract/viz/data/ordering.py +129 -0
  147. diffract/viz/data/provider.py +99 -0
  148. diffract/viz/data/types.py +98 -0
  149. diffract/viz/plots/__init__.py +37 -0
  150. diffract/viz/plots/base/__init__.py +20 -0
  151. diffract/viz/plots/base/axis.py +219 -0
  152. diffract/viz/plots/base/coloraxis.py +133 -0
  153. diffract/viz/plots/base/configurator.py +18 -0
  154. diffract/viz/plots/base/jitter.py +368 -0
  155. diffract/viz/plots/base/line.py +197 -0
  156. diffract/viz/plots/base/marker.py +278 -0
  157. diffract/viz/plots/base/overlay.py +14 -0
  158. diffract/viz/plots/base/plot.py +110 -0
  159. diffract/viz/plots/base/update.py +50 -0
  160. diffract/viz/plots/boxplot.py +283 -0
  161. diffract/viz/plots/cluster.py +374 -0
  162. diffract/viz/plots/heatmap.py +168 -0
  163. diffract/viz/plots/scatter.py +233 -0
  164. diffract/viz/plots/sparkline.py +405 -0
  165. diffract/viz/plots/subplots/__init__.py +32 -0
  166. diffract/viz/plots/subplots/coloraxis.py +339 -0
  167. diffract/viz/plots/subplots/factory.py +713 -0
  168. diffract/viz/plots/subplots/grid.py +214 -0
  169. diffract/viz/plots/subplots/layout.py +370 -0
  170. diffract/viz/plots/subplots/spec.py +39 -0
  171. diffract/viz/plots/violin.py +298 -0
  172. diffract/viz/renderer.py +513 -0
  173. diffract/viz/styling/__init__.py +78 -0
  174. diffract/viz/styling/palettes/__init__.py +20 -0
  175. diffract/viz/styling/palettes/bundle.py +16 -0
  176. diffract/viz/styling/palettes/color.py +83 -0
  177. diffract/viz/styling/palettes/dashes.py +27 -0
  178. diffract/viz/styling/palettes/symbols.py +42 -0
  179. diffract/viz/styling/resolvers/__init__.py +11 -0
  180. diffract/viz/styling/resolvers/categorical.py +68 -0
  181. diffract/viz/styling/resolvers/color.py +77 -0
  182. diffract/viz/styling/resolvers/numeric.py +108 -0
  183. diffract/viz/styling/sources.py +27 -0
  184. diffract/viz/styling/theme/__init__.py +29 -0
  185. diffract/viz/styling/theme/applier.py +114 -0
  186. diffract/viz/styling/theme/components.py +66 -0
  187. diffract/viz/styling/theme/presets.py +58 -0
  188. diffract/viz/styling/theme/theme.py +36 -0
  189. diffract_core-0.2.1.dist-info/METADATA +530 -0
  190. diffract_core-0.2.1.dist-info/RECORD +193 -0
  191. diffract_core-0.2.1.dist-info/WHEEL +4 -0
  192. diffract_core-0.2.1.dist-info/licenses/LICENSE +201 -0
  193. diffract_core-0.2.1.dist-info/licenses/NOTICE +2 -0
@@ -0,0 +1,58 @@
1
+ from __future__ import annotations
2
+
3
+ from diffract.viz.styling.palettes import PaletteBundle
4
+ from diffract.viz.styling.palettes.color import DarkColorPalette
5
+
6
+ from .components import (
7
+ AxesStyle,
8
+ BackgroundStyle,
9
+ LayoutStyle,
10
+ LegendStyle,
11
+ TypographyStyle,
12
+ )
13
+ from .theme import Theme
14
+
15
+ DEFAULT_THEME = Theme()
16
+
17
+
18
+ DARK_THEME = Theme(
19
+ background=BackgroundStyle(
20
+ plot_bgcolor="#1e1e1e",
21
+ paper_bgcolor="#2d2d2d",
22
+ ),
23
+ axes=AxesStyle(
24
+ grid_color="#444444",
25
+ line_color="#666666",
26
+ mirror=False,
27
+ ),
28
+ legend=LegendStyle(
29
+ bgcolor="rgba(45,45,45,0.9)",
30
+ border_color="#666666",
31
+ ),
32
+ palettes=PaletteBundle(
33
+ color=DarkColorPalette(),
34
+ ),
35
+ )
36
+
37
+
38
+ MINIMAL_THEME = Theme(
39
+ layout=LayoutStyle(
40
+ margin={"l": 50, "r": 20, "t": 40, "b": 50},
41
+ ),
42
+ typography=TypographyStyle(
43
+ font_family="Arial",
44
+ title_font_size=14,
45
+ label_font_size=12,
46
+ tick_font_size=10,
47
+ ),
48
+ axes=AxesStyle(
49
+ show_grid=False,
50
+ show_line=False,
51
+ mirror=False,
52
+ ),
53
+ legend=LegendStyle(
54
+ bgcolor="rgba(255,255,255,0)",
55
+ border_color="rgba(0,0,0,0)",
56
+ border_width=0,
57
+ ),
58
+ )
@@ -0,0 +1,36 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+
5
+ from diffract.viz.styling.palettes import PaletteBundle
6
+
7
+ from .components import (
8
+ AxesStyle,
9
+ BackgroundStyle,
10
+ ColorbarStyle,
11
+ LayoutStyle,
12
+ LegendStyle,
13
+ TypographyStyle,
14
+ )
15
+
16
+
17
+ @dataclass
18
+ class Theme:
19
+ """Complete theme configuration with composition.
20
+
21
+ Theme provides figure-level styling and palette configuration.
22
+ Explicit user settings on Plot/Configurator fields take precedence.
23
+
24
+ Example:
25
+ >>> from diffract.viz.styling.theme import Theme, DARK_THEME
26
+ >>> plot = BoxPlot(x=FieldRef("model"), y=FieldRef("accuracy"))
27
+ >>> fig = plot.render(session, theme=DARK_THEME)
28
+ """
29
+
30
+ layout: LayoutStyle = field(default_factory=LayoutStyle)
31
+ typography: TypographyStyle = field(default_factory=TypographyStyle)
32
+ background: BackgroundStyle = field(default_factory=BackgroundStyle)
33
+ axes: AxesStyle = field(default_factory=AxesStyle)
34
+ legend: LegendStyle = field(default_factory=LegendStyle)
35
+ colorbar: ColorbarStyle = field(default_factory=ColorbarStyle)
36
+ palettes: PaletteBundle = field(default_factory=PaletteBundle)
@@ -0,0 +1,530 @@
1
+ Metadata-Version: 2.4
2
+ Name: diffract-core
3
+ Version: 0.2.1
4
+ Summary: Spectral analysis of neural network weights and their evolution over training
5
+ Project-URL: Homepage, https://github.com/Risk-AI-Research/diffract
6
+ Project-URL: Documentation, https://risk-ai-research.github.io/diffract/
7
+ Project-URL: Repository, https://github.com/Risk-AI-Research/diffract
8
+ Project-URL: Issues, https://github.com/Risk-AI-Research/diffract/issues
9
+ Project-URL: Changelog, https://github.com/Risk-AI-Research/diffract/blob/main/CHANGELOG.md
10
+ Project-URL: Paper, https://openreview.net/forum?id=XBUHoiAGDE
11
+ Author: Risk AI Research
12
+ Maintainer-email: Nikita Borodin <borodinik.s@gmail.com>
13
+ License-Expression: Apache-2.0
14
+ License-File: LICENSE
15
+ License-File: NOTICE
16
+ Keywords: deep-learning,llm,neural-networks,random-matrix-theory,spectral-analysis
17
+ Classifier: Development Status :: 3 - Alpha
18
+ Classifier: Intended Audience :: Science/Research
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: <3.13,>=3.12
24
+ Requires-Dist: dependency-injector>=4.44.0
25
+ Requires-Dist: h5py>=3.9.0
26
+ Requires-Dist: numpy<3,>=1.26
27
+ Requires-Dist: ordered-set>=4.1.0
28
+ Requires-Dist: powerlaw<2,>=1.5.0
29
+ Requires-Dist: rootutils<2,>=1.0.7
30
+ Requires-Dist: scipy>=1.12.0
31
+ Requires-Dist: tqdm>=4.65.0
32
+ Requires-Dist: typing-extensions>=4.8.0
33
+ Provides-Extra: all
34
+ Requires-Dist: hydra-core>=1.3.0; extra == 'all'
35
+ Requires-Dist: kaleido>=0.2.1; extra == 'all'
36
+ Requires-Dist: omegaconf>=2.3.0; extra == 'all'
37
+ Requires-Dist: pandas>=2.1.0; extra == 'all'
38
+ Requires-Dist: plotly>=6.0.0; extra == 'all'
39
+ Requires-Dist: polars>=0.20.0; extra == 'all'
40
+ Requires-Dist: pyyaml>=6.0.1; extra == 'all'
41
+ Requires-Dist: taichi>=1.7.3; extra == 'all'
42
+ Requires-Dist: torch>=2.7.0; extra == 'all'
43
+ Provides-Extra: common
44
+ Requires-Dist: hydra-core>=1.3.0; extra == 'common'
45
+ Requires-Dist: kaleido>=0.2.1; extra == 'common'
46
+ Requires-Dist: omegaconf>=2.3.0; extra == 'common'
47
+ Requires-Dist: pandas>=2.1.0; extra == 'common'
48
+ Requires-Dist: plotly>=6.0.0; extra == 'common'
49
+ Requires-Dist: polars>=0.20.0; extra == 'common'
50
+ Requires-Dist: pyyaml>=6.0.1; extra == 'common'
51
+ Provides-Extra: dev
52
+ Requires-Dist: bandit[toml]>=1.7.5; extra == 'dev'
53
+ Requires-Dist: fsspec>=2024.2.0; extra == 'dev'
54
+ Requires-Dist: hydra-core>=1.3.0; extra == 'dev'
55
+ Requires-Dist: interrogate>=1.7.0; extra == 'dev'
56
+ Requires-Dist: kaleido>=0.2.1; extra == 'dev'
57
+ Requires-Dist: mypy>=1.10.1; extra == 'dev'
58
+ Requires-Dist: omegaconf>=2.3.0; extra == 'dev'
59
+ Requires-Dist: pandas>=2.1.0; extra == 'dev'
60
+ Requires-Dist: plotly>=6.0.0; extra == 'dev'
61
+ Requires-Dist: polars>=0.20.0; extra == 'dev'
62
+ Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
63
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
64
+ Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
65
+ Requires-Dist: pytest-timeout>=2.4.0; extra == 'dev'
66
+ Requires-Dist: pytest-watch>=4.2.0; extra == 'dev'
67
+ Requires-Dist: pytest-xdist>=3.3.0; extra == 'dev'
68
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
69
+ Requires-Dist: pyyaml>=6.0.1; extra == 'dev'
70
+ Requires-Dist: ruff>=0.9.0; extra == 'dev'
71
+ Requires-Dist: sybil>=6.0.0; extra == 'dev'
72
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
73
+ Requires-Dist: types-requests>=2.31.0; extra == 'dev'
74
+ Requires-Dist: zarr>=2.18.0; extra == 'dev'
75
+ Provides-Extra: docs
76
+ Requires-Dist: furo>=2024.8.0; extra == 'docs'
77
+ Requires-Dist: myst-parser>=2.0.0; extra == 'docs'
78
+ Requires-Dist: sphinx-autobuild>=2024.10.0; extra == 'docs'
79
+ Requires-Dist: sphinx-autodoc-typehints>=1.25.0; extra == 'docs'
80
+ Requires-Dist: sphinx-copybutton>=0.5.0; extra == 'docs'
81
+ Requires-Dist: sphinx-design>=0.6.0; extra == 'docs'
82
+ Requires-Dist: sphinx>=7.0.0; extra == 'docs'
83
+ Requires-Dist: sphinxext-opengraph>=0.9.0; extra == 'docs'
84
+ Provides-Extra: flax
85
+ Requires-Dist: flax>=0.10.0; extra == 'flax'
86
+ Provides-Extra: frameworks
87
+ Requires-Dist: flax>=0.10.0; extra == 'frameworks'
88
+ Requires-Dist: onnx>=1.16.0; extra == 'frameworks'
89
+ Requires-Dist: tensorflow>=2.16.0; extra == 'frameworks'
90
+ Provides-Extra: notebooks
91
+ Requires-Dist: einops>=0.7.0; extra == 'notebooks'
92
+ Requires-Dist: ipywidgets>=8.1.0; extra == 'notebooks'
93
+ Requires-Dist: jupyter>=1.0.0; extra == 'notebooks'
94
+ Requires-Dist: matplotlib>=3.8.0; extra == 'notebooks'
95
+ Requires-Dist: safetensors>=0.4.0; extra == 'notebooks'
96
+ Provides-Extra: onnx
97
+ Requires-Dist: onnx>=1.16.0; extra == 'onnx'
98
+ Provides-Extra: pandas
99
+ Requires-Dist: pandas>=2.1.0; extra == 'pandas'
100
+ Provides-Extra: polars
101
+ Requires-Dist: polars>=0.20.0; extra == 'polars'
102
+ Provides-Extra: redis
103
+ Requires-Dist: redis>=5.1.0; extra == 'redis'
104
+ Provides-Extra: taichi
105
+ Requires-Dist: taichi>=1.7.3; extra == 'taichi'
106
+ Provides-Extra: tensorflow
107
+ Requires-Dist: tensorflow>=2.16.0; extra == 'tensorflow'
108
+ Provides-Extra: torch
109
+ Requires-Dist: torch>=2.7.0; extra == 'torch'
110
+ Provides-Extra: viz
111
+ Requires-Dist: hydra-core>=1.3.0; extra == 'viz'
112
+ Requires-Dist: kaleido>=0.2.1; extra == 'viz'
113
+ Requires-Dist: omegaconf>=2.3.0; extra == 'viz'
114
+ Requires-Dist: plotly>=6.0.0; extra == 'viz'
115
+ Requires-Dist: pyyaml>=6.0.1; extra == 'viz'
116
+ Provides-Extra: zarr
117
+ Requires-Dist: fsspec>=2024.2.0; extra == 'zarr'
118
+ Requires-Dist: s3fs>=2024.2.0; extra == 'zarr'
119
+ Requires-Dist: zarr>=3.0.0; extra == 'zarr'
120
+ Description-Content-Type: text/markdown
121
+
122
+ # Diffract: Deep Neural Network Weight Analysis Library
123
+
124
+ [![CI](https://github.com/Risk-AI-Research/diffract/actions/workflows/ci.yml/badge.svg)](https://github.com/Risk-AI-Research/diffract/actions/workflows/ci.yml)
125
+ [![PyPI](https://img.shields.io/pypi/v/diffract-core)](https://pypi.org/project/diffract-core/)
126
+ [![Python](https://img.shields.io/pypi/pyversions/diffract-core)](https://pypi.org/project/diffract-core/)
127
+ [![Docs](https://img.shields.io/badge/docs-github.io-blue)](https://risk-ai-research.github.io/diffract/)
128
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
129
+
130
+ Official library of ["Diffract: Spectral View of LLM Domain Adaptation"](https://openreview.net/forum?id=XBUHoiAGDE)
131
+ (**ICML 2026 Oral**).
132
+
133
+ Diffract is a Python package for analyzing deep neural network weights and tracking
134
+ their evolution over the course of training.
135
+
136
+ With a straightforward API and a functional design centered on reusable _kernels_,
137
+ Diffract automatically resolves dependencies, builds computation graphs, and schedules
138
+ calculations. Parameters and results are persisted across sessions.
139
+
140
+ It accepts models from PyTorch, TensorFlow, Flax, and ONNX, as well as plain
141
+ dictionaries of NumPy weight matrices.
142
+
143
+ <br>
144
+
145
+ ## 🚀 Quick Start
146
+
147
+ Diffract requires Python 3.12. The core package installs without any deep
148
+ learning framework; heavy dependencies are opt-in extras:
149
+
150
+ ```bash
151
+ pip install diffract-core # core: extraction, spectral metrics, storage
152
+ pip install "diffract-core[torch]" # + PyTorch model loading (CUDA wheels on Linux, ~2-3 GB)
153
+ pip install "diffract-core[viz]" # + Plotly visualization and YAML plot configs
154
+ pip install "diffract-core[taichi]" # + accelerated heavy-tailed fits and p-value kernels
155
+ pip install "diffract-core[all]" # torch + viz + taichi + pandas/polars exports
156
+ ```
157
+
158
+ Further extras: `frameworks` (TensorFlow, Flax, ONNX), `pandas` / `polars`
159
+ (DataFrame exports), `zarr` (cloud storage), `redis` (shared cache),
160
+ `notebooks` (tooling for the example notebooks). The quotes around
161
+ `"diffract-core[...]"` matter in zsh.
162
+
163
+ ### Development Install
164
+
165
+ ```bash
166
+ # Install uv if you haven't already
167
+ curl -LsSf https://astral.sh/uv/install.sh | sh
168
+
169
+ # Clone and install (uv provisions Python 3.12 automatically)
170
+ git clone https://github.com/Risk-AI-Research/diffract.git
171
+ cd diffract
172
+ uv sync --extra dev --extra torch
173
+ ```
174
+
175
+ Then use it in your code:
176
+
177
+ ```python
178
+ from diffract import Session
179
+
180
+ # Quick experiments (in-memory, no persistence)
181
+ session = Session(profile="ram")
182
+
183
+ # Persistent local storage (SQLite in .diffract/)
184
+ session = Session(profile="local")
185
+
186
+ with session:
187
+ session.models.add(torch_model, model_id="bert-base")
188
+ session.compute.apply("frob_norm", "stable_rank", "log_norm")
189
+ # per-parameter metrics
190
+ metrics_df = session.results.export_metrics(
191
+ "frob_norm", "stable_rank", export_format="pandas"
192
+ )
193
+ # model-level aggregates
194
+ aggregates_df = session.results.export_aggregates(
195
+ "log_norm", export_format="pandas"
196
+ )
197
+ ```
198
+
199
+ Check out
200
+ [example notebooks](https://github.com/Risk-AI-Research/diffract/tree/main/examples) and
201
+ [plot configurations](https://github.com/Risk-AI-Research/diffract/tree/main/examples/configs)
202
+ for more examples. The
203
+ [notebooks](https://github.com/Risk-AI-Research/diffract/tree/main/notebooks) directory
204
+ contains `compare_two_checkpoints.ipynb`, an end-to-end walkthrough.
205
+
206
+ <br>
207
+
208
+ ## 🤔 Why Diffract?
209
+
210
+ Neural networks often feel like black boxes. Diffract provides tools to analyze their
211
+ internal structure:
212
+
213
+ - **Training Insights**: Track how weights evolve across training epochs.
214
+ - **Architecture Analysis**: Compare different model architectures objectively.
215
+ - **Initialization Studies**: Evaluate the impact of initialization methods.
216
+ - **Spectral Analysis**: Compute empirical spectral distributions, ranks, and norms.
217
+ - **Heavy-Tailed Distributions**: Detect power-law and exponential tails in weight
218
+ spectra.
219
+
220
+ <br>
221
+
222
+ ## 🔑 Key Features
223
+
224
+ - **Session-based API**: Simple `models.add`, `compute.apply`, and
225
+ `results.export_metrics` workflow.
226
+
227
+ - **Kernels**: Reusable functions that compute model characteristics—ranks, norms,
228
+ spectral properties—stored as named _fields_ on each parameter. Dependencies are
229
+ resolved automatically.
230
+
231
+ - **Persistent Storage**: Parameters and results survive between sessions. Supports
232
+ HDF5, SQLite, Zarr, and hybrid backends.
233
+
234
+ - **Kernel Apply Levels**: Kernels can work at multiple levels:
235
+ - **PARAMETER** - Operate on individual weight matrices.
236
+ - **IN_MODEL** - Aggregate within a single model.
237
+ - **CROSS_MODEL** - Compare or aggregate across models.
238
+
239
+ - **Built-in Visualization**: Publication-ready Plotly plots with theming support.
240
+
241
+ - **Export Formats**: Get results as `pandas`, `polars`, `dict`, `json`, or `list`.
242
+
243
+ <br>
244
+
245
+ ## ✨ Core Functionality
246
+
247
+ ### Adding Models
248
+
249
+ Add models from various frameworks to a session:
250
+
251
+ <!-- skip: next -->
252
+
253
+ ```python
254
+ from diffract import Session
255
+
256
+ session = Session()
257
+
258
+ with session:
259
+ session.models.add(torch_model) # torch.nn.Module
260
+ session.models.add(torch_state_dict, model_id="checkpoint") # Dict[str, torch.Tensor]
261
+ session.models.add(numpy_weights, model_id="raw-weights") # Dict[str, np.ndarray]
262
+ session.models.add(onnx_model, model_id="onnx-model") # onnx.ModelProto
263
+ session.models.add(flax_model, model_id="flax-model") # flax.linen.Module
264
+ session.models.add(tf_model, model_id="tf-model") # TensorFlow model
265
+ ```
266
+
267
+ ### Computing Metrics
268
+
269
+ Dependencies are resolved automatically:
270
+
271
+ ```python
272
+ session.compute.apply("frob_norm", "stable_rank")
273
+ session.compute.apply("pl_ks") # has many dependencies—all resolved automatically
274
+ ```
275
+
276
+ ### Filtering Parameters
277
+
278
+ Filter computations by model, parameter type, or name:
279
+
280
+ ```python
281
+ from diffract import ParameterOverrides, ParameterType, Session
282
+
283
+ session = Session()
284
+
285
+ # Assign custom types and names during extraction
286
+ overrides = {
287
+ "model.layers.0.attn.q_proj.weight": ParameterOverrides(name="q", ptype="attn"),
288
+ "model.layers.0.attn.k_proj.weight": ParameterOverrides(name="k", ptype="attn"),
289
+ "model.layers.0.mlp.fc1.weight": ParameterOverrides(ptype="mlp"),
290
+ }
291
+
292
+ with session:
293
+ session.models.add(model, model_id="gpt", parameter_overrides=overrides)
294
+ session.compute.apply("frob_norm")
295
+
296
+ # Scope work to a subset with session.filter(...)
297
+ gpt = session.filter(model_ids=["gpt"])
298
+ with gpt:
299
+ gpt.compute.apply("frob_norm")
300
+
301
+ attn = session.filter(param_types=[ParameterType.from_string("attn")])
302
+ with attn:
303
+ attn.results.export_metrics("frob_norm")
304
+ ```
305
+
306
+ ### Retrieving Results
307
+
308
+ Export results in various formats (`pandas`, `polars`, `dict`, `json`, or `list`):
309
+
310
+ ```python
311
+ scalars_df = session.results.export_metrics("stable_rank", export_format="pandas")
312
+ aggregates_df = session.results.export_aggregates(
313
+ "stable_rank", export_format="pandas"
314
+ )
315
+
316
+ # Other formats work the same way
317
+ results = session.results.export_metrics("stable_rank", export_format="polars")
318
+ results = session.results.export_metrics("stable_rank", export_format="dict")
319
+ results = session.results.export_metrics("stable_rank", export_format="json")
320
+ results = session.results.export_metrics("stable_rank", export_format="list")
321
+ ```
322
+
323
+ ### Visualization
324
+
325
+ Create publication-ready Plotly plots:
326
+
327
+ <!-- skip: next -->
328
+
329
+ ```python
330
+ from diffract.viz import DEFAULT_THEME
331
+
332
+ # Ergonomic helpers on session.viz accept field names directly
333
+ session.viz.box(y="stable_rank", x="model_id", theme=DEFAULT_THEME).show()
334
+ session.viz.scatter(x="frob_norm", y="stable_rank").show()
335
+ ```
336
+
337
+ ### YAML-Driven Plotting
338
+
339
+ Define complex visualizations via Hydra configs:
340
+
341
+ <!-- skip: next -->
342
+
343
+ ```python
344
+ session.viz.draw(config_path="examples/configs/boxplot_stable_rank.yaml").show()
345
+ ```
346
+
347
+ ### Kernel Configuration
348
+
349
+ List and configure kernels at runtime:
350
+
351
+ ```python
352
+ session.compute.list_available_kernels(verbose=True)
353
+ session.compute.list_available_metrics(verbose=True)
354
+ session.compute.configure_kernel("hard_rank", threshold=1e-6)
355
+ ```
356
+
357
+ ### Session Management
358
+
359
+ Parameters and results stay available whenever the session is reopened. `Session()`
360
+ defaults to the in-memory `ram` profile; pick a persistent profile such as `local` or
361
+ `hybrid` to keep data across separate runs:
362
+
363
+ ```python
364
+ from diffract import Session
365
+
366
+ session = Session() # in-memory; use profile="local" to persist across runs
367
+
368
+ # Add models and compute
369
+ with session:
370
+ session.models.add(model, model_id="my-model")
371
+ session.compute.apply("frob_norm")
372
+
373
+ # Reopen the session: earlier results are still there
374
+ with session:
375
+ results = session.results.export_metrics("frob_norm", export_format="pandas")
376
+ session.models.list()
377
+ session.models.erase("my-model")
378
+ ```
379
+
380
+ ### Custom Kernels
381
+
382
+ Implement your own research metrics using the session kernel decorator:
383
+
384
+ ```python
385
+ from diffract import Session
386
+
387
+ session = Session()
388
+
389
+ with session:
390
+ # Define and register a custom kernel
391
+ @session.compute.kernel()
392
+ def my_custom_metric(frob_norm: float, *, scaling_factor: float = 1.0) -> float:
393
+ """Custom metric that scales the Frobenius norm."""
394
+ return frob_norm * scaling_factor
395
+
396
+ session.models.add(my_model)
397
+ session.compute.configure_kernel("my_custom_metric", scaling_factor=2.0)
398
+ session.compute.apply("my_custom_metric")
399
+ ```
400
+
401
+ You can also override the registered name and output fields:
402
+
403
+ ```python
404
+ with session:
405
+ @session.compute.kernel(name="scaled_metric", produce_fields=["scaled_result"])
406
+ def custom_analysis(frob_norm: float, stable_rank: float, *, weight: float = 0.5) -> float:
407
+ """Custom analysis combining multiple metrics."""
408
+ return weight * frob_norm + (1 - weight) * stable_rank
409
+ ```
410
+
411
+ ### Available Kernels
412
+
413
+ Diffract includes kernels for norms, ranks, spectral analysis, heavy-tailed fits, and
414
+ more. Run `session.compute.list_available_kernels(verbose=True)` to list them all.
415
+
416
+ ### Merging Sessions
417
+
418
+ Merge parameters and results from another session:
419
+
420
+ <!-- skip: next -->
421
+
422
+ ```python
423
+ from diffract import Session
424
+
425
+ session1 = Session(config_path="config1.ini")
426
+ session2 = Session(config_path="config2.ini")
427
+
428
+ with session1:
429
+ session1.models.add(model1, model_id="model-a")
430
+ session1.compute.apply("frob_norm")
431
+
432
+ with session2:
433
+ session2.models.add(model2, model_id="model-b")
434
+ session2.utils.merge_other_session(session1, fields=["frob_norm"])
435
+ ```
436
+
437
+ ### Configuration
438
+
439
+ Diffract offers built-in **profiles** for common setups:
440
+
441
+ | Profile | Storage | Cache | Use case |
442
+ | -------- | ------------- | ---------- | --------------------------------- |
443
+ | `ram` | RAM | None | Quick experiments, no persistence |
444
+ | `local` | SQLite | Simple LRU | Local development, persistent |
445
+ | `hybrid` | SQLite + HDF5 | Simple LRU | Large models, optimized arrays |
446
+
447
+ ```python
448
+ from diffract import Session
449
+
450
+ # Use a profile (recommended for most users)
451
+ session = Session(profile="ram") # fast, temporary
452
+ session = Session(profile="local") # persistent, simple
453
+ session = Session(profile="hybrid") # persistent, optimized for large arrays
454
+
455
+ # Or use a custom config file for full control
456
+ session = Session(config_path="my_config.ini")
457
+ ```
458
+
459
+ **Tip**: Start with a profile, then switch to a config file when you need
460
+ reproducibility or custom settings.
461
+
462
+ #### Advanced Configuration
463
+
464
+ For production or reproducible experiments, use INI config files. See
465
+ `src/diffract/configs/` for examples:
466
+
467
+ ```ini
468
+ [storage]
469
+ backend = "sqlite"
470
+
471
+ [storage.sqlite]
472
+ path = "data/diffract.db"
473
+
474
+ [cache]
475
+ backend = "simple"
476
+
477
+ [parallel.thread_pool]
478
+ max_workers = 4
479
+ ```
480
+
481
+ #### Storage Backends
482
+
483
+ - **RAM**: In-memory (no persistence)
484
+ - **SQLite**: Lightweight database for metadata and arrays
485
+ - **HDF5**: Optimized for large numerical arrays with compression
486
+ - **Zarr**: Cloud-optimized array storage for large-scale data
487
+ - **Hybrid**: SQLite (metadata) + HDF5/Zarr (arrays)
488
+
489
+ #### Cache Backends
490
+
491
+ - **Simple**: In-memory LRU cache
492
+ - **Redis**: Distributed caching (requires `redis` extra)
493
+ - **None**: Disable caching
494
+
495
+ <br>
496
+
497
+ ## 📚 Documentation
498
+
499
+ The documentation site is sourced from `docs/` and built with Sphinx + MyST. Install the
500
+ tooling via `uv sync --extra docs` and run `make docs` to render the HTML locally.
501
+
502
+ <br>
503
+
504
+ ## 📝 Citation
505
+
506
+ If you use Diffract or build on the paper, please cite:
507
+
508
+ ```bibtex
509
+ @inproceedings{borodin2026diffract,
510
+ title = {Diffract: Spectral View of {LLM} Domain Adaptation},
511
+ author = {Nikita Borodin and Maria Krylova and Artem Zabolotnyi and Dmitry Aspisov and Egor Shikov and Nikita Tyuplyaev and Oleg Travkin and Roman Alferov and Dmitry Vinichenko},
512
+ booktitle = {Forty-third International Conference on Machine Learning},
513
+ year = {2026},
514
+ url = {https://openreview.net/forum?id=XBUHoiAGDE}
515
+ }
516
+ ```
517
+
518
+ <br>
519
+
520
+ ## ❤️ Contributions
521
+
522
+ Contributions are welcome! Fork the repo, create a feature branch, and submit a PR. Use
523
+ `make lint` and `make test` to validate your changes.
524
+
525
+ <br>
526
+
527
+ ## 📄 License
528
+
529
+ Licensed under the Apache License 2.0 — see [LICENSE](LICENSE). Copyright 2026 Risk AI
530
+ Research.