nmoo.denoisers.knnavg
KNN-Averaging
1"""KNN-Averaging""" 2__docformat__ = "google" 3 4from scipy.spatial.distance import cdist 5import numpy as np 6import pandas as pd 7 8from nmoo.wrapped_problem import WrappedProblem 9 10 11class KNNAvg(WrappedProblem): 12 """ 13 Implementation of the KNN-Averaging algorithm[^quatic21]. 14 15 [^quatic21]: Klikovits, S., Arcaini, P. (2021). KNN-Averaging for Noisy 16 Multi-objective Optimisation. In: Paiva, A.C.R., Cavalli, A.R., Ventura 17 Martins, P., Pérez-Castillo, R. (eds) Quality of Information and 18 Communications Technology. QUATIC 2021. Communications in Computer and 19 Information Science, vol 1439. Springer, Cham. 20 https://doi.org/10.1007/978-3-030-85347-1_36 21 """ 22 23 _distance_weight_mode: str 24 _max_distance: float 25 _n_neighbors: int 26 27 def __init__( 28 self, 29 problem: WrappedProblem, 30 max_distance: float, 31 n_neighbors: int = 5, # KNN 32 distance_weight_type: str = "uniform", 33 *, 34 name: str = "knn_avg", 35 **kwargs, 36 ): 37 """ 38 Constructor. 39 40 Args: 41 problem (`nmoo.wrapped_problem.WrappedProblem`): Noisy problem. For 42 memory optimization reasons, this should be a 43 `nmoo.wrapped_problem.WrappedProblem` as opposed to a pymoo 44 `Problem`. 45 distance_weight_type (str): Either `squared` or `uniform` (the 46 default). 47 max_distance (float): Distance cutoff. 48 n_neighbors (int): Number of neighbors to consider (the K in KNN). 49 name (str): An optional name for this problem. This will be used 50 when creating history dump files. Defaults to `knn_avg`. 51 """ 52 super().__init__(problem, name=name, **kwargs) 53 54 if distance_weight_type not in ["squared", "uniform"]: 55 raise ValueError( 56 "Parameter distance_weight_type must be either 'squared' or " 57 "'uniform'." 58 ) 59 self._distance_weight_mode = distance_weight_type 60 61 if max_distance < 0.0: 62 raise ValueError( 63 "Parameter max_distance must either be 'None' or >= 0." 64 ) 65 self._max_distance = max_distance 66 67 if n_neighbors <= 0: 68 raise ValueError("Parameter n_neighbors must be >= 1.") 69 self._n_neighbors = n_neighbors 70 71 def _evaluate(self, x, out, *args, **kwargs): 72 """ 73 Applies the KNN-Avg algorithm to the wrapped (noisy) problem's output. 74 """ 75 self._problem._evaluate(x, out, *args, **kwargs) 76 for i, sol in enumerate(x): 77 # Store the solution history into a dataframe (note that we are 78 # using the wrapped problem's history to make sure this dataframe 79 # is never empty). 80 x_hist = pd.DataFrame(self._problem._history["X"]) 81 # Compute the standardized Euclidean distances between the current 82 # solution (sol) and all historical solutions. 83 x_hist["_sed"] = cdist( 84 self._problem._history["X"], 85 sol.reshape((1, -1)), 86 "seuclidean", 87 ) 88 # Apply the KNN scheme: select the K closest neighbors among those 89 # closer than the maximum allowed distance. 90 x_hist = ( 91 x_hist[x_hist["_sed"] <= self._max_distance] 92 .sort_values(by="_sed") 93 .head(self._n_neighbors) 94 ) 95 if x_hist.shape[0] <= 1: 96 # If only the current solution remains, then skip to the next 97 # solution. 98 continue 99 # Compute the weights. 100 if self._distance_weight_mode == "squared": 101 x_hist["_w"] = (self._max_distance - x_hist["_sed"]) ** 2 102 elif self._distance_weight_mode == "uniform": 103 x_hist["_w"] = 1.0 104 else: 105 raise RuntimeError( 106 "Unknown distance weight mode: " 107 + self._distance_weight_mode 108 ) 109 # Compute the weighted averages of the (numerical) outputs. 110 for k in out: 111 if not isinstance(out[k], np.ndarray): 112 continue 113 out_k_hist = pd.DataFrame(self._problem._history[k]) 114 avg = np.average( 115 out_k_hist.iloc[x_hist.index], 116 axis=0, 117 weights=x_hist["_w"], 118 ) 119 out[k][i] = avg 120 self.add_to_history_x_out(x, out)
12class KNNAvg(WrappedProblem): 13 """ 14 Implementation of the KNN-Averaging algorithm[^quatic21]. 15 16 [^quatic21]: Klikovits, S., Arcaini, P. (2021). KNN-Averaging for Noisy 17 Multi-objective Optimisation. In: Paiva, A.C.R., Cavalli, A.R., Ventura 18 Martins, P., Pérez-Castillo, R. (eds) Quality of Information and 19 Communications Technology. QUATIC 2021. Communications in Computer and 20 Information Science, vol 1439. Springer, Cham. 21 https://doi.org/10.1007/978-3-030-85347-1_36 22 """ 23 24 _distance_weight_mode: str 25 _max_distance: float 26 _n_neighbors: int 27 28 def __init__( 29 self, 30 problem: WrappedProblem, 31 max_distance: float, 32 n_neighbors: int = 5, # KNN 33 distance_weight_type: str = "uniform", 34 *, 35 name: str = "knn_avg", 36 **kwargs, 37 ): 38 """ 39 Constructor. 40 41 Args: 42 problem (`nmoo.wrapped_problem.WrappedProblem`): Noisy problem. For 43 memory optimization reasons, this should be a 44 `nmoo.wrapped_problem.WrappedProblem` as opposed to a pymoo 45 `Problem`. 46 distance_weight_type (str): Either `squared` or `uniform` (the 47 default). 48 max_distance (float): Distance cutoff. 49 n_neighbors (int): Number of neighbors to consider (the K in KNN). 50 name (str): An optional name for this problem. This will be used 51 when creating history dump files. Defaults to `knn_avg`. 52 """ 53 super().__init__(problem, name=name, **kwargs) 54 55 if distance_weight_type not in ["squared", "uniform"]: 56 raise ValueError( 57 "Parameter distance_weight_type must be either 'squared' or " 58 "'uniform'." 59 ) 60 self._distance_weight_mode = distance_weight_type 61 62 if max_distance < 0.0: 63 raise ValueError( 64 "Parameter max_distance must either be 'None' or >= 0." 65 ) 66 self._max_distance = max_distance 67 68 if n_neighbors <= 0: 69 raise ValueError("Parameter n_neighbors must be >= 1.") 70 self._n_neighbors = n_neighbors 71 72 def _evaluate(self, x, out, *args, **kwargs): 73 """ 74 Applies the KNN-Avg algorithm to the wrapped (noisy) problem's output. 75 """ 76 self._problem._evaluate(x, out, *args, **kwargs) 77 for i, sol in enumerate(x): 78 # Store the solution history into a dataframe (note that we are 79 # using the wrapped problem's history to make sure this dataframe 80 # is never empty). 81 x_hist = pd.DataFrame(self._problem._history["X"]) 82 # Compute the standardized Euclidean distances between the current 83 # solution (sol) and all historical solutions. 84 x_hist["_sed"] = cdist( 85 self._problem._history["X"], 86 sol.reshape((1, -1)), 87 "seuclidean", 88 ) 89 # Apply the KNN scheme: select the K closest neighbors among those 90 # closer than the maximum allowed distance. 91 x_hist = ( 92 x_hist[x_hist["_sed"] <= self._max_distance] 93 .sort_values(by="_sed") 94 .head(self._n_neighbors) 95 ) 96 if x_hist.shape[0] <= 1: 97 # If only the current solution remains, then skip to the next 98 # solution. 99 continue 100 # Compute the weights. 101 if self._distance_weight_mode == "squared": 102 x_hist["_w"] = (self._max_distance - x_hist["_sed"]) ** 2 103 elif self._distance_weight_mode == "uniform": 104 x_hist["_w"] = 1.0 105 else: 106 raise RuntimeError( 107 "Unknown distance weight mode: " 108 + self._distance_weight_mode 109 ) 110 # Compute the weighted averages of the (numerical) outputs. 111 for k in out: 112 if not isinstance(out[k], np.ndarray): 113 continue 114 out_k_hist = pd.DataFrame(self._problem._history[k]) 115 avg = np.average( 116 out_k_hist.iloc[x_hist.index], 117 axis=0, 118 weights=x_hist["_w"], 119 ) 120 out[k][i] = avg 121 self.add_to_history_x_out(x, out)
Implementation of the KNN-Averaging algorithm1.
-
Klikovits, S., Arcaini, P. (2021). KNN-Averaging for Noisy Multi-objective Optimisation. In: Paiva, A.C.R., Cavalli, A.R., Ventura Martins, P., Pérez-Castillo, R. (eds) Quality of Information and Communications Technology. QUATIC 2021. Communications in Computer and Information Science, vol 1439. Springer, Cham. https://doi.org/10.1007/978-3-030-85347-1_36 ↩
KNNAvg( problem: nmoo.wrapped_problem.WrappedProblem, max_distance: float, n_neighbors: int = 5, distance_weight_type: str = 'uniform', *, name: str = 'knn_avg', **kwargs)
28 def __init__( 29 self, 30 problem: WrappedProblem, 31 max_distance: float, 32 n_neighbors: int = 5, # KNN 33 distance_weight_type: str = "uniform", 34 *, 35 name: str = "knn_avg", 36 **kwargs, 37 ): 38 """ 39 Constructor. 40 41 Args: 42 problem (`nmoo.wrapped_problem.WrappedProblem`): Noisy problem. For 43 memory optimization reasons, this should be a 44 `nmoo.wrapped_problem.WrappedProblem` as opposed to a pymoo 45 `Problem`. 46 distance_weight_type (str): Either `squared` or `uniform` (the 47 default). 48 max_distance (float): Distance cutoff. 49 n_neighbors (int): Number of neighbors to consider (the K in KNN). 50 name (str): An optional name for this problem. This will be used 51 when creating history dump files. Defaults to `knn_avg`. 52 """ 53 super().__init__(problem, name=name, **kwargs) 54 55 if distance_weight_type not in ["squared", "uniform"]: 56 raise ValueError( 57 "Parameter distance_weight_type must be either 'squared' or " 58 "'uniform'." 59 ) 60 self._distance_weight_mode = distance_weight_type 61 62 if max_distance < 0.0: 63 raise ValueError( 64 "Parameter max_distance must either be 'None' or >= 0." 65 ) 66 self._max_distance = max_distance 67 68 if n_neighbors <= 0: 69 raise ValueError("Parameter n_neighbors must be >= 1.") 70 self._n_neighbors = n_neighbors
Constructor.
Arguments:
- problem (
nmoo.wrapped_problem.WrappedProblem
): Noisy problem. For memory optimization reasons, this should be anmoo.wrapped_problem.WrappedProblem
as opposed to a pymooProblem
. - distance_weight_type (str): Either
squared
oruniform
(the default). - max_distance (float): Distance cutoff.
- n_neighbors (int): Number of neighbors to consider (the K in KNN).
- name (str): An optional name for this problem. This will be used
when creating history dump files. Defaults to
knn_avg
.
Inherited Members
- nmoo.wrapped_problem.WrappedProblem
- add_to_history
- add_to_history_x_out
- all_layers
- depth
- dump_all_histories
- dump_history
- ground_problem
- innermost_wrapper
- reseed
- start_new_run
- pymoo.core.problem.Problem
- evaluate
- do
- nadir_point
- ideal_point
- pareto_front
- pareto_set
- has_bounds
- has_constraints
- bounds
- name
- calc_constraint_violation