l0-python 0.3.0__py3-none-any.whl → 0.4.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.
- l0/calibration.py +80 -21
- {l0_python-0.3.0.dist-info → l0_python-0.4.0.dist-info}/METADATA +2 -2
- {l0_python-0.3.0.dist-info → l0_python-0.4.0.dist-info}/RECORD +6 -6
- {l0_python-0.3.0.dist-info → l0_python-0.4.0.dist-info}/WHEEL +0 -0
- {l0_python-0.3.0.dist-info → l0_python-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {l0_python-0.3.0.dist-info → l0_python-0.4.0.dist-info}/top_level.txt +0 -0
l0/calibration.py
CHANGED
|
@@ -30,10 +30,21 @@ class SparseCalibrationWeights(nn.Module):
|
|
|
30
30
|
Lower bound of stretched concrete distribution
|
|
31
31
|
zeta : float
|
|
32
32
|
Upper bound of stretched concrete distribution
|
|
33
|
-
init_keep_prob : float
|
|
34
|
-
Initial probability of keeping each weight active
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
init_keep_prob : float or array-like
|
|
34
|
+
Initial probability of keeping each weight active.
|
|
35
|
+
If float, all weights use the same probability.
|
|
36
|
+
If array, must have shape (n_features,)
|
|
37
|
+
init_weights : float, array-like, or None
|
|
38
|
+
Initial weight values (on original scale, not log).
|
|
39
|
+
If float, all weights initialized to this value.
|
|
40
|
+
If array, must have shape (n_features,).
|
|
41
|
+
If None, defaults to 1.0 for all weights.
|
|
42
|
+
log_weight_jitter_sd : float
|
|
43
|
+
Standard deviation of noise added to log weights at start of fit() to break symmetry.
|
|
44
|
+
Set to 0 to disable jitter. Default is 0.0 (no jitter).
|
|
45
|
+
log_alpha_jitter_sd : float
|
|
46
|
+
Standard deviation of noise added to log_alpha at initialization to break symmetry.
|
|
47
|
+
Set to 0 to disable jitter. Default is 0.01 (following Louizos et al.).
|
|
37
48
|
device : str or torch.device
|
|
38
49
|
Device to run computations on ('cpu' or 'cuda')
|
|
39
50
|
"""
|
|
@@ -44,8 +55,10 @@ class SparseCalibrationWeights(nn.Module):
|
|
|
44
55
|
beta: float = 2 / 3,
|
|
45
56
|
gamma: float = -0.1,
|
|
46
57
|
zeta: float = 1.1,
|
|
47
|
-
init_keep_prob: float = 0.5,
|
|
48
|
-
|
|
58
|
+
init_keep_prob: float | np.ndarray = 0.5,
|
|
59
|
+
init_weights: float | np.ndarray | None = None,
|
|
60
|
+
log_weight_jitter_sd: float = 0.0,
|
|
61
|
+
log_alpha_jitter_sd: float = 0.01,
|
|
49
62
|
device: str | torch.device = "cpu",
|
|
50
63
|
):
|
|
51
64
|
super().__init__()
|
|
@@ -53,25 +66,65 @@ class SparseCalibrationWeights(nn.Module):
|
|
|
53
66
|
self.beta = beta
|
|
54
67
|
self.gamma = gamma
|
|
55
68
|
self.zeta = zeta
|
|
69
|
+
self.log_weight_jitter_sd = log_weight_jitter_sd
|
|
70
|
+
self.log_alpha_jitter_sd = log_alpha_jitter_sd
|
|
56
71
|
self.device = torch.device(device)
|
|
57
72
|
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
73
|
+
# Initialize weights (on original scale)
|
|
74
|
+
if init_weights is None:
|
|
75
|
+
# Default: all weights start at 1.0
|
|
76
|
+
weight_values = torch.ones(n_features, device=self.device)
|
|
77
|
+
elif isinstance(init_weights, (int, float)):
|
|
78
|
+
# Scalar: all weights start at this value
|
|
79
|
+
weight_values = torch.full(
|
|
80
|
+
(n_features,), float(init_weights), device=self.device
|
|
65
81
|
)
|
|
66
|
-
|
|
82
|
+
else:
|
|
83
|
+
# Array: use provided values
|
|
84
|
+
weight_values = torch.tensor(
|
|
85
|
+
init_weights, dtype=torch.float32, device=self.device
|
|
86
|
+
)
|
|
87
|
+
if weight_values.shape != (n_features,):
|
|
88
|
+
raise ValueError(
|
|
89
|
+
f"init_weights array must have shape ({n_features},), "
|
|
90
|
+
f"got {weight_values.shape}"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Convert to log space to ensure positivity via exp transformation
|
|
94
|
+
# Add small epsilon to avoid log(0)
|
|
95
|
+
self.log_weight = nn.Parameter(torch.log(weight_values + 1e-8))
|
|
67
96
|
|
|
68
97
|
# L0 gate parameters
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
98
|
+
# Handle init_keep_prob as scalar or array
|
|
99
|
+
if isinstance(init_keep_prob, (int, float)):
|
|
100
|
+
# Scalar: broadcast to all features
|
|
101
|
+
keep_prob_values = torch.full(
|
|
102
|
+
(n_features,), float(init_keep_prob), device=self.device
|
|
73
103
|
)
|
|
74
|
-
|
|
104
|
+
else:
|
|
105
|
+
# Array: use provided values
|
|
106
|
+
keep_prob_values = torch.tensor(
|
|
107
|
+
init_keep_prob, dtype=torch.float32, device=self.device
|
|
108
|
+
)
|
|
109
|
+
if keep_prob_values.shape != (n_features,):
|
|
110
|
+
raise ValueError(
|
|
111
|
+
f"init_keep_prob array must have shape ({n_features},), "
|
|
112
|
+
f"got {keep_prob_values.shape}"
|
|
113
|
+
)
|
|
114
|
+
# Clip to valid probability range to avoid log(0) or log(inf)
|
|
115
|
+
keep_prob_values = keep_prob_values.clamp(1e-6, 1 - 1e-6)
|
|
116
|
+
|
|
117
|
+
# Convert probabilities to log_alpha
|
|
118
|
+
mu = torch.log(keep_prob_values / (1 - keep_prob_values))
|
|
119
|
+
# Add jitter to break symmetry (if specified)
|
|
120
|
+
if self.log_alpha_jitter_sd > 0:
|
|
121
|
+
jitter = (
|
|
122
|
+
torch.randn(n_features, device=self.device)
|
|
123
|
+
* self.log_alpha_jitter_sd
|
|
124
|
+
)
|
|
125
|
+
self.log_alpha = nn.Parameter(mu + jitter)
|
|
126
|
+
else:
|
|
127
|
+
self.log_alpha = nn.Parameter(mu)
|
|
75
128
|
|
|
76
129
|
# Cache for sparse tensor conversion
|
|
77
130
|
self._cached_M_torch: torch.sparse.Tensor | None = None
|
|
@@ -312,8 +365,14 @@ class SparseCalibrationWeights(nn.Module):
|
|
|
312
365
|
# No grouping - all targets weighted equally
|
|
313
366
|
group_weights = torch.ones_like(y)
|
|
314
367
|
|
|
315
|
-
#
|
|
316
|
-
|
|
368
|
+
# Add jitter to weights to break symmetry (if jitter_sd > 0)
|
|
369
|
+
if self.log_weight_jitter_sd > 0:
|
|
370
|
+
with torch.no_grad():
|
|
371
|
+
jitter = (
|
|
372
|
+
torch.randn_like(self.log_weight)
|
|
373
|
+
* self.log_weight_jitter_sd
|
|
374
|
+
)
|
|
375
|
+
self.log_weight.data += jitter
|
|
317
376
|
|
|
318
377
|
# Setup optimizer
|
|
319
378
|
optimizer = torch.optim.Adam([self.log_weight, self.log_alpha], lr=lr)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: l0-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: L0 regularization for sparse neural networks and intelligent sampling
|
|
5
5
|
Author-email: PolicyEngine <hello@policyengine.org>
|
|
6
6
|
License: MIT License
|
|
@@ -36,7 +36,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
36
36
|
Classifier: Programming Language :: Python :: 3
|
|
37
37
|
Classifier: Programming Language :: Python :: 3.13
|
|
38
38
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
39
|
-
Requires-Python: >=3.
|
|
39
|
+
Requires-Python: >=3.11
|
|
40
40
|
Description-Content-Type: text/markdown
|
|
41
41
|
License-File: LICENSE
|
|
42
42
|
Requires-Dist: torch>=2.0.0
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
l0/__init__.py,sha256=ezGVLGbdU_jAElAJSdLKjSWCnZRILAZi8qMBPjcHwQc,1192
|
|
2
|
-
l0/calibration.py,sha256=
|
|
2
|
+
l0/calibration.py,sha256=EnIhQPkC6yvRp0-o1qG3SCVUp6pIqwkqkx3DX3uWdG0,17838
|
|
3
3
|
l0/distributions.py,sha256=GvVoDasdxoDlPPdzt33lFzkuJgQsfkEn9e-abxru3nM,6325
|
|
4
4
|
l0/gates.py,sha256=54OORMg9qSsdbIyzYIL9t9CCHWsKbumSKl_d4-YFuNU,11443
|
|
5
5
|
l0/layers.py,sha256=j_DPEFdfUc37ojtoK2ufGzVYzZ_DwusqTcJXCVxZS68,13785
|
|
6
6
|
l0/penalties.py,sha256=okqXgX2eGUmg5prcDclicTQALPPPF9FA5eQP09V4GTE,9569
|
|
7
7
|
l0/sparse.py,sha256=UVpkrrJBnQ9iSNDoWK5F_sr43tQareWXzYHyMq_cKss,9726
|
|
8
|
-
l0_python-0.
|
|
9
|
-
l0_python-0.
|
|
10
|
-
l0_python-0.
|
|
11
|
-
l0_python-0.
|
|
12
|
-
l0_python-0.
|
|
8
|
+
l0_python-0.4.0.dist-info/licenses/LICENSE,sha256=LoyFJ8qmpwWPp5RmxFGHhdBxsemvp_BqGyiCgNAZHlk,1069
|
|
9
|
+
l0_python-0.4.0.dist-info/METADATA,sha256=tVMaa0UIafPSIv9V9WWoxga7x2xtIVMhQ_egiX3C3y4,6833
|
|
10
|
+
l0_python-0.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
l0_python-0.4.0.dist-info/top_level.txt,sha256=brP2SoElgmGhNJk-qRFEQZ5UE-d1e87Tr60hSSh8n34,3
|
|
12
|
+
l0_python-0.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|