SparseDGP
Exactly k features drive the target and the remaining p − k are pure noise. Built for
feature-selection work: you know the true support, so you can compute precision and recall of
a selection method rather than only its predictive error.
Note that k and complexity control different things, and complexity is inverted from
what the name suggests. It sets the coefficient scale, so a higher complexity means a
weaker signal buried in the same fixed σ = 0.5 noise:
| Complexity | Coefficient scale | Effect |
|---|---|---|
"low" |
3.0 | Strong signal, easy to detect |
"medium" |
1.0 | |
"high" |
0.3 | Weak signal, hard to separate from noise |
Sparsity itself never changes with complexity — that is k's job alone.
from synthbench import BenchPipeline, SparseDGP
dgp = SparseDGP(k=3, complexity="medium", task_type="regression", random_state=0)
result = BenchPipeline(dgp).run(n_samples=500, n_features=10, random_state=42)
importances = result.metadata["signal_feature_importances"]
print(sum(importances.values())) # 1.0
print(sum(v == 0.0 for v in importances.values())) # 7 noise features
Noise features get exactly 0.0, not a small number — that is a contract, not a
floating-point accident, so v == 0.0 is a safe test for "outside the true support". k must
not exceed the n_features you pass to .run().
For more than two classes, pass n_classes. Each of the k informative features gets one
coefficient per class and the labels come from a softmax over those scores, so the classes are
unordered. The support is unchanged: the same k features drive every class, and the rest stay
exactly 0.0, which keeps the feature-selection ground truth meaningful.
Full parameter list: SparseDGP in the API reference.