English Русский 中文 Deutsch 日本語 Português
preview
Algoritmo de búsqueda por vecindad — Across Neighbourhood Search (ANS)

Algoritmo de búsqueda por vecindad — Across Neighbourhood Search (ANS)

MetaTrader 5Ejemplos |
226 0
Andrey Dik
Andrey Dik
Índice
  1. Introducción
  2. Aplicación del algoritmo
  3. Resultados de las pruebas


1. Introducción

En el mundo actual, el desarrollo de métodos de optimización eficientes desempeña un papel importante en la resolución de una serie de problemas que van desde las aplicaciones de ingeniería hasta la investigación en el aprendizaje automático y la inteligencia artificial. En este contexto, los algoritmos evolutivos metaheurísticos suponen potentes herramientas para resolver problemas de optimización complejos. No obstante, para mejorar aún más su rendimiento y eficacia, resulta necesario seguir desarrollando y modificando los métodos existentes, así como desarrollar nuevos algoritmos.

En el presente artículo, nos familiarizaremos con un algoritmo de optimización conocido como Across Neighborhood Search (ANS), propuesto por Guohua Wu en 2014 y basado en la búsqueda poblacional para la optimización numérica. El algoritmo ANS desarrollado representa un avance significativo en el campo de la optimización, y promete resolver una amplia variedad de problemas del mundo real con alta eficiencia y precisión. Hoy confirmaremos si es esto cierto o no. La idea básica de ANS consiste en modelar el comportamiento de un sistema multiagente en el que cada agente se mueve por el espacio de decisión, interactuando con sus vecinos e intercambiando información. Este enfoque ofrece una excelente exploración del espacio de búsqueda, pues combina la optimización local y global.

Así, veremos una descripción detallada de la estructura del algoritmo ANS y sus principios de funcionamiento, además de un análisis comparativo con los métodos de optimización ya existentes. El algoritmo ANS desarrollado nos descubre un nuevo camino en el campo de la optimización, permitiéndonos resolver una amplia gama de problemas con un alto rendimiento. Asimismo, en el contexto del desarrollo de la inteligencia artificial, cabe señalar que el algoritmo ANS supone un paso importante hacia métodos de optimización más flexibles e inteligentes, capaces de considerar la especificidad del problema y la dinámica del entorno.

2. Aplicación del algoritmo

El algoritmo Across Neighborhood Search (ANS) es un método de optimización que usa ideas del campo de los algoritmos evolutivos y la metaheurística y está diseñado para encontrar soluciones óptimas en el espacio de parámetros de un problema.

Vamos a destacar las principales características del ANS:

  • Búsqueda de vecindad: los agentes exploran la vecindad de las soluciones actuales, lo cual les permite encontrar óptimos locales de forma más eficiente.
  • Uso de la distribución normal: El ANS utiliza la distribución normal para generar nuevos valores de los parámetros.
  • Colecciones de soluciones: el ANS utiliza colecciones de las mejores soluciones para ayudar a guiar al algoritmo en varias direcciones prometedoras a la vez.

En el ANS, un grupo de individuos realiza una búsqueda conjunta en el espacio de soluciones para ejecutar de forma óptima el problema de optimización considerado. La idea básica del algoritmo es mantener y actualizar de forma dinámica la colección de soluciones superiores encontradas por los individuos hasta el momento. En cada generación, un individuo busca directamente en la vecindad varias soluciones distintas según una distribución de probabilidad normal. De esta forma, se explota la idea de que existen varias soluciones potencialmente buenas a la vez, ya que no se sabe de antemano cuál será la mejor.

A continuación analizaremos una descripción completa del algoritmo ANS con sus fórmulas y pasos, según el concepto del autor. El ANS realiza los siguientes pasos:

1. Inicialización de parámetros:

  • Tamaño de la población m
  • Recopilación de un conjunto de las mejores soluciones c
  • Desviación típica de la distribución gaussiana sigma
  • Dimensionalidad del espacio de búsqueda D
  • Número máximo de generaciones MaxG

2. Inicialización de la población. Inicialización aleatoria de la posición de cada individuo de la población en el espacio de búsqueda.

3. Actualización de las mejores soluciones. Cada individuo de la población actualiza su posición actual explorando la vecindad de las mejores soluciones de la colección usando una distribución normal.

4. Selección de la coordenada a buscar. Selección de un número aleatorio n (across-search degree) para determinar la coordenada actual de la posición de un individuo en el espacio de soluciones.

5. Actualización de la posición del individuo. Actualización de la posición del individuo i según el paso anterior.

Fórmulas y operaciones:

1. Actualización de la posición pos_i del individuo i (exploración de la vecindad de la solución a partir de la colección):

  • La posición del individuo i se actualiza usando una distribución gaussiana: pos_i =  r_g + G (r_g - pos_i), donde:
  • G - valor aleatorio de la distribución gaussiana
  • r_g - posición de la mejor solución de la colección

2. Actualización de la posición pos_i del individuo i (exploración de la vecindad de la mejor solución propia del individuo):

  • La posición del individuo i se actualiza usando una distribución gaussiana: pos_i = r_i + G (r_i - pos_i), donde:
  • G - valor aleatorio de la distribución gaussiana
  • r_i - posición de la mejor decisión del individuo

3. Actualización de un conjunto de mejores soluciones:

  • La recopilación de las mejores soluciones se actualiza según las nuevas posiciones de los individuos.

De esta forma, las fórmulas reflejarán el mecanismo de búsqueda de un individuo i en la vecindad de su mejor solución r_i, así como en la vecindad de otras mejores soluciones r_g de la colección R. Los pasos mencionados del algoritmo representan la lógica básica del método ANS para resolver problemas de optimización. Esta incluye la inicialización de los parámetros, la inicialización aleatoria de las posiciones de los individuos, la actualización de las posiciones de los individuos dada la vecindad de las mejores soluciones y la actualización de la colección de mejores soluciones. El algoritmo seguirá funcionando hasta que se cumple la condición de parada.

La búsqueda basada en las mejores soluciones o individuos es una técnica de búsqueda común y frecuentemente usada en los algoritmos basados en estrategias poblacionales, aunque los procesos que implementan este mecanismo de búsqueda pueden diferir para distintos algoritmos de optimización. De hecho, en este caso, además de la población principal de agentes, se introducirá una población adicional: una colección de las mejores soluciones (direcciones potenciales de búsqueda). El tamaño de la colección se define en los parámetros externos del algoritmo y puede ser mayor o menor que el tamaño de la población principal.

La estrategia de búsqueda en el algoritmo ANS empieza poblando la colección de mejores soluciones, y luego procede a buscar en la vecindad de las mejores soluciones de la colección y las mejores soluciones individuales de cada agente. El tamaño de la desviación estándar sigma desempeñará un papel clave en el algoritmo. Los valores pequeños de sigma ofrecen una exploración más amplia del espacio de búsqueda, mientras que los valores más altos permiten refinar las soluciones estrechando sus vecindades. Este parámetro del algoritmo es responsable del equilibrio entre intensificación y diversificación de la búsqueda. En algunos algoritmos, este equilibrio está vinculado con el número de época actual para permitir cambios dinámicos de equilibrio entre exploración y refinamiento, pero en este caso los autores definieron el ajuste de equilibrio como un parámetro ANS externo.

Así, el algoritmo ANS combina la explotación de las mejores soluciones encontradas (mediante la búsqueda en sus vecindades) y la exploración del espacio de soluciones (mediante la búsqueda en las vecindades de las mejores soluciones de los propios individuos). En teoría, esto debería proporcionar un buen equilibrio entre la intensificación y la diversificación de la búsqueda.

Ahora vamos a escribir y analizar el código del algoritmo ANS. Primero definiremos la estructura "S_ANS_Agent" que se utilizará para representar a los agentes en el algoritmo ANS. Campos de la estructura:

  • c: array para almacenar las coordenadas del agente.
  • cBest: array para almacenar las mejores coordenadas del agente.
  • f: valor de aptitud (fitness) del agente.
  • fBest: mejor valor de adaptación del agente.
  • Init(int coords): método de inicialización, establece los tamaños de los arrays "c" y "cBest" y establece los valores iniciales de "f" y "fBest".

Esta parte del código representa la estructura básica de un agente, un array de los cuales (agentes) representará la población básica en el algoritmo ANS.

//——————————————————————————————————————————————————————————————————————————————
struct S_ANS_Agent
{
    double c     []; //coordinates
    double cBest []; //best coordinates
    double f;        //fitness
    double fBest;    //best fitness

    void Init (int coords)
    {
      ArrayResize (c,     coords);
      ArrayResize (cBest, coords);
      f     = -DBL_MAX;
      fBest = -DBL_MAX;
    }
};
//—————————————————————————————————————————————————————————————————————————————

Para describir la colección de mejores soluciones, escribiremos la estructura "S_Collection", que se utilizará para almacenar información sobre las mejores coordenadas en el espacio de búsqueda y su correspondiente valor de aptitud. La estructura contendrá los campos siguientes:

  • c: array para almacenar coordenadas.
  • f: valor de aptitud para una solución dada a un problema de la colección.
  • Init(int coords): método de inicialización; establece el tamaño del array "c" y el valor inicial "f" al mínimo valor posible de tipo "double".
//——————————————————————————————————————————————————————————————————————————————
struct S_Collection
{
    double c []; //coordinates
    double f;    //fitness

    void Init (int coords)
    {
      ArrayResize (c, coords);
      f = -DBL_MAX;
    }
};
//——————————————————————————————————————————————————————————————————————————————

Luego declararemos una clase "C_AO_ANS", que será heredera de la clase básica "C_AO" y supondrá una implementación del algoritmo Across Neighbourhood Search (ANS). He aquí algunos puntos clave:

  • ao_name, ao_desc, ao_link: propiedades que describen el algoritmo ANS.
  • popSize: tamaño de la población.
  • collectionSize, sigma, range, collChoiceProbab: parámetros del algoritmo ANS.
  • SetParams(): método de parametrización.
  • Init(), Moving(), Revision(): métodos para inicializar, mover agentes y actualizar la población y la colección de soluciones.
  • S_ANS_Agent, S_Collection: estructuras para guardar los datos del agente y la colección.
//——————————————————————————————————————————————————————————————————————————————
class C_AO_ANS : public C_AO
{
  public: //--------------------------------------------------------------------
  ~C_AO_ANS () { }
  C_AO_ANS ()
  {
    ao_name = "ANS";
    ao_desc = "Across Neighbourhood Search";
    ao_link = "https://www.mql5.com/es/articles/15049";

    popSize          = 50;   //population size

    collectionSize   = 20;   //Best solutions collection
    sigma            = 3.0;  //Form of normal distribution
    range            = 0.5;  //Range of values dispersed
    collChoiceProbab = 0.8;  //Collection choice probab

    ArrayResize (params, 5);

    params [0].name = "popSize";          params [0].val = popSize;
    params [1].name = "collectionSize";   params [1].val = collectionSize;
    params [2].name = "sigma";            params [2].val = sigma;
    params [3].name = "range";            params [3].val = range;
    params [4].name = "collChoiceProbab"; params [4].val = collChoiceProbab;
  }

  void SetParams ()
  {
    popSize          = (int)params [0].val;
    collectionSize   = (int)params [1].val;
    sigma            = params      [2].val;
    range            = params      [3].val;
  }

  bool Init (const double &rangeMinP  [], //minimum search range
             const double &rangeMaxP  [], //maximum search range
             const double &rangeStepP [], //step search
             const int     epochsP = 0);  //number of epochs

  void Moving   ();
  void Revision ();

  //----------------------------------------------------------------------------
  int    collectionSize;    //Best solutions collection
  double sigma;             //Form of normal distribution
  double range;             //Range of values dispersed
  double collChoiceProbab;  //Collection choice probab

  S_ANS_Agent agent [];

  private: //-------------------------------------------------------------------
  S_Collection coll     [];
  S_Collection collTemp [];
};
//——————————————————————————————————————————————————————————————————————————————

El método "Init" inicializa los parámetros del algoritmo ANS (Across Neighbourhood Search).

  • rangeMinP, rangeMaxP, rangeStepP: arrays que representan el mínimo, el máximo y el paso del rango de búsqueda.
  • epochsP: número de épocas (generaciones).

Método interior:

  • Comprobamos que se hayan inicializado correctamente los parámetros estándar con "StandardInit".
  • Creamos los arrays de agentes "agent" y colecciones "coll" (una segunda población para almacenar las mejores soluciones) y "collTemp" (un array temporal para clasificación de la colección).
  • Para cada agente y colección, se llama al método "Init" para establecer los valores iniciales.

Este método desempeña un papel esencial en la preparación del algoritmo ANS para realizar la optimización. Debemos considerar que los arrays "coll" y "collTemp" se inicializan con un tamaño doble con respecto al parámetro "collectionSize".  Así se garantizará que los nuevos agentes añadidos a la colección se sitúen en la segunda mitad del array. A continuación, se clasificará toda la colección y solo la primera mitad, que contiene los mejores agentes, se utilizará para el trabajo posterior.

//——————————————————————————————————————————————————————————————————————————————
bool C_AO_ANS::Init (const double &rangeMinP  [], //minimum search range
                     const double &rangeMaxP  [], //maximum search range
                     const double &rangeStepP [], //step search
                     const int     epochsP = 0)   //number of epochs
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //----------------------------------------------------------------------------
  ArrayResize (agent, popSize);
  for (int i = 0; i < popSize; i++) agent [i].Init (coords);

  ArrayResize (coll,     collectionSize * 2);
  ArrayResize (collTemp, collectionSize * 2);
  for (int i = 0; i < collectionSize * 2; i++)
  {
    coll     [i].Init (coords);
    collTemp [i].Init (coords);
  }

  return true;
}
//——————————————————————————————————————————————————————————————————————————————

El método "Moving" realizará el movimiento (desplazamiento) de los agentes en el algoritmo ANS. Vamos a desglosar este código con detalle:

1. Inicialización (si "revision" es igual a "false"):

  • Si es el primer paso (primera época), entonces para cada agente:
    • Se generará un valor aleatorio "val" en un rango comprendido entre "rangeMin[c]" y "rangeMax[c]".
    • El operador "SeInDiSp" se aplica para considerar el paso "rangeStep[c]".
    • El valor "val" se asigna a las coordenadas del agente "agent[i].c[c]".
    • El valor "val" también se asigna a las mejores coordenadas del agente "agent[i].cBest[c]" (en esta fase se desconocen los valores de adaptación de los agentes, por lo que las mejores coordenadas serán iguales a las coordenadas iniciales actuales).
    • El valor "val" se asigna al array de agentes "a[i].c[c]".

2. Desplazamiento de agentes (si "revisión" es igual a "true"):

  • Para cada agente y cada coordenada:
    • Si el número aleatorio es menor que "collChoiceProbab", se selecciona una solución aleatoria de la colección:
      • Se selecciona un índice aleatorio "ind" de la colección (hasta que se encuentre una solución no vacía).
      • El valor "p" se toma de las coordenadas actuales del agente.
      • El valor "r" se toma de la solución seleccionada en la colección.
    • En caso contrario, se usan las mejores coordenadas del agente:
      • El valor "p" se toma de las coordenadas actuales del agente.
      • El valor "r" se toma de las mejores coordenadas del agente.
    • Se calculan la distancia "dist" y el alcance ("min" y "max") del desplazamiento.
    • Los valores "min" y "max" se limitan a los rangos "rangeMin[c]" y "rangeMax[c]".
    • Se aplica una distribución normal con los parámetros "r", "min", "max" y "sigma".
    • El valor "val" se asigna a las coordenadas del agente "agent[i].c[c]".
    • El valor "val" también se asigna al array de agentes "a[i].c[c]".

Este código actualiza las coordenadas de los agentes en el algoritmo ANS, dadas las coordenadas propias de los mejores agentes y las soluciones de la colección.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ANS::Moving ()
{
  double val = 0.0;

  //----------------------------------------------------------------------------
  if (!revision)
  {
    for (int i = 0; i < popSize; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        val = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        val = u.SeInDiSp  (val, rangeMin [c], rangeMax [c], rangeStep [c]);

        agent [i].c     [c] = val;
        agent [i].cBest [c] = val;

        a [i].c [c] = val;
      }
    }

    revision = true;
    return;
  }

  //----------------------------------------------------------------------------
  double min  = 0.0;
  double max  = 0.0;
  double dist = 0.0;
  int    ind  = 0;
  double r    = 0.0;
  double p    = 0.0;

  for (int i = 0; i < popSize; i++)
  {
    for (int c = 0; c < coords; c++)
    {
      if (u.RNDprobab () < collChoiceProbab)
      {
        do ind = u.RNDminusOne (collectionSize);
        while (coll [ind].f == -DBL_MAX);

        p = agent [i].c   [c];
        r = coll  [ind].c [c];

      }
      else
      {
        p = agent [i].c     [c];
        r = agent [i].cBest [c];
      }

      dist = fabs (p - r) * range;
      min  = r - dist;
      max  = r + dist;

      if (min < rangeMin [c]) min = rangeMin [c];
      if (max > rangeMax [c]) max = rangeMax [c];

      val = u.GaussDistribution (r, min, max, sigma);
      val = u.SeInDiSp (val, rangeMin [c], rangeMax [c], rangeStep [c]);

      agent [i].c [c] = val;
      a     [i].c [c] = val;
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

El método "Revision" realiza una revisión (actualización) de los agentes y de la colección en el algoritmo ANS. Aquí tenemos lo más destacado:

  • Primera parte del método: busca un agente cuya aptitud resulte mejor que la solución global con aptitud "fB" y almacena sus coordenadas en el array "cB".
  • Segunda parte del método: actualiza las mejores coordenadas de los agentes "agent[i].cBest" según su aptitud actual "a[i].f".
  • Tercera parte del método: actualiza la colección "coll" basándose en las mejores coordenadas de los agentes.
  • Clasifica la colección.

Este método desempeña un papel importante en la actualización de los agentes y la colección de soluciones durante la ejecución del algoritmo. La población de agentes se coloca en la segunda parte de la colección; luego se realiza la clasificación de la colección y se utiliza la primera mitad de la colección que contiene las mejores soluciones.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ANS::Revision ()
{
  //----------------------------------------------------------------------------
  int ind = -1;

  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > fB)
    {
      fB = a [i].f;
      ind = i;
    }
  }

  if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY);

  //----------------------------------------------------------------------------
  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > agent [i].fBest)
    {
      agent [i].fBest = a [i].f;
      ArrayCopy (agent [i].cBest, a [i].c, 0, 0, WHOLE_ARRAY);
    }
  }

  //----------------------------------------------------------------------------
  int cnt = 0;
  for (int i = collectionSize; i < collectionSize * 2; i++)
  {
    if (cnt < popSize)
    {
      coll [i].f = agent [cnt].fBest;
      ArrayCopy (coll [i].c, agent [cnt].cBest, 0, 0, WHOLE_ARRAY);
      cnt++;
    }
    else break;
  }

  u.Sorting (coll, collTemp, collectionSize * 2);
}
//——————————————————————————————————————————————————————————————————————————————


3. Resultados de las pruebas

Impresión del rendimiento del algoritmo ANS en un banco de pruebas con funciones de prueba:

ANS|Across Neighbourhood Search|50.0|100.0|8.0|1.0|0.6|
=============================
5 Hilly's; Func runs: 10000; result: 0.9494753644543816
25 Hilly's; Func runs: 10000; result: 0.8477633752716718
500 Hilly's; Func runs: 10000; result: 0.43857039929159747
=============================
5 Forest's; Func runs: 10000; result: 0.9999999999988883
25 Forest's; Func runs: 10000; result: 0.9233446583489741
500 Forest's; Func runs: 10000; result: 0.3998822848099108
=============================
5 Megacity's; Func runs: 10000; result: 0.709230769230769
25 Megacity's; Func runs: 10000; result: 0.6347692307692309
500 Megacity's; Func runs: 10000; result: 0.2309076923076936
=============================
All score: 6.13394 (68.15%)

El ANS muestra unos resultados impresionantes en todas las funciones de prueba. Bien, ahora podemos disfrutar de la visualización del funcionamiento de este algoritmo en el banco de pruebas. Los resultados del ANS son realmente asombrosos, pero surgen algunos problemas a la hora de visualizarlos. En particular, llama la atención el comportamiento de la población, que parece desaparecer del campo visual. Podemos observar que el espacio de soluciones se despeja y el paisaje de características queda sin agentes. Esto solo puede significar una cosa: a pesar de los excelentes resultados del algoritmo, la población resulta propensa a la degeneración. La colección de soluciones excelentes está plagada de soluciones muy similares, y simplemente no se pueden crear nuevas soluciones porque todas ellas se derivan de las ya existentes.

Semejante dinámica de la población puede indicar la necesidad de perfeccionar los mecanismos para mantener la diversidad en la población. Puede que merezca la pena plantearse añadir un operador de mutación o introducir otros mecanismos que mantengan una mayor diversidad de soluciones durante la optimización. Esto servirá para evitar la degeneración de la población y proporcionará un algoritmo más estable.

Hilly

  ANS en la función de prueba Hilly.

Forest

  ANS en la función de prueba Forest.

Megacity

  ANS en la función de prueba Megacity.

El algoritmo analizado en este artículo se sitúa con seguridad en la segunda línea de la tabla de clasificación. Los comentarios resultan innecesarios, pero podemos destacar ciertos puntos esenciales: el algoritmo muestra una escalabilidad impresionante, manteniendo su capacidad de búsqueda incluso con problemas de grandes dimensionalidad.  

AO Description Hilly Hilly final Forest Forest final Megacity (discrete) Megacity final Final result % de MAX
10 p (5 F) 50 p (25 F) 1000 p (500 F) 10 p (5 F) 50 p (25 F) 1000 p (500 F) 10 p (5 F) 50 p (25 F) 1000 p (500 F)
1 BGA binary genetic algorithm 0,99989 0,99518 0,42835 2,42341 0,96153 0,96181 0,32027 2,24360 0,91385 0,95908 0,24220 2,11512 6,782 75,36
2 ANS across neighbourhood search 0,94948 0,84776 0,43857 2,23581 1,00000 0,92334 0,39988 2,32323 0,70923 0,63477 0,23091 1,57491 6,134 68,15
3 CLA code lock algorithm 0,95345 0,87107 0,37590 2,20042 0,98942 0,91709 0,31642 2,22294 0,79692 0,69385 0,19303 1,68380 6,107 67,86
4 (P+O)ES (P+O) evolution strategies 0,92256 0,88101 0,40021 2,20379 0,97750 0,87490 0,31945 2,17185 0,67385 0,62985 0,18634 1,49003 5,866 65,17
5 CTA comet tail algorithm 0,95346 0,86319 0,27770 2,09435 0,99794 0,85740 0,33949 2,19484 0,88769 0,56431 0,10512 1,55712 5,846 64,96
6 SDSm stochastic diffusion search M 0,93066 0,85445 0,39476 2,17988 0,99983 0,89244 0,19619 2,08846 0,72333 0,61100 0,10670 1,44103 5,709 63,44
7 ESG evolution of social groups 0,99906 0,79654 0,35056 2,14616 1,00000 0,82863 0,13102 1,95965 0,82333 0,55300 0,04725 1,42358 5,529 61,44
8 SIA simulated isotropic annealing 0,95784 0,84264 0,41465 2,21513 0,98239 0,79586 0,20507 1,98332 0,68667 0,49300 0,09053 1,27020 5,469 60,76
9 ACS artificial cooperative search 0,75547 0,74744 0,30407 1,80698 1,00000 0,88861 0,22413 2,11274 0,69077 0,48185 0,13322 1,30583 5,226 58,06
10 TSEA turtle shell evolution algorithm 0,96798 0,64480 0,29672 1,90949 0,99449 0,61981 0,22708 1,84139 0,69077 0,42646 0,13598 1,25322 5,004 55,60
11 DE differential evolution 0,95044 0,61674 0,30308 1,87026 0,95317 0,78896 0,16652 1,90865 0,78667 0,36033 0,02953 1,17653 4,955 55,06
12 CRO chemical reaction optimisation 0,94629 0,66112 0,29853 1,90593 0,87906 0,58422 0,21146 1,67473 0,75846 0,42646 0,12686 1,31178 4,892 54,36
13 BSA bird swarm algorithm 0,89306 0,64900 0,26250 1,80455 0,92420 0,71121 0,24939 1,88479 0,69385 0,32615 0,10012 1,12012 4,809 53,44
14 HS harmony search 0,86509 0,68782 0,32527 1,87818 0,99999 0,68002 0,09590 1,77592 0,62000 0,42267 0,05458 1,09725 4,751 52,79
15 SSG saplings sowing and growing 0,77839 0,64925 0,39543 1,82308 0,85973 0,62467 0,17429 1,65869 0,64667 0,44133 0,10598 1,19398 4,676 51,95
16 (PO)ES (PO) evolution strategies 0,79025 0,62647 0,42935 1,84606 0,87616 0,60943 0,19591 1,68151 0,59000 0,37933 0,11322 1,08255 4,610 51,22
17 BSO brain storm optimization 0,93736 0,57616 0,29688 1,81041 0,93131 0,55866 0,23537 1,72534 0,55231 0,29077 0,11914 0,96222 4,498 49,98
18 WOAm wale optimization algorithm M 0,84521 0,56298 0,26263 1,67081 0,93100 0,52278 0,16365 1,61743 0,66308 0,41138 0,11357 1,18803 4,476 49,74
19 ACOm ant colony optimization M 0,88190 0,66127 0,30377 1,84693 0,85873 0,58680 0,15051 1,59604 0,59667 0,37333 0,02472 0,99472 4,438 49,31
20 BFO-GA bacterial foraging optimization - ga 0,89150 0,55111 0,31529 1,75790 0,96982 0,39612 0,06305 1,42899 0,72667 0,27500 0,03525 1,03692 4,224 46,93
21 MEC mind evolutionary computation 0,69533 0,53376 0,32661 1,55569 0,72464 0,33036 0,07198 1,12698 0,52500 0,22000 0,04198 0,78698 3,470 38,55
22 IWO invasive weed optimization 0,72679 0,52256 0,33123 1,58058 0,70756 0,33955 0,07484 1,12196 0,42333 0,23067 0,04617 0,70017 3,403 37,81
23 Micro-AIS micro artificial immune system 0,79547 0,51922 0,30861 1,62330 0,72956 0,36879 0,09398 1,19233 0,37667 0,15867 0,02802 0,56335 3,379 37,54
24 COAm cuckoo optimization algorithm M 0,75820 0,48652 0,31369 1,55841 0,74054 0,28051 0,05599 1,07704 0,50500 0,17467 0,03380 0,71347 3,349 37,21
25 SDOm spiral dynamics optimization M 0,74601 0,44623 0,29687 1,48912 0,70204 0,34678 0,10944 1,15826 0,42833 0,16767 0,03663 0,63263 3,280 36,44
26 NMm Nelder-Mead method M 0,73807 0,50598 0,31342 1,55747 0,63674 0,28302 0,08221 1,00197 0,44667 0,18667 0,04028 0,67362 3,233 35,92
27 FAm firefly algorithm M 0,58634 0,47228 0,32276 1,38138 0,68467 0,37439 0,10908 1,16814 0,28667 0,16467 0,04722 0,49855 3,048 33,87
28 GSA gravitational search algorithm 0,64757 0,49197 0,30062 1,44016 0,53962 0,36353 0,09945 1,00260 0,32667 0,12200 0,01917 0,46783 2,911 32,34
29 BFO bacterial foraging optimization 0,61171 0,43270 0,31318 1,35759 0,54410 0,21511 0,05676 0,81597 0,42167 0,13800 0,03195 0,59162 2,765 30,72
30 ABC artificial bee colony 0,63377 0,42402 0,30892 1,36671 0,55103 0,21874 0,05623 0,82600 0,34000 0,14200 0,03102 0,51302 2,706 30,06
31 BA bat algorithm 0,59761 0,45911 0,35242 1,40915 0,40321 0,19313 0,07175 0,66810 0,21000 0,10100 0,03517 0,34617 2,423 26,93
32 SA simulated annealing 0,55787 0,42177 0,31549 1,29513 0,34998 0,15259 0,05023 0,55280 0,31167 0,10033 0,02883 0,44083 2,289 25,43
33 IWDm intelligent water drops M 0,54501 0,37897 0,30124 1,22522 0,46104 0,14704 0,04369 0,65177 0,25833 0,09700 0,02308 0,37842 2,255 25,06
34 PSO particle swarm Optimization 0,59726 0,36923 0,29928 1,26577 0,37237 0,16324 0,07010 0,60572 0,25667 0,08000 0,02157 0,35823 2,230 24,77
35 Boids boids algorithm 0,43340 0,30581 0,25425 0,99346 0,35718 0,20160 0,15708 0,71586 0,27846 0,14277 0,09834 0,51957 2,229 24,77
36 MA monkey algorithm 0,59107 0,42681 0,31816 1,33604 0,31138 0,14069 0,06612 0,51819 0,22833 0,08567 0,02790 0,34190 2,196 24,40
37 SFL shuffled frog-leaping 0,53925 0,35816 0,29809 1,19551 0,37141 0,11427 0,04051 0,52618 0,27167 0,08667 0,02402 0,38235 2,104 23,38
38 FSS fish school search 0,55669 0,39992 0,31172 1,26833 0,31009 0,11889 0,04569 0,47467 0,21167 0,07633 0,02488 0,31288 2,056 22,84
39 RND random 0,52033 0,36068 0,30133 1,18234 0,31335 0,11787 0,04354 0,47476 0,25333 0,07933 0,02382 0,35648 2,014 22,37
40 GWO grey wolf optimizer 0,59169 0,36561 0,29595 1,25326 0,24499 0,09047 0,03612 0,37158 0,27667 0,08567 0,02170 0,38403 2,009 22,32
41 CSS charged system search 0,44252 0,35454 0,35201 1,14907 0,24140 0,11345 0,06814 0,42299 0,18333 0,06300 0,02322 0,26955 1,842 20,46
42 EM electroMagnetism-like algorithm 0,46250 0,34594 0,32285 1,13129 0,21245 0,09783 0,10057 0,41085 0,15667 0,06033 0,02712 0,24412 1,786 19,85


Esta parte del artículo suele ir seguida de las conclusiones. En este caso, sin embargo, creo que resulta demasiado pronto para sacar conclusiones definitivas. Antes de sacar conclusiones de los resultados, veamos primero las representaciones visuales tradicionales de los mismos, en este caso, una tabla de clasificación coloreada y un histograma que muestra la posición de los algoritmos entre sí en una escala del 100% a partir del resultado teórico máximo. Estos datos ilustrativos nos ayudarán a comprender y evaluar mejor el rendimiento del ANS en comparación con otros métodos.

Tab

Figura 1. Gradación por colores de los algoritmos según sus respectivas pruebas. Los resultados superiores o iguales a 0,99 aparecen resaltados en blanco.

chart

Figura 2. Histograma de los resultados de las pruebas de los algoritmos (en una escala de 0 a 100, cuanto mayor, mejor),

donde 100 es el máximo resultado teórico posible; el script para calcular la tabla de clasificación está en el archivo)

Más arriba en el artículo, hemos señalado la tendencia de la población del algoritmo ANS a degenerar. Para solventar esta importante deficiencia, hemos decidido modificar el algoritmo añadiendo un operador de mutación. En este caso, la mutación sería la probabilidad gaussiana de obtener una nueva coordenada en la vecindad de la mejor solución del agente, pero oscilando entre el valor mínimo aceptable y el máximo para la coordenada correspondiente. Para ello, tendremos que hacer algunos cambios en el método Moving.

Ahora veremos qué cambios hemos realizado en el código y describiremos brevemente la lógica del método:

  • Si el número aleatorio es inferior a 0,005, la mutación se producirá utilizando una distribución normal.
  • En caso contrario, elegiremos una solución aleatoria de la colección o utilizaremos las mejores coordenadas del agente.
  • Para una distribución normal se calcularán la distancia y el rango.
  • Luego aplicaremos la distribución normal para obtener nuevos valores de coordenadas.
//----------------------------------------------------------------------------
double min  = 0.0;
double max  = 0.0;
double dist = 0.0;
int    ind  = 0;
double r    = 0.0;
double p    = 0.0;

for (int i = 0; i < popSize; i++)
{
  for (int c = 0; c < coords; c++)
  {
    if (u.RNDprobab () < 0.005)
    {
      val = u.GaussDistribution (agent [i].cBest [c], rangeMin [c], rangeMax [c], sigma);
      val = u.SeInDiSp (val, rangeMin [c], rangeMax [c], rangeStep [c]);
    }
    else
    {
      if (u.RNDprobab () < collChoiceProbab)
      {
        do ind = u.RNDminusOne (collectionSize);
        while (coll [ind].f == -DBL_MAX);

        p = agent [i].c   [c];
        r = coll  [ind].c [c];
 
      }
      else
      {
        p = agent [i].c     [c];
        r = agent [i].cBest [c];
      }

      dist = fabs (p - r) * range;
      min  = r - dist;
      max  = r + dist;

      if (min < rangeMin [c]) min = rangeMin [c];
      if (max > rangeMax [c]) max = rangeMax [c];

      val = u.GaussDistribution (r, min, max, sigma);
      val = u.SeInDiSp (val, rangeMin [c], rangeMax [c], rangeStep [c]);
    }
      
    agent [i].c [c] = val;
    a     [i].c [c] = val;
  }
}

Tras añadir el operador de mutación, el algoritmo continúa explorando el espacio de búsqueda en cualquier número de épocas, como se demuestra en la figura 3 (captura de pantalla de la visualización del funcionamiento del algoritmo).

Agent left

Figura 3. Los agentes permanecen, la población no degenera (parámetro mut = 0,005)

De los resultados del algoritmo ANS en funciones de prueba con diferente número de coordenadas y distintos valores del operador de mutación (mut) podemos extraer la siguiente conclusión:
  • El operador de mutación con el parámetro "mut 0,1" tiene un efecto negativo en el resultado global. Cuando el factor de mutación es tan significativo (10% del número total de operaciones en cada coordenada), se observa un deterioro de los resultados del algoritmo. Por ello, hemos decidido reducir sistemáticamente este parámetro. Reduciendo el valor del parámetro hemos obtenido mejores resultados; nos hemos decidido por un valor de 0,005. Este coeficiente ha sido suficiente para evitar la degeneración de la población y, al mismo tiempo, proporcionar una mejora en el rendimiento del algoritmo, como se refleja en las impresiones siguientes.

Resultados del algoritmo con una probabilidad de mutación mut = 0,1:

500 Megacity's; Func runs: 10000; result: 0.19352307692307838

=============================
All score: 6.05103 (67.23%)
ANS|Across Neighbourhood Search|50.0|100.0|8.0|1.0|0.6|
=============================
5 Hilly's; Func runs: 10000; result: 0.9534829314854332
25 Hilly's; Func runs: 10000; result: 0.8136803288623282
500 Hilly's; Func runs: 10000; result: 0.31144979106165716
=============================
5 Forest's; Func runs: 10000; result: 0.9996561274415626
25 Forest's; Func runs: 10000; result: 0.81670393859872
500 Forest's; Func runs: 10000; result: 0.25620559379918284
=============================
5 Megacity's; Func runs: 10000; result: 0.8753846153846153
25 Megacity's; Func runs: 10000; result: 0.5778461538461539
500 Megacity's; Func runs: 10000; result: 0.13375384615384744
=============================
All score: 5.73816 (63.76%)

Resultados del algoritmo con una probabilidad de mutación mut = 0,01:

ANS|Across Neighbourhood Search|50.0|100.0|8.0|1.0|0.6|

=============================
5 Hilly's; Func runs: 10000; result: 0.9073657389037575
25 Hilly's; Func runs: 10000; result: 0.871278233418226
500 Hilly's; Func runs: 10000; result: 0.3960769225373809
=============================
5 Forest's; Func runs: 10000; result: 0.989394440004635
25 Forest's; Func runs: 10000; result: 0.9513150500729907
500 Forest's; Func runs: 10000; result: 0.35407610928209116
=============================
5 Megacity's; Func runs: 10000; result: 0.7492307692307691
25 Megacity's; Func runs: 10000; result: 0.6387692307692309
500 Megacity's; Func runs: 10000; result: 0.19352307692307838
=============================
All score: 6.05103 (67.23%)

Resultados del algoritmo con una probabilidad de mutación mut = 0,005:

ANS|Across Neighbourhood Search|50.0|100.0|8.0|1.0|0.6|
=============================
5 Hilly's; Func runs: 10000; result: 0.949632264944664
25 Hilly's; Func runs: 10000; result: 0.871206955779846
500 Hilly's; Func runs: 10000; result: 0.40738389742274217
=============================
5 Forest's; Func runs: 10000; result: 0.9924803131691761
25 Forest's; Func runs: 10000; result: 0.9493489251290264
500 Forest's; Func runs: 10000; result: 0.3666276564633121
=============================
5 Megacity's; Func runs: 10000; result: 0.8061538461538461
25 Megacity's; Func runs: 10000; result: 0.6732307692307691
500 Megacity's; Func runs: 10000; result: 0.20844615384615534
=============================
All score: 6.22451 (69.16%)


Conclusiones

Ahora que hemos analizado los resultados junto con el operador de mutación, podemos sacar las siguientes conclusiones:

1. Simplicidad y facilidad de aplicación.
2. Equilibrio entre exploración y explotación.
3. Eficacia en la resolución de distintos tipos de problemas.
4. Adaptabilidad a diferentes tareas.
5. Potencial de mejora.

Así pues, el ANS es un algoritmo de optimización sencillo pero eficiente que muestra resultados competitivos en una amplia gama de problemas y tiene potencial para seguir desarrollándose.

Ventajas e inconvenientes generales del algoritmo de búsqueda por vecindad (ANS):

Ventajas:

  1. Buena convergencia en varios tipos de funciones.
  2. Muy rápido.
  3. Implementación sencilla.
  4. Excelente escalabilidad.

Desventajas:

  1. A veces se atasca en los extremos locales.

Adjuntamos al artículo un archivo con las versiones actuales de los códigos de los algoritmos. El autor de este artículo no se responsabiliza de la exactitud absoluta de la descripción de los algoritmos canónicos, muchos de ellos han sido modificados para mejorar las capacidades de búsqueda. Las conclusiones y juicios presentados en los artículos se basan en los resultados de los experimentos realizados.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/15049

Archivos adjuntos |
ANS.zip (26.81 KB)
Redes neuronales en el trading: Representación lineal por partes de series temporales Redes neuronales en el trading: Representación lineal por partes de series temporales
Este artículo es algo distinto de los anteriores de esta serie. En él, hablaremos de una representación alternativa de las series temporales. La representación lineal por partes de series temporales es un método de aproximación de una serie temporal usando funciones lineales en intervalos pequeños.
Creación de un modelo de restricción de tendencia de velas (Parte 6): Integración todo en uno Creación de un modelo de restricción de tendencia de velas (Parte 6): Integración todo en uno
Un reto importante es la gestión de varias ventanas de gráficos del mismo par que ejecutan el mismo programa con diferentes funciones. Vamos a discutir cómo consolidar varias integraciones en un programa principal. Además, compartiremos ideas sobre la configuración del programa para imprimir en un diario y comentar el éxito de la emisión de señales en la interfaz de gráficos. Encontrará más información en este artículo a medida que avancemos en la serie de artículos.
Combinación de estrategias de análisis técnico y fundamental en MQL5 para principiantes Combinación de estrategias de análisis técnico y fundamental en MQL5 para principiantes
En este artículo, analizaremos cómo integrar sin problemas el seguimiento de tendencias y los principios fundamentales en un Asesor Experto para crear una estrategia más sólida. Este artículo demostrará lo fácil que es para cualquiera comenzar a desarrollar algoritmos comerciales personalizados utilizando MQL5.
Redes neuronales: así de sencillo (Parte 97): Entrenamiento de un modelo con el MSFformer Redes neuronales: así de sencillo (Parte 97): Entrenamiento de un modelo con el MSFformer
Al estudiar las distintas arquitecturas de construcción de modelos, prestamos poca atención al proceso de entrenamiento de los mismos. En este artículo intentaremos rellenar ese vacío.