SHADE: Success-History Based Adaptive Differential Evolution
SHADE es una variante auto-adaptativa del algoritmo de evolución diferencial (Differential Evolution, DE), diseñada para resolver problemas de optimización continua con alta eficiencia y robustez. En el contexto de clustering con restricciones, SHADE ha demostrado ser eficaz para encontrar particiones de calidad optimizando una función objetivo que combina compacidad y violación de restricciones.
¿Qué es la Evolución Diferencial (DE)?
DE es un algoritmo evolutivo basado en poblaciones que optimiza una función objetivo real mediante la combinación lineal de soluciones. Sus operadores clave son:
- Mutación: combina soluciones para crear una nueva (vector mutante).
- Cruce (crossover): mezcla el vector mutante con uno original (vector trial).
- Selección: elige entre el vector original y el trial según el fitness.
Motivación de SHADE
Aunque DE es potente, su rendimiento depende fuertemente de los parámetros de control:
- Factor de escala \( F \)
- Tasa de cruce \( CR \)
SHADE resuelve este problema mediante una adaptación basada en la historia de éxito, es decir, aprende qué combinaciones de parámetros han funcionado bien en el pasado y los reutiliza con probabilidad creciente.
El algoritmo presenta los siguientes fases:
- Inicializar una población de soluciones con vectores reales.
- Para cada generación:
- Elegir un conjunto de padres.
- Generar un vector mutante usando una estrategia como current-to-pbest/1.
- Cruzar el mutante con el padre para obtener el trial.
- Evaluar la calidad del trial.
- Reemplazar si mejora la solución.
- Registrar los valores de \( F \) y \( CR \) que generaron soluciones exitosas.
- Actualizar una memoria histórica con los \( F \) y \( CR \) exitosos.
- Repetir hasta convergencia.
Success-History Adaptation
SHADE mantiene dos vectores de memoria:
- \( M_F \): historial de factores de escala exitosos.
- \( M_{CR} \): historial de tasas de cruce exitosas.
Para generar los parámetros de un nuevo individuo, SHADE:
- Selecciona aleatoriamente un índice \( k \) del historial.
- Usa una distribución Cauchy centrada en \( M_F[k] \) para \( F \).
- Usa una distribución Normal centrada en \( M_{CR}[k] \) para \( CR \).
- Los nuevos valores se ajustan si salen de sus rangos válidos.
Este mecanismo favorece gradualmente los valores que han tenido éxito, manteniendo diversidad.
Aplicación a Clustering con Restricciones
En clustering con restricciones, cada individuo representa una partición del conjunto de datos:
- Puede codificarse como un vector real que luego se decodifica a una asignación discreta.
- La función de fitness incluye:
- Variación intra-cluster (e.g., suma de distancias).
- Penalización por violación de must-link y cannot-link.
- La estrategia current-to-pbest/1 favorece la convergencia sin perder diversidad.
- SHADE puede integrar búsquedas locales para acelerar la explotación.
SHADE en Clustering con Restricciones
SHADE ha sido adaptado con éxito para abordar el problema de clustering con restricciones instancia-instancia, donde el objetivo es encontrar una partición de los datos que:
- Minimice la varianza intra-cluster (cohesión).
- Respete un conjunto de restricciones suaves tipo:
- Must-Link (ML): dos instancias deben ir al mismo cluster.
- Cannot-Link (CL): dos instancias no deben ir al mismo cluster.
Dado que estas restricciones pueden ser contradictorias o ruidosas, SHADE incorpora una función objetivo penalizada que permite tolerar violaciones a cambio de obtener una mejor calidad general de partición.
Representación de la Solución
En este contexto, cada individuo en la población de SHADE representa una partición de los datos. Hay varias formas de codificar esto:
- Una codificación entera directa (no diferenciable) donde cada posición representa la asignación de un punto a un cluster.
- Una codificación con claves aleatorias (random keys) que se traduce a clusters mediante un decodificador determinista.
- Una codificación real continua donde se utiliza un proceso de agrupamiento posterior (como agrupamiento por proximidad en un espacio latente).
Función Objetivo
La función de evaluación para cada individuo incluye:
Donde:
- \( \mu_i \) es el centroide del cluster \( C_i \).
- La función Infeasibility cuenta las restricciones ML y CL violadas.
- \( \lambda \) es un parámetro de penalización ajustable.
Este enfoque permite tratar restricciones como soft-constraints y controlar el grado de compromiso entre calidad de agrupamiento y cumplimiento estructural.
Referencia
Tanabe, R., & Fukunaga, A. (2013). Success-History Based Parameter Adaptation for Differential Evolution. IEEE Congress on Evolutionary Computation (CEC), pp. 71–78.
González-Almagro et al. (2020): SHADE se utilizó como núcleo en un algoritmo de clustering con restricciones basado en DE.
API
Bases: GeneticClustering
SHADE Clustering with Constraints (ShadeCC).
Adaptive genetic algorithm based on SHADE to solve clustering problems with constraints. It uses success history to dynamically adjust the parameters of differential evolution.
Attributes:
| Name | Type | Description |
|---|---|---|
population_size |
int
|
Number of solutions in the genetic population. |
n_clusters |
int
|
Target number of clusters. |
init |
str
|
Method for initializing centroids. |
max_iter |
int
|
Maximum number of generations. |
tol |
float
|
Convergence tolerance. |
constraints |
ConstraintMatrix
|
Must-link and cannot-link constraints. |
solution_archive |
ndarray
|
External solution archive to maintain diversity. |
Source code in clustlib/gac/shade.py
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | |
__init__(n_clusters=8, init='random', max_iter=300, tol=0.0001, custom_initial_centroids=None, constraints=None, population_size=20, memory_size=20)
Initialize the SHADE algorithm for clustering with constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_clusters
|
int
|
Number of clusters to generate. |
8
|
init
|
str
|
Method for initializing centroids. |
'random'
|
max_iter
|
int
|
Maximum number of iterations. |
300
|
tol
|
float
|
Tolerance for convergence. |
0.0001
|
custom_initial_centroids
|
Optional[ndarray]
|
User-defined centroids. |
None
|
constraints
|
Sequence[Sequence]
|
List of ML and CL constraints. |
None
|
population_size
|
int
|
Size of the genetic population. |
20
|
memory_size
|
int
|
Size of the memory to store successful solutions. |
20
|
Source code in clustlib/gac/shade.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
create_adaptive_parameter()
Generate new adaptive parameters CR and F.
Returns:
| Type | Description |
|---|---|
|
Tuple[float, float]: Pair of adapted (CR, F). |
Source code in clustlib/gac/shade.py
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | |
create_archive()
Initialize the external solution archive.
Source code in clustlib/gac/shade.py
121 122 123 124 125 126 127 128 129 130 131 | |
create_population()
Create the initial population of solutions.
Source code in clustlib/gac/shade.py
114 115 116 117 118 119 | |
crossover(parents, f_i, cr_i)
Perform differential crossover among multiple parents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parents
|
ndarray
|
Parent solutions [element, best, r1, r2]. |
required |
f_i
|
float
|
Scaling factor. |
required |
cr_i
|
float
|
Crossover rate. |
required |
Returns:
| Type | Description |
|---|---|
|
np.ndarray: Generated mutant chromosome. |
Source code in clustlib/gac/shade.py
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | |
get_instances(parents_idx)
Retrieve instances from the population and the external archive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parents_idx
|
ndarray
|
Indices of the selected parents. |
required |
Returns:
| Type | Description |
|---|---|
|
Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: Instances from the population and the external archive. |
Source code in clustlib/gac/shade.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | |
mutation()
Generate mutation on the current individual.
Returns:
| Type | Description |
|---|---|
|
Tuple[np.ndarray, float, float]: Generated mutant, cr_i, and f_i. |
Source code in clustlib/gac/shade.py
238 239 240 241 242 243 244 245 246 247 248 | |
randint(low, high=None, size=None, exclude=None)
staticmethod
Generate a random integer, excluding certain values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
int
|
Lower bound of the range. |
required |
high
|
int
|
Upper bound of the range. |
None
|
size
|
int
|
Number of values to generate. |
None
|
exclude
|
Sequence[int]
|
Values to exclude from the range. |
None
|
Returns:
| Type | Description |
|---|---|
|
np.ndarray: Array of random integers excluding the specified values. |
Source code in clustlib/gac/shade.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
save_adaptive(delta_fitness, cr_i, f_i)
Save successful parameters for future adaptation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
delta_fitness
|
float
|
Improvement obtained in fitness. |
required |
cr_i
|
float
|
Crossover rate used. |
required |
f_i
|
float
|
Scaling factor used. |
required |
Source code in clustlib/gac/shade.py
197 198 199 200 201 202 203 204 205 206 207 208 | |
select_parents()
Select parents from the population and the external archive.
Returns:
| Type | Description |
|---|---|
|
np.ndarray: Indices of the selected parents. |
Source code in clustlib/gac/shade.py
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
update_adaptive()
Update the H_CR and H_F histories with weighted averages.
Source code in clustlib/gac/shade.py
210 211 212 213 214 215 216 217 218 | |