nous 0.2.0__tar.gz → 0.5.1__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.
- nous-0.5.1/PKG-INFO +336 -0
- nous-0.5.1/README.md +275 -0
- {nous-0.2.0 → nous-0.5.1}/nous/__init__.py +23 -4
- {nous-0.2.0 → nous-0.5.1}/nous/explain/loo.py +16 -2
- {nous-0.2.0 → nous-0.5.1}/nous/explain/traces.py +11 -0
- {nous-0.2.0 → nous-0.5.1}/nous/export/__init__.py +1 -1
- {nous-0.2.0 → nous-0.5.1}/nous/export/numpy_infer.py +211 -35
- {nous-0.2.0 → nous-0.5.1}/nous/facts.py +50 -0
- {nous-0.2.0 → nous-0.5.1}/nous/model.py +44 -16
- nous-0.5.1/nous/optim/__init__.py +13 -0
- nous-0.5.1/nous/optim/base.py +47 -0
- nous-0.5.1/nous/optim/beta_ng.py +214 -0
- nous-0.5.1/nous/optim/extragrad_trust.py +175 -0
- nous-0.5.1/nous/optim/factory.py +77 -0
- nous-0.5.1/nous/optim/mirror_radam.py +190 -0
- nous-0.5.1/nous/optim/sam_gates.py +229 -0
- nous-0.5.1/nous/rules/__init__.py +30 -0
- nous-0.5.1/nous/rules/gaters.py +212 -0
- nous-0.5.1/nous/rules/soft_fact.py +132 -0
- nous-0.5.1/nous/utils/__init__.py +4 -0
- nous-0.5.1/nous/utils/calibrators.py +31 -0
- nous-0.5.1/nous/version.py +1 -0
- nous-0.5.1/nous.egg-info/PKG-INFO +336 -0
- {nous-0.2.0 → nous-0.5.1}/nous.egg-info/SOURCES.txt +15 -1
- {nous-0.2.0 → nous-0.5.1}/pyproject.toml +3 -3
- {nous-0.2.0 → nous-0.5.1}/setup.cfg +4 -4
- nous-0.5.1/tests/test_export_numpy_gaters.py +41 -0
- nous-0.5.1/tests/test_facts.py +26 -0
- {nous-0.2.0 → nous-0.5.1}/tests/test_model_forward.py +13 -1
- nous-0.5.1/tests/test_optim.py +180 -0
- nous-0.5.1/tests/test_rule_gaters.py +67 -0
- {nous-0.2.0 → nous-0.5.1}/tests/test_rules.py +12 -2
- nous-0.5.1/tests/test_utils.py +8 -0
- nous-0.2.0/PKG-INFO +0 -150
- nous-0.2.0/README.md +0 -89
- nous-0.2.0/nous/rules/__init__.py +0 -11
- nous-0.2.0/nous/utils/__init__.py +0 -3
- nous-0.2.0/nous/version.py +0 -1
- nous-0.2.0/nous.egg-info/PKG-INFO +0 -150
- nous-0.2.0/tests/test_facts.py +0 -16
- {nous-0.2.0 → nous-0.5.1}/LICENSE +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/data/__init__.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/data/california.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/data/wine.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/__init__.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/aggregator.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/cf.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/facts_desc.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/fidelity.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/generate.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/global_book.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/mse.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/pruning.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/stability.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/explain/utils.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/prototypes.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/rules/blocks.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/rules/fixed.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/rules/softmax.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/rules/sparse.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/training/__init__.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/training/evaluation.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/training/schedulers.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/training/train.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/types.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/utils/metrics.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous/utils/seed.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous.egg-info/dependency_links.txt +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous.egg-info/requires.txt +0 -0
- {nous-0.2.0 → nous-0.5.1}/nous.egg-info/top_level.txt +0 -0
- {nous-0.2.0 → nous-0.5.1}/tests/test_explain_loo.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/tests/test_export_numpy.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/tests/test_forward_explain.py +0 -0
- {nous-0.2.0 → nous-0.5.1}/tests/test_prototypes.py +0 -0
nous-0.5.1/PKG-INFO
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nous
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: Nous: A Neuro-Symbolic Library for Interpretable AI
|
|
5
|
+
Author-email: Islam Tlupov <tlupovislam@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025 Islam Tlupov
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Repository, https://github.com/EmotionEngineer/nous
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: Intended Audience :: Science/Research
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
36
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
37
|
+
Classifier: Typing :: Typed
|
|
38
|
+
Requires-Python: >=3.8
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
License-File: LICENSE
|
|
41
|
+
Requires-Dist: torch>=2.1
|
|
42
|
+
Requires-Dist: numpy>=1.22
|
|
43
|
+
Requires-Dist: pandas>=1.5
|
|
44
|
+
Requires-Dist: scikit-learn>=1.2
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
47
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
48
|
+
Requires-Dist: mypy>=1.5; extra == "dev"
|
|
49
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
50
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
51
|
+
Requires-Dist: matplotlib>=3.6; extra == "dev"
|
|
52
|
+
Requires-Dist: seaborn>=0.12; extra == "dev"
|
|
53
|
+
Requires-Dist: tqdm>=4.65; extra == "dev"
|
|
54
|
+
Requires-Dist: ucimlrepo>=0.0.5; extra == "dev"
|
|
55
|
+
Provides-Extra: examples
|
|
56
|
+
Requires-Dist: matplotlib>=3.6; extra == "examples"
|
|
57
|
+
Requires-Dist: seaborn>=0.12; extra == "examples"
|
|
58
|
+
Requires-Dist: tqdm>=4.65; extra == "examples"
|
|
59
|
+
Requires-Dist: ucimlrepo>=0.0.5; extra == "examples"
|
|
60
|
+
Dynamic: license-file
|
|
61
|
+
|
|
62
|
+
# Nous: A Neuro‑Symbolic Library for Interpretable AI
|
|
63
|
+
|
|
64
|
+
[](https://pypi.org/project/nous/)
|
|
65
|
+
[](https://opensource.org/licenses/MIT)
|
|
66
|
+
[](https://www.python.org/)
|
|
67
|
+
[](https://pytorch.org/)
|
|
68
|
+
[](https://github.com/EmotionEngineer/nous)
|
|
69
|
+
|
|
70
|
+
**Nous** (Greek: νοῦς, "mind") is a neuro‑symbolic deep learning library for building interpretable, causally transparent, and high‑performance models for classification and regression. It combines differentiable β‑facts with rule aggregation layers to produce human‑readable decision logic while retaining the benefits of gradient‑based optimization.
|
|
71
|
+
|
|
72
|
+
## 🚀 Key Features
|
|
73
|
+
|
|
74
|
+
- **Human‑Readable Explanations**. Get clear "IF-THEN" rules that explain predictions
|
|
75
|
+
- **Differentiable Rule Learning**. Train symbolic rules with gradient-based optimization
|
|
76
|
+
- **Faithful Interpretability**. Honest leave‑one‑out, counterfactuals, and minimal sufficient explanations
|
|
77
|
+
- **Zero‑Dependency Inference**. Export to pure NumPy for production deployment
|
|
78
|
+
- **Prototype‑Based Reasoning**. Classification by similarity to learned prototypes
|
|
79
|
+
- **Advanced Optimizers**. Specialized training for sparse, gated models
|
|
80
|
+
|
|
81
|
+
## 📦 Installation
|
|
82
|
+
|
|
83
|
+
**Stable release (PyPI)**
|
|
84
|
+
```bash
|
|
85
|
+
pip install nous
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Development version (GitHub)**
|
|
89
|
+
```bash
|
|
90
|
+
pip install "nous[dev,examples] @ git+https://github.com/EmotionEngineer/nous@main"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 🎯 Quick Start
|
|
94
|
+
|
|
95
|
+
### Training a Classification Model
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from nous import NousNet
|
|
99
|
+
import torch
|
|
100
|
+
|
|
101
|
+
# Initialize model
|
|
102
|
+
model = NousNet(
|
|
103
|
+
input_dim=10,
|
|
104
|
+
num_outputs=3,
|
|
105
|
+
task_type="classification",
|
|
106
|
+
num_facts=32,
|
|
107
|
+
rules_per_layer=(16, 8),
|
|
108
|
+
rule_selection_method="soft_fact",
|
|
109
|
+
use_prototypes=True
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Sample data
|
|
113
|
+
X = torch.randn(1000, 10)
|
|
114
|
+
y = torch.randint(0, 3, (1000,))
|
|
115
|
+
|
|
116
|
+
# Training
|
|
117
|
+
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3)
|
|
118
|
+
criterion = torch.nn.CrossEntropyLoss()
|
|
119
|
+
|
|
120
|
+
for epoch in range(100):
|
|
121
|
+
optimizer.zero_grad()
|
|
122
|
+
outputs = model(X)
|
|
123
|
+
loss = criterion(outputs, y)
|
|
124
|
+
loss.backward()
|
|
125
|
+
optimizer.step()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Generating Explanations
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from nous import generate_enhanced_explanation
|
|
132
|
+
|
|
133
|
+
# Explain a prediction
|
|
134
|
+
x_sample = X[0].numpy()
|
|
135
|
+
explanation = generate_enhanced_explanation(
|
|
136
|
+
model, x_sample, y_true=int(y[0].item()),
|
|
137
|
+
feature_names=[f"f{i}" for i in range(10)],
|
|
138
|
+
class_names=["A", "B", "C"]
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
print(explanation)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Export for Production
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from nous.export import export_numpy_inference, load_numpy_module
|
|
148
|
+
|
|
149
|
+
# Export to pure NumPy
|
|
150
|
+
export_numpy_inference(model, "nous_infer.py")
|
|
151
|
+
|
|
152
|
+
# Load and use in any environment
|
|
153
|
+
infer = load_numpy_module("nous_infer.py")
|
|
154
|
+
probs = infer.predict(X.numpy()[:5])
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 🏗️ Core Architecture
|
|
158
|
+
|
|
159
|
+
```mermaid
|
|
160
|
+
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#1a1a1a','primaryBorderColor':'#2c5f7c','lineColor':'#4a90a4','secondaryColor':'#fef5e7','tertiaryColor':'#f0f8ff','noteTextColor':'#1a1a1a','noteBkgColor':'#fffacd','textColor':'#1a1a1a'}}}%%
|
|
161
|
+
|
|
162
|
+
graph TB
|
|
163
|
+
%% Input Layer
|
|
164
|
+
INPUT["<b>📥 Input Layer</b><br/>x ∈ ℝᴰ<br/><i>Raw Features</i>"]:::inputStyle
|
|
165
|
+
|
|
166
|
+
%% Preprocessing
|
|
167
|
+
CALIB["<b>📊 Feature Calibrators</b><br/>Monotonic splines<br/>Feature scaling & normalization<br/><i>Optional preprocessing</i>"]:::preprocessStyle
|
|
168
|
+
|
|
169
|
+
%% Beta Facts
|
|
170
|
+
BETA["<b>🔷 Beta-Fact Layer</b><br/>βᵢ(x) = σ(kᵢ·(Lᵢx − Rᵢx − θᵢ))^νᵢ<br/>━━━━━━━━━━━━━━<br/>• k: sharpness parameter<br/>• ν: shape exponent<br/>• L,R: feature projections<br/>• θ: threshold bias<br/><i>N differentiable atoms ∈ [0,1]</i>"]:::factStyle
|
|
171
|
+
|
|
172
|
+
%% Rule Layer 1
|
|
173
|
+
RULE1["<b>⚙️ Rule Layer 1</b><br/>Combinator Logic<br/>━━━━━━━━━━━━━━<br/>• AND: ∏ᵢ βᵢ<br/>• OR: 1−∏ᵢ(1−βᵢ)<br/>• k-of-n: soft threshold<br/>• NOT: 1−β<br/><i>R₁ learned rules</i>"]:::ruleStyle
|
|
174
|
+
|
|
175
|
+
GATE1["<b>🚪 Gating 1</b><br/>Soft top-k selection<br/>Budget masking<br/><i>Sparsity control</i>"]:::gateStyle
|
|
176
|
+
|
|
177
|
+
AGG1["<b>∑ Aggregation 1</b><br/>Weighted sum<br/>Residual connections"]:::aggStyle
|
|
178
|
+
|
|
179
|
+
%% Rule Layer 2
|
|
180
|
+
RULE2["<b>⚙️ Rule Layer 2</b><br/>Higher-order combinations<br/>━━━━━━━━━━━━━━<br/>Rules over rules<br/><i>R₂ meta-rules</i>"]:::ruleStyle
|
|
181
|
+
|
|
182
|
+
GATE2["<b>🚪 Gating 2</b><br/>Hierarchical pruning<br/>Confidence weighting"]:::gateStyle
|
|
183
|
+
|
|
184
|
+
AGG2["<b>∑ Aggregation 2</b><br/>Final rule scores<br/>Symbolic → numeric"]:::aggStyle
|
|
185
|
+
|
|
186
|
+
%% Output Heads
|
|
187
|
+
HEAD_LINEAR["<b>📐 Linear Head</b><br/>W·r + b<br/><i>Regression output</i>"]:::headStyle
|
|
188
|
+
|
|
189
|
+
HEAD_PROTO["<b>🎯 Prototype Head</b><br/>Similarity to prototypes<br/>━━━━━━━━━━━━━━<br/>d(r, pₖ) = ||r − pₖ||₂<br/>L2 normalization<br/><i>Classification via distance</i>"]:::headStyle
|
|
190
|
+
|
|
191
|
+
%% Output
|
|
192
|
+
OUTPUT["<b>📤 Predictions</b><br/>ŷ ∈ ℝᴷ<br/>━━━━━━━━━━━━━━<br/>• Logits (classification)<br/>• Values (regression)<br/>+ Rule activations<br/>+ Explanation data"]:::outputStyle
|
|
193
|
+
|
|
194
|
+
%% Explanation Module
|
|
195
|
+
EXPLAIN["<b>💡 Explanation Engine</b><br/>━━━━━━━━━━━━━━<br/>• IF-THEN rules<br/>• Counterfactuals<br/>• Feature importance<br/>• Minimal sufficient sets<br/>• Global rule ranking"]:::explainStyle
|
|
196
|
+
|
|
197
|
+
%% Connections
|
|
198
|
+
INPUT --> CALIB
|
|
199
|
+
CALIB --> BETA
|
|
200
|
+
BETA --> RULE1
|
|
201
|
+
RULE1 --> GATE1
|
|
202
|
+
GATE1 --> AGG1
|
|
203
|
+
AGG1 --> RULE2
|
|
204
|
+
RULE2 --> GATE2
|
|
205
|
+
GATE2 --> AGG2
|
|
206
|
+
|
|
207
|
+
AGG2 --> HEAD_LINEAR
|
|
208
|
+
AGG2 --> HEAD_PROTO
|
|
209
|
+
|
|
210
|
+
HEAD_LINEAR --> OUTPUT
|
|
211
|
+
HEAD_PROTO --> OUTPUT
|
|
212
|
+
|
|
213
|
+
OUTPUT -.->|"Rule traces"| EXPLAIN
|
|
214
|
+
RULE1 -.->|"Layer 1 rules"| EXPLAIN
|
|
215
|
+
RULE2 -.->|"Layer 2 rules"| EXPLAIN
|
|
216
|
+
BETA -.->|"Fact activations"| EXPLAIN
|
|
217
|
+
|
|
218
|
+
%% Subgraphs
|
|
219
|
+
subgraph SYMBOLIC ["<b>🧠 Symbolic Core</b>"]
|
|
220
|
+
BETA
|
|
221
|
+
RULE1
|
|
222
|
+
RULE2
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
subgraph CONTROL ["<b>🎛️ Neural Control</b>"]
|
|
226
|
+
GATE1
|
|
227
|
+
GATE2
|
|
228
|
+
AGG1
|
|
229
|
+
AGG2
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
subgraph HEADS ["<b>🎯 Task Heads</b>"]
|
|
233
|
+
HEAD_LINEAR
|
|
234
|
+
HEAD_PROTO
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
%% Gradient Flow Annotation
|
|
238
|
+
GRAD["<b>⚡ Gradient Flow</b><br/>End-to-end differentiable<br/>Backprop through rules"]:::gradStyle
|
|
239
|
+
OUTPUT -.->|"∇Loss"| GRAD
|
|
240
|
+
GRAD -.->|"∂L/∂β, ∂L/∂W"| BETA
|
|
241
|
+
|
|
242
|
+
%% Styling
|
|
243
|
+
classDef inputStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:3px,color:#0d47a1,font-weight:bold
|
|
244
|
+
classDef preprocessStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c
|
|
245
|
+
classDef factStyle fill:#fff3e0,stroke:#e65100,stroke-width:3px,color:#bf360c,font-weight:bold
|
|
246
|
+
classDef ruleStyle fill:#e8f5e9,stroke:#2e7d32,stroke-width:3px,color:#1b5e20,font-weight:bold
|
|
247
|
+
classDef gateStyle fill:#fce4ec,stroke:#c2185b,stroke-width:2px,color:#880e4f
|
|
248
|
+
classDef aggStyle fill:#e0f2f1,stroke:#00695c,stroke-width:2px,color:#004d40
|
|
249
|
+
classDef headStyle fill:#f1f8e9,stroke:#558b2f,stroke-width:3px,color:#33691e,font-weight:bold
|
|
250
|
+
classDef outputStyle fill:#e8eaf6,stroke:#283593,stroke-width:4px,color:#1a237e,font-weight:bold
|
|
251
|
+
classDef explainStyle fill:#fffde7,stroke:#f9a825,stroke-width:3px,color:#f57f17,font-weight:bold
|
|
252
|
+
classDef gradStyle fill:#fce4ec,stroke:#ad1457,stroke-width:2px,color:#880e4f,font-style:italic
|
|
253
|
+
|
|
254
|
+
style SYMBOLIC fill:#e8f5e9,stroke:#2e7d32,stroke-width:3px,stroke-dasharray: 5 5
|
|
255
|
+
style CONTROL fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,stroke-dasharray: 5 5
|
|
256
|
+
style HEADS fill:#e1f5fe,stroke:#0277bd,stroke-width:2px,stroke-dasharray: 5 5
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Key Components
|
|
260
|
+
|
|
261
|
+
- **β‑Facts**. Differentiable, bounded atoms defined as:
|
|
262
|
+
`βᵢ(x) = σ(kᵢ · (Lᵢx − Rᵢx − θᵢ))^νᵢ`
|
|
263
|
+
where `k` controls sharpness, `ν` controls shape, and `(L, R, θ)` parameterize linear predicates
|
|
264
|
+
|
|
265
|
+
- **Rule Layers**. Combinators over β‑facts using AND/OR/k‑of‑n/NOT with multiple selection modes
|
|
266
|
+
|
|
267
|
+
- **Differentiable Gaters**. Soft top‑k or budgeted masking over rules
|
|
268
|
+
|
|
269
|
+
- **Prototype Head**. Classification by similarity to learned, L2‑normalized prototypes
|
|
270
|
+
|
|
271
|
+
## 📊 Performance Benchmarks
|
|
272
|
+
|
|
273
|
+
| Dataset | Metric | **Nous** | **XGBoost** | **EBM** | **MLP** | **KAN** |
|
|
274
|
+
|---------|--------|----------|-------------|---------|---------|---------|
|
|
275
|
+
| **HELOC** (classification) | AUC | 0.7922 ± 0.0037 | 0.7965 ± 0.0071 | 0.8001 ± 0.0065 | 0.7910 ± 0.0045 | 0.7964 ± 0.0060 |
|
|
276
|
+
| | Accuracy | 0.7199 ± 0.0063 | 0.7239 ± 0.0089 | 0.7279 ± 0.0083 | 0.7218 ± 0.0063 | 0.7252 ± 0.0073 |
|
|
277
|
+
| **California Housing** (regression) | RMSE ↓ | 0.5157 ± 0.0117 | 0.4441 ± 0.0117 | 0.5500 ± 0.0131 | 0.5231 ± 0.0072 | 0.5510 ± 0.0046 |
|
|
278
|
+
| | R² ↑ | 0.8001 ± 0.0091 | 0.8517 ± 0.0090 | 0.7726 ± 0.0107 | 0.7944 ± 0.0027 | 0.7719 ± 0.0038 |
|
|
279
|
+
|
|
280
|
+
*Note: Nous provides state‑of‑the‑art interpretability with competitive accuracy, trading minimal performance gaps for full symbolic transparency.*
|
|
281
|
+
|
|
282
|
+
## 🔍 Advanced Features
|
|
283
|
+
|
|
284
|
+
### Minimal Sufficient Explanations
|
|
285
|
+
```python
|
|
286
|
+
from nous.explain import minimal_sufficient_explanation
|
|
287
|
+
|
|
288
|
+
mse = minimal_sufficient_explanation(model, x_sample)
|
|
289
|
+
print(f"Minimal rules needed: {mse['rules_used']}")
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Counterfactual Suggestions
|
|
293
|
+
```python
|
|
294
|
+
from nous.explain import suggest_rule_counterfactuals
|
|
295
|
+
|
|
296
|
+
cf = suggest_rule_counterfactuals(model, x_sample, target_class=1)
|
|
297
|
+
print(f"Change {cf['feature']} from {cf['current']} to {cf['target']}")
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Global Rule Analysis
|
|
301
|
+
```python
|
|
302
|
+
from nous.explain import global_rulebook
|
|
303
|
+
|
|
304
|
+
rules = global_rulebook(model, X.numpy())
|
|
305
|
+
print(f"Top global rule: {rules[0]['description']}")
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## 🗂️ Project Structure
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
nous/
|
|
312
|
+
├── model.py # Main NousNet class
|
|
313
|
+
├── facts.py # β-facts and calibrators
|
|
314
|
+
├── rules/ # Rule layers and gaters
|
|
315
|
+
├── prototypes.py # Prototype-based head
|
|
316
|
+
├── explain/ # Interpretation tools
|
|
317
|
+
├── export/ # NumPy export
|
|
318
|
+
├── training/ # Training utilities
|
|
319
|
+
├── optim/ # Specialized optimizers
|
|
320
|
+
└── examples/ # Usage examples
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## 🤝 Contributing
|
|
324
|
+
|
|
325
|
+
We welcome contributions! Please:
|
|
326
|
+
|
|
327
|
+
1. Fork the repository
|
|
328
|
+
2. Create a feature branch (`git checkout -b feat/amazing-feature`)
|
|
329
|
+
3. Add tests and documentation
|
|
330
|
+
4. Open a pull request
|
|
331
|
+
|
|
332
|
+
Bug reports, documentation improvements, and use‑case suggestions are appreciated.
|
|
333
|
+
|
|
334
|
+
## 📄 License
|
|
335
|
+
|
|
336
|
+
MIT License. See [LICENSE](https://github.com/EmotionEngineer/nous/blob/main/LICENSE) for details.
|
nous-0.5.1/README.md
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Nous: A Neuro‑Symbolic Library for Interpretable AI
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/nous/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](https://pytorch.org/)
|
|
7
|
+
[](https://github.com/EmotionEngineer/nous)
|
|
8
|
+
|
|
9
|
+
**Nous** (Greek: νοῦς, "mind") is a neuro‑symbolic deep learning library for building interpretable, causally transparent, and high‑performance models for classification and regression. It combines differentiable β‑facts with rule aggregation layers to produce human‑readable decision logic while retaining the benefits of gradient‑based optimization.
|
|
10
|
+
|
|
11
|
+
## 🚀 Key Features
|
|
12
|
+
|
|
13
|
+
- **Human‑Readable Explanations**. Get clear "IF-THEN" rules that explain predictions
|
|
14
|
+
- **Differentiable Rule Learning**. Train symbolic rules with gradient-based optimization
|
|
15
|
+
- **Faithful Interpretability**. Honest leave‑one‑out, counterfactuals, and minimal sufficient explanations
|
|
16
|
+
- **Zero‑Dependency Inference**. Export to pure NumPy for production deployment
|
|
17
|
+
- **Prototype‑Based Reasoning**. Classification by similarity to learned prototypes
|
|
18
|
+
- **Advanced Optimizers**. Specialized training for sparse, gated models
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
21
|
+
|
|
22
|
+
**Stable release (PyPI)**
|
|
23
|
+
```bash
|
|
24
|
+
pip install nous
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Development version (GitHub)**
|
|
28
|
+
```bash
|
|
29
|
+
pip install "nous[dev,examples] @ git+https://github.com/EmotionEngineer/nous@main"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 🎯 Quick Start
|
|
33
|
+
|
|
34
|
+
### Training a Classification Model
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from nous import NousNet
|
|
38
|
+
import torch
|
|
39
|
+
|
|
40
|
+
# Initialize model
|
|
41
|
+
model = NousNet(
|
|
42
|
+
input_dim=10,
|
|
43
|
+
num_outputs=3,
|
|
44
|
+
task_type="classification",
|
|
45
|
+
num_facts=32,
|
|
46
|
+
rules_per_layer=(16, 8),
|
|
47
|
+
rule_selection_method="soft_fact",
|
|
48
|
+
use_prototypes=True
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Sample data
|
|
52
|
+
X = torch.randn(1000, 10)
|
|
53
|
+
y = torch.randint(0, 3, (1000,))
|
|
54
|
+
|
|
55
|
+
# Training
|
|
56
|
+
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3)
|
|
57
|
+
criterion = torch.nn.CrossEntropyLoss()
|
|
58
|
+
|
|
59
|
+
for epoch in range(100):
|
|
60
|
+
optimizer.zero_grad()
|
|
61
|
+
outputs = model(X)
|
|
62
|
+
loss = criterion(outputs, y)
|
|
63
|
+
loss.backward()
|
|
64
|
+
optimizer.step()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Generating Explanations
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from nous import generate_enhanced_explanation
|
|
71
|
+
|
|
72
|
+
# Explain a prediction
|
|
73
|
+
x_sample = X[0].numpy()
|
|
74
|
+
explanation = generate_enhanced_explanation(
|
|
75
|
+
model, x_sample, y_true=int(y[0].item()),
|
|
76
|
+
feature_names=[f"f{i}" for i in range(10)],
|
|
77
|
+
class_names=["A", "B", "C"]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
print(explanation)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Export for Production
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from nous.export import export_numpy_inference, load_numpy_module
|
|
87
|
+
|
|
88
|
+
# Export to pure NumPy
|
|
89
|
+
export_numpy_inference(model, "nous_infer.py")
|
|
90
|
+
|
|
91
|
+
# Load and use in any environment
|
|
92
|
+
infer = load_numpy_module("nous_infer.py")
|
|
93
|
+
probs = infer.predict(X.numpy()[:5])
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 🏗️ Core Architecture
|
|
97
|
+
|
|
98
|
+
```mermaid
|
|
99
|
+
%%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#e8f4f8','primaryTextColor':'#1a1a1a','primaryBorderColor':'#2c5f7c','lineColor':'#4a90a4','secondaryColor':'#fef5e7','tertiaryColor':'#f0f8ff','noteTextColor':'#1a1a1a','noteBkgColor':'#fffacd','textColor':'#1a1a1a'}}}%%
|
|
100
|
+
|
|
101
|
+
graph TB
|
|
102
|
+
%% Input Layer
|
|
103
|
+
INPUT["<b>📥 Input Layer</b><br/>x ∈ ℝᴰ<br/><i>Raw Features</i>"]:::inputStyle
|
|
104
|
+
|
|
105
|
+
%% Preprocessing
|
|
106
|
+
CALIB["<b>📊 Feature Calibrators</b><br/>Monotonic splines<br/>Feature scaling & normalization<br/><i>Optional preprocessing</i>"]:::preprocessStyle
|
|
107
|
+
|
|
108
|
+
%% Beta Facts
|
|
109
|
+
BETA["<b>🔷 Beta-Fact Layer</b><br/>βᵢ(x) = σ(kᵢ·(Lᵢx − Rᵢx − θᵢ))^νᵢ<br/>━━━━━━━━━━━━━━<br/>• k: sharpness parameter<br/>• ν: shape exponent<br/>• L,R: feature projections<br/>• θ: threshold bias<br/><i>N differentiable atoms ∈ [0,1]</i>"]:::factStyle
|
|
110
|
+
|
|
111
|
+
%% Rule Layer 1
|
|
112
|
+
RULE1["<b>⚙️ Rule Layer 1</b><br/>Combinator Logic<br/>━━━━━━━━━━━━━━<br/>• AND: ∏ᵢ βᵢ<br/>• OR: 1−∏ᵢ(1−βᵢ)<br/>• k-of-n: soft threshold<br/>• NOT: 1−β<br/><i>R₁ learned rules</i>"]:::ruleStyle
|
|
113
|
+
|
|
114
|
+
GATE1["<b>🚪 Gating 1</b><br/>Soft top-k selection<br/>Budget masking<br/><i>Sparsity control</i>"]:::gateStyle
|
|
115
|
+
|
|
116
|
+
AGG1["<b>∑ Aggregation 1</b><br/>Weighted sum<br/>Residual connections"]:::aggStyle
|
|
117
|
+
|
|
118
|
+
%% Rule Layer 2
|
|
119
|
+
RULE2["<b>⚙️ Rule Layer 2</b><br/>Higher-order combinations<br/>━━━━━━━━━━━━━━<br/>Rules over rules<br/><i>R₂ meta-rules</i>"]:::ruleStyle
|
|
120
|
+
|
|
121
|
+
GATE2["<b>🚪 Gating 2</b><br/>Hierarchical pruning<br/>Confidence weighting"]:::gateStyle
|
|
122
|
+
|
|
123
|
+
AGG2["<b>∑ Aggregation 2</b><br/>Final rule scores<br/>Symbolic → numeric"]:::aggStyle
|
|
124
|
+
|
|
125
|
+
%% Output Heads
|
|
126
|
+
HEAD_LINEAR["<b>📐 Linear Head</b><br/>W·r + b<br/><i>Regression output</i>"]:::headStyle
|
|
127
|
+
|
|
128
|
+
HEAD_PROTO["<b>🎯 Prototype Head</b><br/>Similarity to prototypes<br/>━━━━━━━━━━━━━━<br/>d(r, pₖ) = ||r − pₖ||₂<br/>L2 normalization<br/><i>Classification via distance</i>"]:::headStyle
|
|
129
|
+
|
|
130
|
+
%% Output
|
|
131
|
+
OUTPUT["<b>📤 Predictions</b><br/>ŷ ∈ ℝᴷ<br/>━━━━━━━━━━━━━━<br/>• Logits (classification)<br/>• Values (regression)<br/>+ Rule activations<br/>+ Explanation data"]:::outputStyle
|
|
132
|
+
|
|
133
|
+
%% Explanation Module
|
|
134
|
+
EXPLAIN["<b>💡 Explanation Engine</b><br/>━━━━━━━━━━━━━━<br/>• IF-THEN rules<br/>• Counterfactuals<br/>• Feature importance<br/>• Minimal sufficient sets<br/>• Global rule ranking"]:::explainStyle
|
|
135
|
+
|
|
136
|
+
%% Connections
|
|
137
|
+
INPUT --> CALIB
|
|
138
|
+
CALIB --> BETA
|
|
139
|
+
BETA --> RULE1
|
|
140
|
+
RULE1 --> GATE1
|
|
141
|
+
GATE1 --> AGG1
|
|
142
|
+
AGG1 --> RULE2
|
|
143
|
+
RULE2 --> GATE2
|
|
144
|
+
GATE2 --> AGG2
|
|
145
|
+
|
|
146
|
+
AGG2 --> HEAD_LINEAR
|
|
147
|
+
AGG2 --> HEAD_PROTO
|
|
148
|
+
|
|
149
|
+
HEAD_LINEAR --> OUTPUT
|
|
150
|
+
HEAD_PROTO --> OUTPUT
|
|
151
|
+
|
|
152
|
+
OUTPUT -.->|"Rule traces"| EXPLAIN
|
|
153
|
+
RULE1 -.->|"Layer 1 rules"| EXPLAIN
|
|
154
|
+
RULE2 -.->|"Layer 2 rules"| EXPLAIN
|
|
155
|
+
BETA -.->|"Fact activations"| EXPLAIN
|
|
156
|
+
|
|
157
|
+
%% Subgraphs
|
|
158
|
+
subgraph SYMBOLIC ["<b>🧠 Symbolic Core</b>"]
|
|
159
|
+
BETA
|
|
160
|
+
RULE1
|
|
161
|
+
RULE2
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
subgraph CONTROL ["<b>🎛️ Neural Control</b>"]
|
|
165
|
+
GATE1
|
|
166
|
+
GATE2
|
|
167
|
+
AGG1
|
|
168
|
+
AGG2
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
subgraph HEADS ["<b>🎯 Task Heads</b>"]
|
|
172
|
+
HEAD_LINEAR
|
|
173
|
+
HEAD_PROTO
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
%% Gradient Flow Annotation
|
|
177
|
+
GRAD["<b>⚡ Gradient Flow</b><br/>End-to-end differentiable<br/>Backprop through rules"]:::gradStyle
|
|
178
|
+
OUTPUT -.->|"∇Loss"| GRAD
|
|
179
|
+
GRAD -.->|"∂L/∂β, ∂L/∂W"| BETA
|
|
180
|
+
|
|
181
|
+
%% Styling
|
|
182
|
+
classDef inputStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:3px,color:#0d47a1,font-weight:bold
|
|
183
|
+
classDef preprocessStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c
|
|
184
|
+
classDef factStyle fill:#fff3e0,stroke:#e65100,stroke-width:3px,color:#bf360c,font-weight:bold
|
|
185
|
+
classDef ruleStyle fill:#e8f5e9,stroke:#2e7d32,stroke-width:3px,color:#1b5e20,font-weight:bold
|
|
186
|
+
classDef gateStyle fill:#fce4ec,stroke:#c2185b,stroke-width:2px,color:#880e4f
|
|
187
|
+
classDef aggStyle fill:#e0f2f1,stroke:#00695c,stroke-width:2px,color:#004d40
|
|
188
|
+
classDef headStyle fill:#f1f8e9,stroke:#558b2f,stroke-width:3px,color:#33691e,font-weight:bold
|
|
189
|
+
classDef outputStyle fill:#e8eaf6,stroke:#283593,stroke-width:4px,color:#1a237e,font-weight:bold
|
|
190
|
+
classDef explainStyle fill:#fffde7,stroke:#f9a825,stroke-width:3px,color:#f57f17,font-weight:bold
|
|
191
|
+
classDef gradStyle fill:#fce4ec,stroke:#ad1457,stroke-width:2px,color:#880e4f,font-style:italic
|
|
192
|
+
|
|
193
|
+
style SYMBOLIC fill:#e8f5e9,stroke:#2e7d32,stroke-width:3px,stroke-dasharray: 5 5
|
|
194
|
+
style CONTROL fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,stroke-dasharray: 5 5
|
|
195
|
+
style HEADS fill:#e1f5fe,stroke:#0277bd,stroke-width:2px,stroke-dasharray: 5 5
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Key Components
|
|
199
|
+
|
|
200
|
+
- **β‑Facts**. Differentiable, bounded atoms defined as:
|
|
201
|
+
`βᵢ(x) = σ(kᵢ · (Lᵢx − Rᵢx − θᵢ))^νᵢ`
|
|
202
|
+
where `k` controls sharpness, `ν` controls shape, and `(L, R, θ)` parameterize linear predicates
|
|
203
|
+
|
|
204
|
+
- **Rule Layers**. Combinators over β‑facts using AND/OR/k‑of‑n/NOT with multiple selection modes
|
|
205
|
+
|
|
206
|
+
- **Differentiable Gaters**. Soft top‑k or budgeted masking over rules
|
|
207
|
+
|
|
208
|
+
- **Prototype Head**. Classification by similarity to learned, L2‑normalized prototypes
|
|
209
|
+
|
|
210
|
+
## 📊 Performance Benchmarks
|
|
211
|
+
|
|
212
|
+
| Dataset | Metric | **Nous** | **XGBoost** | **EBM** | **MLP** | **KAN** |
|
|
213
|
+
|---------|--------|----------|-------------|---------|---------|---------|
|
|
214
|
+
| **HELOC** (classification) | AUC | 0.7922 ± 0.0037 | 0.7965 ± 0.0071 | 0.8001 ± 0.0065 | 0.7910 ± 0.0045 | 0.7964 ± 0.0060 |
|
|
215
|
+
| | Accuracy | 0.7199 ± 0.0063 | 0.7239 ± 0.0089 | 0.7279 ± 0.0083 | 0.7218 ± 0.0063 | 0.7252 ± 0.0073 |
|
|
216
|
+
| **California Housing** (regression) | RMSE ↓ | 0.5157 ± 0.0117 | 0.4441 ± 0.0117 | 0.5500 ± 0.0131 | 0.5231 ± 0.0072 | 0.5510 ± 0.0046 |
|
|
217
|
+
| | R² ↑ | 0.8001 ± 0.0091 | 0.8517 ± 0.0090 | 0.7726 ± 0.0107 | 0.7944 ± 0.0027 | 0.7719 ± 0.0038 |
|
|
218
|
+
|
|
219
|
+
*Note: Nous provides state‑of‑the‑art interpretability with competitive accuracy, trading minimal performance gaps for full symbolic transparency.*
|
|
220
|
+
|
|
221
|
+
## 🔍 Advanced Features
|
|
222
|
+
|
|
223
|
+
### Minimal Sufficient Explanations
|
|
224
|
+
```python
|
|
225
|
+
from nous.explain import minimal_sufficient_explanation
|
|
226
|
+
|
|
227
|
+
mse = minimal_sufficient_explanation(model, x_sample)
|
|
228
|
+
print(f"Minimal rules needed: {mse['rules_used']}")
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Counterfactual Suggestions
|
|
232
|
+
```python
|
|
233
|
+
from nous.explain import suggest_rule_counterfactuals
|
|
234
|
+
|
|
235
|
+
cf = suggest_rule_counterfactuals(model, x_sample, target_class=1)
|
|
236
|
+
print(f"Change {cf['feature']} from {cf['current']} to {cf['target']}")
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Global Rule Analysis
|
|
240
|
+
```python
|
|
241
|
+
from nous.explain import global_rulebook
|
|
242
|
+
|
|
243
|
+
rules = global_rulebook(model, X.numpy())
|
|
244
|
+
print(f"Top global rule: {rules[0]['description']}")
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## 🗂️ Project Structure
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
nous/
|
|
251
|
+
├── model.py # Main NousNet class
|
|
252
|
+
├── facts.py # β-facts and calibrators
|
|
253
|
+
├── rules/ # Rule layers and gaters
|
|
254
|
+
├── prototypes.py # Prototype-based head
|
|
255
|
+
├── explain/ # Interpretation tools
|
|
256
|
+
├── export/ # NumPy export
|
|
257
|
+
├── training/ # Training utilities
|
|
258
|
+
├── optim/ # Specialized optimizers
|
|
259
|
+
└── examples/ # Usage examples
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## 🤝 Contributing
|
|
263
|
+
|
|
264
|
+
We welcome contributions! Please:
|
|
265
|
+
|
|
266
|
+
1. Fork the repository
|
|
267
|
+
2. Create a feature branch (`git checkout -b feat/amazing-feature`)
|
|
268
|
+
3. Add tests and documentation
|
|
269
|
+
4. Open a pull request
|
|
270
|
+
|
|
271
|
+
Bug reports, documentation improvements, and use‑case suggestions are appreciated.
|
|
272
|
+
|
|
273
|
+
## 📄 License
|
|
274
|
+
|
|
275
|
+
MIT License. See [LICENSE](https://github.com/EmotionEngineer/nous/blob/main/LICENSE) for details.
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
from .version import __version__
|
|
2
2
|
from .model import NousNet
|
|
3
|
-
from .facts import BetaFactLayer, PiecewiseLinearCalibrator
|
|
3
|
+
from .facts import BetaFactLayer, PiecewiseLinearCalibrator, PiecewiseLinearCalibratorQuantile
|
|
4
4
|
from .prototypes import ScaledPrototypeLayer
|
|
5
|
-
from .rules import FixedPairRuleLayer, SoftmaxRuleLayer, SparseRuleLayer, SimpleNousBlock
|
|
5
|
+
from .rules import FixedPairRuleLayer, SoftmaxRuleLayer, SparseRuleLayer, SoftFactRuleLayer, SimpleNousBlock
|
|
6
|
+
from .rules import (
|
|
7
|
+
BaseRuleGater,
|
|
8
|
+
GateSoftRank,
|
|
9
|
+
GateLogisticThresholdExactK,
|
|
10
|
+
GateCappedSimplex,
|
|
11
|
+
GateSparsemaxK,
|
|
12
|
+
GateHardConcreteBudget,
|
|
13
|
+
make_rule_gater,
|
|
14
|
+
)
|
|
6
15
|
|
|
7
16
|
# Explainability (core API)
|
|
8
17
|
from .explain import (
|
|
@@ -51,7 +60,7 @@ from .training import (
|
|
|
51
60
|
from .data import get_wine_data, get_california_housing_data
|
|
52
61
|
|
|
53
62
|
# Utilities
|
|
54
|
-
from .utils import set_global_seed
|
|
63
|
+
from .utils import set_global_seed, make_quantile_calibrators
|
|
55
64
|
|
|
56
65
|
__all__ = [
|
|
57
66
|
"__version__",
|
|
@@ -63,7 +72,16 @@ __all__ = [
|
|
|
63
72
|
"FixedPairRuleLayer",
|
|
64
73
|
"SoftmaxRuleLayer",
|
|
65
74
|
"SparseRuleLayer",
|
|
75
|
+
"SoftFactRuleLayer",
|
|
66
76
|
"SimpleNousBlock",
|
|
77
|
+
# Differentiable rule gaters
|
|
78
|
+
"BaseRuleGater",
|
|
79
|
+
"GateSoftRank",
|
|
80
|
+
"GateLogisticThresholdExactK",
|
|
81
|
+
"GateCappedSimplex",
|
|
82
|
+
"GateSparsemaxK",
|
|
83
|
+
"GateHardConcreteBudget",
|
|
84
|
+
"make_rule_gater",
|
|
67
85
|
# Explainability (core)
|
|
68
86
|
"rule_impact_df",
|
|
69
87
|
"minimal_sufficient_explanation",
|
|
@@ -100,4 +118,5 @@ __all__ = [
|
|
|
100
118
|
"get_california_housing_data",
|
|
101
119
|
# Utilities
|
|
102
120
|
"set_global_seed",
|
|
103
|
-
|
|
121
|
+
"make_quantile_calibrators",
|
|
122
|
+
]
|