@@ -75,25 +75,24 @@ def calculate(
7575 self ,
7676 objectives : Optional [Union [Objective , List [Objective ]]], # noqa
7777 budget : Optional [Union [int , float ]] = None , # noqa
78- n_trees : int = 50 , # noqa
79- seed : int = 0 , # noqa
78+ model : Any = None ,
8079 ) -> None :
8180 """
8281 Calculate the ablation path performances and improvements.
8382
83+ To use standard Random Forest surrogate do not pass a model.
84+ The option to pass another model is just for testing purposes.
85+
8486 Parameters
8587 ----------
8688 objectives : Optional[Union[Objective, List[Objective]]]
8789 The objective(s) to be considered.
8890 budget : Optional[Union[int, float]]
8991 The budget to be considered. If None, all budgets of the run are considered.
9092 Default is None.
91- n_trees : int
92- The number of trees for the surrogate model.
93- Default is 50.
94- seed : int
95- The seed for the surrogate model.
96- Default is 0.
93+ model :
94+ The surrogate model to use for the prediction of the perfromances.
95+ By default None.
9796 """
9897 if isinstance (objectives , list ) and len (objectives ) > 1 :
9998 raise ValueError ("Only one objective is supported for ablation paths." )
@@ -103,25 +102,30 @@ def calculate(
103102 performances : OrderedDict = OrderedDict ()
104103 improvements : OrderedDict = OrderedDict ()
105104
105+ self ._model = model
106+
106107 df = self .run .get_encoded_data (objective , budget , specific = True )
107108
108109 # Obtain all configurations with theirs costs
109110 df = df .dropna (subset = [objective .name ])
110111 X = df [list (self .run .configspace .keys ())].to_numpy ()
111112 Y = df [objective .name ].to_numpy ()
112113
113- # A Random Forest Regressor is used as surrogate model
114- self ._model = RandomForestSurrogate (self .cs , seed = seed , n_trees = n_trees )
115- self ._model ._fit (X , Y )
116-
117114 # Get the incumbent configuration
118115 incumbent_config , _ = self .run .get_incumbent (budget = budget , objectives = objective )
119116 incumbent_encode = self .run .encode_config (incumbent_config )
120117
121118 # Get the default configuration
119+
122120 self .default_config = self .cs .get_default_configuration ()
123121 default_encode = self .run .encode_config (self .default_config )
124122
123+ # The default model is a RF Surrogate, but it cant be passed as parameter directly
124+ # because it needs access to its config space
125+ if self ._model is None :
126+ self ._model = RandomForestSurrogate (self .cs , seed = 0 , n_trees = 50 )
127+
128+ self ._model .fit (X , Y )
125129 # Obtain the predicted cost of the default and incumbent configuration
126130 def_cost , def_std = self ._model .predict (np .array ([default_encode ]))
127131 def_cost , def_std = def_cost [0 ], def_std [0 ]
@@ -166,6 +170,7 @@ def calculate(
166170 performances [max_hp ] = (max_hp_cost , max_hp_std )
167171 impr_std = np .sqrt (def_std ** 2 + max_hp_std ** 2 )
168172 improvements [max_hp ] = ((def_cost - max_hp_cost ), impr_std )
173+
169174 # New 'default' cost and std
170175 def_cost = max_hp_cost
171176 def_std = max_hp_std
@@ -248,7 +253,6 @@ def _ablation(
248253 if hp in incumbent_config .keys () and hp in self .default_config .keys ():
249254 config_copy = copy .copy (self .default_config )
250255 config_copy [hp ] = incumbent_config [hp ]
251-
252256 new_cost , _ = self ._model .predict (np .array ([self .run .encode_config (config_copy )]))
253257 if objective .optimize == "upper" :
254258 new_cost = - new_cost
@@ -262,6 +266,7 @@ def _ablation(
262266 else :
263267 continue
264268 hp_count = len (list (self .cs .keys ()))
269+
265270 if max_hp != "" :
266271 # For the maximum impact hyperparameter, switch the default with the incumbent value
267272 self .default_config [max_hp ] = incumbent_config [max_hp ]
@@ -270,6 +275,7 @@ def _ablation(
270275 )
271276 if objective .optimize == "upper" :
272277 max_hp_cost = - max_hp_cost
278+
273279 return True , max_hp , max_hp_cost [0 ], max_hp_std [0 ]
274280 else :
275281 self .logger .info (
0 commit comments