Parameter Importance
After a study, parameter importance tells you which hyperparameters actually drove the objective
and which barely mattered — so you can widen the ranges that count and fix the ones that don't.
OptunaSharp ports optuna.importance into OptunaSharp.Importance.
Computing importances
using OptunaSharp;
using OptunaSharp.Collections; // OrderedDict
using OptunaSharp.Importance;
OrderedDict<string, double> importances = ImportanceFunctions.GetParamImportances(study);
foreach (var (name, importance) in importances) // ordered most-important first
Console.WriteLine($"{name}: {importance:P1}");
The full signature:
public static OrderedDict<string, double> GetParamImportances(
Study study,
BaseImportanceEvaluator? evaluator = null, // default: PedAnovaImportanceEvaluator
IReadOnlyList<string>? @params = null, // restrict to these parameters
Func<FrozenTrial, double>? target = null, // custom target (e.g. an objective index)
bool normalize = true); // importances sum to 1
With normalize: true (the default) the importances sum to 1 and read as fractions of the total.
Restrict the analysis with @params, or point it at a different quantity — a specific objective in a
multi-objective study, or a trial duration — with target.
Available evaluators
All four of Optuna's importance evaluators are ported, and all live in Core — the forest-based
ones use a pure-managed, bit-exact port of scikit-learn's RandomForestRegressor as the
surrogate, so none of them needs a foreign runtime:
| Evaluator | Namespace | Ports |
|---|---|---|
PedAnovaImportanceEvaluator (default) |
OptunaSharp.Importance.PedAnova |
optuna.importance.PedAnovaImportanceEvaluator |
FanovaImportanceEvaluator |
OptunaSharp.Importance |
optuna.importance.FanovaImportanceEvaluator |
MeanDecreaseImpurityImportanceEvaluator |
OptunaSharp.Importance |
optuna.importance.MeanDecreaseImpurityImportanceEvaluator |
ShapleyImportanceEvaluator |
OptunaSharp.Importance.Shap |
optuna.integration.ShapleyImportanceEvaluator |
Which parameters are assessed. With the default
PedAnovaImportanceEvaluatorandparams: null, all parameters that appear in completed trials are assessed, including conditional ones. The three forest/SHAP evaluators assess only parameters that are present in all of the completed trials. Passingparamsrestricts any evaluator to the listed parameters.
PED-ANOVA (the default evaluator)
The default evaluator is PedAnovaImportanceEvaluator (namespace OptunaSharp.Importance.PedAnova),
a fast, sampler-agnostic method based on the Pearson-divergence ANOVA of the distribution of good
trials against all trials. It needs no surrogate forest.
using OptunaSharp.Importance.PedAnova;
var evaluator = new PedAnovaImportanceEvaluator(
targetQuantile: 0.1, // "good" trials = the top 10%
regionQuantile: 1.0, // baseline region = all trials
evaluateOnLocal: true); // measure importance within the good region
var importances = ImportanceFunctions.GetParamImportances(study, evaluator);
targetQuantile sets what counts as a good trial; evaluateOnLocal focuses the measurement on the
promising region rather than the whole space.
fANOVA
FanovaImportanceEvaluator (namespace OptunaSharp.Importance) implements the fANOVA algorithm of
Hutter et al. (ICML 2014): it fits a random forest
that predicts the objective from the parameter configurations, then decomposes the forest's
prediction variance across the parameters. The more accurate the forest, the more reliable the
importances — an exploration-oriented sampler such as RandomSampler is recommended.
using OptunaSharp.Importance;
var evaluator = new FanovaImportanceEvaluator(nTrees: 64, maxDepth: 64, seed: 0);
var importances = ImportanceFunctions.GetParamImportances(study, evaluator);
Because the surrogate is a bit-exact port of scikit-learn's RandomForestRegressor, a fixed seed
reproduces Python Optuna's importance values to about 1 ULP.
Mean Decrease Impurity (MDI)
MeanDecreaseImpurityImportanceEvaluator (namespace OptunaSharp.Importance) fits the same random
forest and reads each tree's stored per-node impurity decrease and weighted sample counts — a port of
sklearn.ensemble.RandomForestRegressor.feature_importances_.
using OptunaSharp.Importance;
var evaluator = new MeanDecreaseImpurityImportanceEvaluator(nTrees: 64, maxDepth: 64, seed: 0);
var importances = ImportanceFunctions.GetParamImportances(study, evaluator);
Like fANOVA, under a fixed seed the importances match Python Optuna to about 1 ULP.
Shapley (SHAP)
ShapleyImportanceEvaluator (namespace OptunaSharp.Importance.Shap) fits the same random forest and
computes each parameter's importance as the mean absolute SHAP value over the trials, using a
tree-path-dependent Tree SHAP walk. Optuna ships this evaluator in the separate optuna_integration
package because there it depends on the third-party shap and scikit-learn Python libraries;
OptunaSharp's port is pure arithmetic (no erf, no LAPACK), so it lives in Core with the other
evaluators.
using OptunaSharp.Importance.Shap;
var evaluator = new ShapleyImportanceEvaluator(nTrees: 64, maxDepth: 64, seed: 0);
var importances = ImportanceFunctions.GetParamImportances(study, evaluator);
Two behaviors mirror Optuna: the constructor raises an ExperimentalWarning (the class is
@experimental_class("3.0.0")), and on a multi-objective study it throws a ValueError unless
you pass a target (for example target: t => t.Values[0]). Under a fixed seed the importances are
byte-for-byte identical to Optuna's ShapleyImportanceEvaluator (SHAP 0.52.0) on x64/x86 hosts.
ML.NET forest backends (optional package)
The OptunaSharp.Integration.ML.NET package adds forest-based evaluators that swap the native
surrogate for an ML.NET trainer. The faithful drop-ins are
FastForestFanovaImportanceEvaluator and FastForestMeanDecreaseImpurityImportanceEvaluator
(namespace OptunaSharp.Importance.Forests); experimental FastTree / FastTree-Tweedie boosters
(namespace OptunaSharp.Importance.Booster) are also provided. These are an off-label extension
beyond Optuna — the four Core evaluators above are the parity surface.
Writing a custom evaluator
Derive from BaseImportanceEvaluator:
public abstract OrderedDict<string, double> Evaluate(
Study study, IReadOnlyList<string>? @params = null, Func<FrozenTrial, double>? target = null);
Relationship to Optuna
| Optuna (Python) | OptunaSharp |
|---|---|
optuna.importance.get_param_importances(study) |
ImportanceFunctions.GetParamImportances(study) |
PedAnovaImportanceEvaluator(target_quantile=0.1) |
new PedAnovaImportanceEvaluator(targetQuantile: 0.1) |
FanovaImportanceEvaluator(seed=0) |
new FanovaImportanceEvaluator(seed: 0) |
MeanDecreaseImpurityImportanceEvaluator(seed=0) |
new MeanDecreaseImpurityImportanceEvaluator(seed: 0) |
optuna.integration.ShapleyImportanceEvaluator(seed=0) |
new ShapleyImportanceEvaluator(seed: 0) |
get_param_importances(study, evaluator=e, normalize=False) |
GetParamImportances(study, e, normalize: false) |
Under a fixed seed the forest-based evaluators (fANOVA, MDI, SHAP) reproduce Optuna's importance values byte-for-byte or to about 1 ULP — their scikit-learn surrogate is a bit-exact port. PED-ANOVA is computed with plain numeric operations and matches Optuna closely; where the underlying quantities ride the error-function path, the documented erf tolerance applies. In every case the ranking is the intended, stable output.
See also
ML.NET importance backends · LightGBM importance backends — alternative trainer-backed evaluators with different numeric behavior from Core's canonical forest.
Study and Trials · Visualization — plot importances · the API reference.