English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
preview
모집단 최적화 알고리즘: 반딧불이 알고리즘(FA)

모집단 최적화 알고리즘: 반딧불이 알고리즘(FA)

MetaTrader 5 | 20 11월 2023, 14:28
254 0
Andrey Dik
Andrey Dik

콘텐츠

1. 소개
2. 알고리즘에 대한 설명
3. 테스트 결과


1. 소개

자연은 항상 많은 메타휴리스틱 알고리즘에 영감을 주었습니다. 이 알고리즘은 개별적인 경험을 바탕으로 문제에 대한 해결책을 찾을 수 있도록 했습니다. 자연 선택과 적자생존은 초기 메타휴리스틱 알고리즘이 탄생하게 된 주요 동기였습니다. 자연에서 동물은 다양한 방식으로 서로 소통합니다. 반딧불이의 경우는 눈을 깜빡이는 능력으로 의사소통을 합니다. 반딧불이의 종류는 약 2000종에 달하며 각자의 특별한 반짝임의 패턴을 가지고 있습니다. 반딧불이는 일반적으로 특정한 패턴의 짧은 반짝임을 생성합니다. 빛과 그 강도는 생체 발광이라고 하는 생화학적 과정의 결과입니다. 이러한 반짝임의 주요 기능은 짝짓기 패턴과 잠재적인 희생자들을 끌어들이는 것으로 믿어집니다. 일부 열대 반딧불이는 반짝임을 동기화할 수 있는데 이는 생물학적 자기 조직화의 한 예를 보여줍니다. 빛의 강도는 광원으로부터의 거리에 따라 역제곱의 법칙을 따르기 때문에 반딧불이에서 나오는 깜박임의 빛은 주변의 반딧불이들이 이를 보고 반응하게 만듭니다.

반딧불이의 행동에서 영감을 얻은 모집단 최적화 알고리즘에는 두가지 변형이 있습니다: 반딧불이 알고리즘과 땅 반딧불이 군집 최적화(GSO) 알고리즘이 두 가지 변형입니다. 반딧불이와 땅 반딧불이의 가장 큰 차이점은 후자는 날개가 없다는 것입니다. 이 글에서는 최적화 알고리즘의 첫 번째 유형을 고려할 것입니다.

2. 알고리즘에 대한 설명

반딧불이 알고리즘(F-알고리즘)은 X-Sh가 제안했습니다. 양은 2007년 영국 케임브리지 대학에서 박사 학위를 취득한 후 곧바로 최적화 연구자들의 주목을 받았습니다. 반딧불이 알고리즘은 최근 최적화 문제 해결에서 인상적인 결과를 보여준 군집 지능 알고리즘 제품군의 일부입니다. 특히 반딧불이 알고리즘은 연속 및 이산 최적화 문제를 해결하는 데 사용됩니다.

반딧불이 알고리즘에는 반딧불이의 실제 깜박임 특성에 기반한 세 가지 규칙이 있습니다. 규칙은 다음과 같습니다:

  1. 모든 반딧불이는 더 매력적이고 더 밝은 반딧불이를 향해 움직입니다.
  2. 반딧불이의 인력의 정도는 밝기에 비례하며 다른 반딧불이와의 거리가 멀어질수록 감소합니다. 이는 공기가 빛을 흡수하기 때문입니다. 그러므로 깜박이는 두 반딧불이 사이에서 덜 밝은 반딧불이가 더 밝은 반딧불이를 향해 이동합니다. 더 밝거나 더 매력적인 상대가 없으면 반딧불이는 무작위로 움직입니다.
  3. 반딧불이의 밝기 또는 빛의 강도는 문제의 목적함수의 값에 따라 결정됩니다.


처음에는 알고리즘이 시작될 때 모든 반딧불이는 검색 공간 전체에 무작위로 분산됩니다. 그런 다음 알고리즘은 두 단계에 따라 최적의 파티션을 결정합니다:

  1. 빛의 세기 변화 - 현재 위치에서 반딧불이의 밝기가 체력 값에 반영되어 매력적인 반딧불이를 향해 움직입니다.
  2. 반딧불이는 주변 반딧불이의 빛의 세기를 관찰하여 위치를 바꿉니다.


이제 우리는 반딧불이 최적화의 복잡성에 대해 좀 더 자세히 알아볼 수 있습니다. 알고리즘의 핵심은 그림 1에 명확하게 나와 있습니다.

Fas

그림 1. 검색 공간의 반딧불이. 거리가 커질수록 가시성이 감소합니다.

검색 원리의 기본 원리는 반딧불이 사이의 거리가 멀어질수록 가시성이 비선형적으로 감소한다는 것입니다. 이 비선형 관계가 없다면 각 반딧불이는 더 밝은 광원을 향해 결정론적으로 움직일 것입니다. 그러나 그림 1에서 볼 수 있듯이 반딧불이는 가장 밝은 상대를 선택하지 않습니다. 왜냐하면 환경에 의한 빛의 흡수로 인해 빛이 덜 눈에 띄기 때문입니다. 대신 주변에 가장 밝은 상대가 있더라도 덜 밝은 상대를 선택합니다. 이것은 알고리즘이 더 작은 군집으로 분할하게 되는 것을 설명합니다. 이는 거리에 의해 빛을 흡수하게 되는 비선형 기능으로 인해 자연적으로 발생합니다. 아래 그림 2에서는 알고리즘 매개변수 중 하나인 감마 매체의 흡수 계수 값에 따른 알고리즘에 대한 가시성 대 거리 함수를 확인할 수 있습니다.


가시성

그림 2. 감마 투명도 계수가 각각 1.0, 0.2, 0.05, 0.01인 거리 f(x)에서 매체의 투명도 함수입니다.

감마가 무한대가 되면 환경이 불투명해지고 감마가 0이 되면 환경이 완전히 투명해지며 각 반딧불이는 검색 공간에서 어떤 거리에서도 서로를 볼 수 있습니다. 감마가 0.0이면 어떻게 될까요? 모든 반딧불이는 최적이 아닌 어떤 지점에 수렴하는 가장 밝은 곳으로 날아갑니다. 따라서 알고리즘은 로컬 극한 중 하나에 갇힌 채 남아 있으며 수렴하지 않습니다. 환경이 완전히 불투명하면 어떻게 될까요? 반딧불이는 자신보다 더 매력적인 대상을 보지 못하게 됩니다. 알고리즘의 저자가 제안한 개념에 따르면 자신보다 더 나은 대상을 보지 않으면 반딧불이는 무작위로 움직입니다. 알고리즘이 무작위 검색으로 변질되는 것입니다. 알고리즘 분류 등급표에서 무작위 검색 알고리즘은 최하위에 있습니다.  

알고리즘에 대해 더 자세한 분석을 해보고 반딧불이의 움직임을 설명하는 방정식을 고려해 보겠습니다. 가시성 대 거리의 함수는 소위 매력도 지수라는 것의 계산의 기초가 됩니다:

attractiveness = fireflies [k].f / (1.0 + gamma * distance * distance);

설명:
attractiveness - 말 그대로 매력
gamma - 환경 불투명도 계수
distance - 반딧불이 사이의 유클리드 거리
fireflies [k].f - k번째 반딧불이의 광도

이 방정식은 매력도 함수가 문제의 차원과 거리 값의 한계에 직접적으로 의존한다는 것을 명확하게 보여 주고 있습니다 그러므로 알고리즘의 저자는 특정한 최적화 문제에 대한 투명도 계수를 선택할 것을 권장합니다. 저는 0에서 20까지의 범위에서 거리 값을 정규화 할 필요가 있다고 생각합니다. 왜냐하면 알고리즘이 어떻게 동작할지 미리 알지 못한 상태에서 그렇게 하는 것은 불편하고 시간이 많이 걸린다고 생각하기 때문입니다. 이를 위해 다른 알고리즘에서 반복적으로 사용했던 Scale () 함수를 적용합니다. 매력도 계산 전 '거리'의 환산은 다음과 같습니다:

distance = Scale (distance, 0.0, maxDist, 0.0, 20.0, false);

설명:

maxDist - 반딧불이 한 쌍 사이의 최대 유클리드 거리

이 경우에는 반딧불이의 매력도는 문제의 차원에 의존하지 않으며 특정 최적화 문제에 대한 감마 계수를 선택할 필요가 없습니다. 매력도 함수는 각 반딧불이가 어떤 종류의 짝을 선택할지를 결정합니다. 이 선택은 엄격하게 결정됩니다. 반딧불이의 서로에 대한 매력도의 영향은 베타 계수 (알고리즘의 두 번째 매개 변수)를 결정합니다. 반딧불이의 선택이 미리 결정되어 있는 경우 각 해당 반복에서 알고리즘의 검색 기능은 어떻게 보장될까요? 이를 위해 무작위 벡터 구성 요소와 세 번째 알고리즘 매개변수(알파)가 도입되었습니다. 반딧불이의 복잡한 행동 관계는 다음과 같습니다:

fireflies [i].c [c] = Xj + beta * (Xi - Xj) + alpha * r * v [c];

설명:
fireflies [i].c [c] - i번째 반딧불이의 c번째 좌표
beta - 반딧불이 유인 영향력 계수
alpha - 반딧불이를 움직일 때 무작위 구성 요소에 영향을 미치는 계수로 이동 대상으로부터 편차를 제공합니다.
r - [-1.0;1.0] 범위의 난수
v[c] - 검색 범위의 극한점 사이의 거리를 c번째 좌표로 나타내는 벡터 구성 요소
Хj - 반딧불이 쌍의 해당 좌표로 이곳으로 이동이 있을 것입니다
Xi - 움직임이 계산되는 반딧불이의 해당 좌표

이제 알고리즘 코드를 설명할 차례입니다. 설명은 비교적 간단합니다. 좀 더 자세히 살펴봅시다.

반딧불이는 [] - 좌표, f - 반딧불이의 광도(적합도 함수)라는 두 가지 구성 요소를 가진 간단한 구조 S_Firefly로 설명됩니다. 각 반딧불이에 대해 해당 반복에는 한 쌍을 이루어 이동하게 될 개체가 하나만 존재하므로 다음 이동을 계산할 때 좌표를 덮어쓸 위험이 없습니다. 이를 위해 저는 아래에서 고려한 특별한 구조를 소개합니다.
//——————————————————————————————————————————————————————————————————————————————
struct S_Firefly
{
  double c  []; //coordinates
  double f;     //the value of the fitness function
};
//——————————————————————————————————————————————————————————————————————————————

S_Attractiveness 구조는 매력도 값과 해당 반딧불이의 수를 한 쌍으로 저장하기 위한 것입니다. 각 반딧불이는 가장 매력적인 반딧불이의 좌표로 이동하는 것이 아니라 파트너가 이미 이동한 좌표로 이동합니다. 이것은 저자가 설명한 알고리즘 버전과 약간의 차이가 있지만 이것이 더 잘 작동하는 방식입니다.

//——————————————————————————————————————————————————————————————————————————————
struct S_Attractiveness
{
  double a; //attractiveness
  int    i; //index of the most attractive firefly
};
//——————————————————————————————————————————————————————————————————————————————

반딧불이 알고리즘은 C_AO_FA 클래스를 사용하여 설명됩니다. 여기에는 세 개의 공용 메서드가 있는데 그 중 하나는 초기화를 위한 Init(), 각 반복마다 호출해야 하는 두 개의 공용 메서드인 Flight() 및 Luminosity()와 파라미터 상수를 저장하기 위한 프라이빗 헬퍼 메서드 및 멤버입니다.

//——————————————————————————————————————————————————————————————————————————————
class C_AO_FA
{
  //----------------------------------------------------------------------------
  public: S_Firefly fireflies []; //fireflies
  public: double    rangeMax  []; //maximum search range
  public: double    rangeMin  []; //minimum search range
  public: double    rangeStep []; //step search
  public: double    cB        []; //best coordinates
  public: double    fB;           //FF of the best coordinates

  public: void Init (const int    paramsP,  //number of opt. parameters
                     const int    sizeP,    //swarm size
                     const double alphaP,   //alpha, randomness in motion
                     const double betaP,    //beta, effect of attractiveness
                     const double gammaP);  //gamma, transparency of the environment

  public: void Flight ();
  public: void Luminosity ();

  //----------------------------------------------------------------------------
  private: S_Attractiveness att [];
  private: int    swarmSize;
  private: int    params;
  private: double maxDist;
  private: double v [];

  private: double alpha;      //randomness in motion
  private: double beta;       //effect of attractiveness
  private: double gamma;      //transparency of the environment
  private: bool   luminosity;

  private: double SeInDiSp  (double In, double inMin, double inMax, double step);
  private: double RNDfromCI (double min, double max);
  protected: double Scale   (double In, double InMIN, double InMAX, double OutMIN, double OutMAX,  bool revers);
};
//——————————————————————————————————————————————————————————————————————————————

Init() open 메서드는 초기화에 사용되며 각 최적화를 시작하기 전에 호출해야 합니다. 이 매개변수는 알고리즘의 상부의 구조 매개변수입니다. 이 메서드는 배열에 메모리를 할당하고 전역 및 각 개별 반딧불이의 광도 값을 재설정합니다.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_FA::Init (const int    paramsP, //number of opt. parameters
                    const int    sizeP,   //swarm size
                    const double alphaP,  //alpha, randomness in motion
                    const double betaP,   //beta, effect of attractiveness
                    const double gammaP)  //gamma, transparency of the environment
{
  fB = -DBL_MAX;

  params    = paramsP;
  swarmSize = sizeP;
  alpha     = alphaP;
  beta      = betaP;
  gamma     = gammaP;

  ArrayResize (rangeMax,  params);
  ArrayResize (rangeMin,  params);
  ArrayResize (rangeStep, params);
  ArrayResize (v,         params);
  ArrayResize (att,       swarmSize);

  luminosity = false;

  ArrayResize (fireflies, swarmSize);

  for (int i = 0; i < swarmSize; i++)
  {
    ArrayResize (fireflies [i].c,  params);
    fireflies [i].f = -DBL_MAX;
  }

  ArrayResize (cB, params);
}
//——————————————————————————————————————————————————————————————————————————————

각 반복에서 호출되는 첫 번째 공용 메서드인 Flight()를 살펴보겠습니다. 알고리즘의 주요 논리는 이 메서드에 집중되어 있으므로 더 자세히 살펴볼 필요가 있습니다. '밝기' 변수는 알고리즘이 첫 번째 반복에서 실행될지 또는 후속 반복에서 실행될지를 결정할 수 있도록 해주는 플래그 역할을 합니다. 플래그가 설정되지 않은 경우 균일 분포에 따라 좌표 공간에 반딧불이를 무작위로 배포해야 합니다. 이 작업과 함께 각 좌표에 대한 변위 벡터를 설정하고 반딧불이 사이에 있을 수 있는 최대 가능한 유클리드 거리를 즉시 계산합니다(이는 이미 언급했듯이 환경 투명도 계수가 문제의 차원에 의존하지 않도록 하기 위해 반딧불이 사이의 거리를 정규화 하는 데 필요합니다). 이러한 작업이 끝나면 'luminosity' 플래그를 활성화합니다.

if (!luminosity)
{
  fB = -DBL_MAX;

  //--------------------------------------------------------------------------
  double summCoordinates = 0.0;
  for (int c = 0; c < params; c++)
  {
    v [c] = rangeMax [c] - rangeMin [c];
    summCoordinates += pow (v [c], 2.0);
  }
  maxDist = pow (summCoordinates, 0.5);

  //--------------------------------------------------------------------------
  for (int s = 0; s < swarmSize; s++)
  {
    for (int k = 0; k < params; k++)
    {
      fireflies [s].c  [k] = RNDfromCI (rangeMin [k], rangeMax [k]);
      fireflies [s].c  [k] = SeInDiSp (fireflies [s].c [k], rangeMin [k], rangeMax [k], rangeStep [k]);
    }
  }

  luminosity = true;
}

두 번째 및 이후의 반복에서 반딧불이가 첫 번째 반복에서 무작위로 분포되어 빛을 발하기 시작한 후 (적합성 함수가 계산됨) 각 반딧불이에 대한 매력도를 계산하는 것이 가능합니다. 이를 위해 우리는 가능한 모든 반딧불이 쌍 사이의 유클리드 거리를 계산해야 합니다. 이렇게 하려면 좌표 차이의 제곱을 더하고 그 합에서 근을 구하면 됩니다. 이렇게 계산된 거리는 매력도 계산 방정식에 사용됩니다. 이것이 각 반딧불이에 대해 가능한 유일한 쌍을 얻는 방법입니다. 모든 반딧불이의 최대 광도를 결정합니다. 이것은 한 쌍을 찾을 수 없고 혼자 공간을 돌아다니는 가장 밝은 반딧불이를 결정하기 위해 필요합니다. 글쎄요 아마도 다음 반복에서는 더 운이 좋을 것입니다.

//measure the distance between all------------------------------------------
for (int i = 0; i < swarmSize; i++)
{
  att [i].a = -DBL_MAX;

  for (int k = 0; k < swarmSize; k++)
  {
    if (i == k) continue;

    summCoordinates = 0.0;
    for (int c = 0; c < params; c++) summCoordinates += pow (fireflies [i].c [c] - fireflies [k].c [c], 2.0);

    distance = pow (summCoordinates, 0.5);
    distance = Scale (distance, 0.0, maxDist, 0.0, 20.0, false);
    attractiveness = fireflies [k].f / (1.0 + gamma * distance * distance);

    if (attractiveness > att [i].a)
    {
      att [i].a = attractiveness;
      att [i].i = k;
    }

    if (fireflies [i].f > maxF) maxF = fireflies [i].f;
  }
}

Flight() 메서드 코드의 이 부분이 반딧불이의 비행을 담당합니다. 다른 모든 반딧불이보다 광도가 큰 반딧불이의 경우에는 계산이 다소 다르게 수행됩니다. 이 경우 우리는 알파 계수에 난수[-1.0;1.0]를 곱한 값을 통해 이동 벡터를 현재 위치에 추가합니다. 이론적으로 알고리즘에서 이것은 더 나은 솔루션이 될 것이라는 기대와 함께 최상의 솔루션에 대한 추가적인 연구의 역할을 합니다. 그러나 나중에 살펴 보겠지만 이 기술은 쓸모없는 것으로 판명될 것입니다. 이 단계에서 우리는 고전적인 버전의 알고리즘을 살펴봅니다.

이미 쌍이 발견된 다른 모든 반딧불이의 경우 이동의 계산은 무작위 구성 요소를 추가하여 적절한 쌍을 향해 이동하는 것으로 구성됩니다 (앞서 언급했듯이).

//flight--------------------------------------------------------------------
for (int i = 0; i < swarmSize; i++)
{
  if (fireflies [i].f >= maxF)
  {
    for (int c = 0; c < params; c++)
    {
      r  = RNDfromCI (-1.0, 1.0);
      fireflies [i].c [c] = fireflies [i].c [c] + alpha * r * v [c];
      fireflies [i].c [c] = SeInDiSp (fireflies [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); 
    }
  }
  else
  {
    for (int c = 0; c < params; c++)
    {
      r  = RNDfromCI (-1.0, 1.0);
      Xi = fireflies [i].c [c];
      Xj = fireflies [att [i].i].c [c];
      fireflies [i].c [c] = Xj + beta * (Xi - Xj) + alpha * r * v [c];
      fireflies [i].c [c] = SeInDiSp (fireflies [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }
}

모든 반복에서 호출되는 간단한 오픈 메서드입니다. 여기에 우리는 최상의 솔루션을 업데이트할 것입니다.

//——————————————————————————————————————————————————————————————————————————————
void C_AO_FA::Luminosity ()
{
  for (int i = 0; i < swarmSize; i++)
  {
    if (fireflies [i].f > fB)
    {
      fB = fireflies [i].f;
      ArrayCopy (cB, fireflies [i].c, 0, 0, WHOLE_ARRAY);
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

테스트로 넘어가 보겠습니다. 테스트 함수에 대한 알고리즘의 결과를 살펴봅시다:

2022.12.16 13:39:00.102 Test_AO_FA (EURUSD,M1) =============================
2022.12.16 13:39:05.930 Test_AO_FA (EURUSD,M1) 1 Skin's; Func 10000 실행 결과: 4.901742065217812
2022.12.16 13:39:05.930 Test_AO_FA (EURUSD,M1) 점수: 0.99603
2022.12.16 13:39:13.579 Test_AO_FA (EURUSD,M1) 20 Skin's; Func 10000 실행 결과: 3.2208359936020665
2022.12.16 13:39:13.579 Test_AO_FA (EURUSD,M1) 점수: 0.59468
2022.12.16 13:39:53.607 Test_AO_FA (EURUSD,M1) 500 Skin's; Func 10000 실행 결과: 0.98491319842575
2022.12.16 13:39:53.607 Test_AO_FA (EURUSD,M1) 점수: 0.06082
2022.12.16 13:39:53.607 Test_AO_FA (EURUSD,M1) =============================
2022.12.16 13:39:59.313 Test_AO_FA (EURUSD,M1) 1 Forest's; Func 10000 실행 결과: 1.578196881663454
2022.12.16 13:39:59.313 Test_AO_FA (EURUSD,M1) 점수: 0.89271
2022.12.16 13:40:07.274 Test_AO_FA (EURUSD,M1) 20 Forest's; Func 10000 실행 결과: 0.3101994341994826
2022.12.16 13:40:07.274 Test_AO_FA (EURUSD,M1) 점수: 0.17546
2022.12.16 13:40:49.159 Test_AO_FA (EURUSD,M1) 500 Forest's; Func 10000 실행 결과: 0.06829102669136165
2022.12.16 13:40:49.159 Test_AO_FA (EURUSD,M1) 점수: 0.03863
2022.12.16 13:40:49.159 Test_AO_FA (EURUSD,M1) =============================
2022.12.16 13:40:54.895 Test_AO_FA (EURUSD,M1) 1 Megacity's; Func 10000 실행 결과: 8.2
2022.12.16 13:40:54.895 Test_AO_FA (EURUSD,M1) 점수: 0.68333
2022.12.16 13:41:02.777 Test_AO_FA (EURUSD,M1) 20 Megacity's; Func 10000 실행 결과: 1.5900000000000003
2022.12.16 13:41:02.777 Test_AO_FA (EURUSD,M1) 점수: 0.13250
2022.12.16 13:41:43.901 Test_AO_FA (EURUSD,M1) 500 Megacity's; Func 10000 실행 결과: 0.2892
2022.12.16 13:41:43.901 Test_AO_FA (EURUSD,M1) 점수: 0.02410
2022.12.16 13:41:43.901 Test_AO_FA (EURUSD,M1) =============================
2022.12.16 13:41:43.901 Test_AO_FA (EURUSD,M1) C_AO_FA의 모든 점수: 0.39980648892951776

그 결과는 솔직히 말해 인상적이지 않습니다. 이 알고리즘은 개별 테스트에서 PSO, FSS, GWO보다 약간 더 우수합니다. 그러나 총 평점 지표에서는 무작위 검색 알고리즘을 제외하면 맨 아래에서 두 번째 위치에 있습니다. 이 모든 것을 고려했을 때 저는 테스트에서 예상 지표의 계산을 수정하는 아이디어가 떠올랐습니다. 다음 글에서는 좀 더 편리한 평점 계산 방식으로 바꾸기로 하고 현재 글에서는 최종 결과의 히스토그램을 추가하겠습니다. 히스토그램은 개별 알고리즘 간의 성능 비율을 명확하게 보여줍니다.

고전적인 반딧불이 알고리즘은 구현하기 쉽습니다. 그러나 연구 결과에 따르면 이 수치는 느리게 수렴하고 멀티모달 문제의 경우 국부적 극한 함정에 쉽게 빠지는 것으로 나타났습니다. 또한 현재 반복에 대해 매개변수적으로 의존하는 계수가 없습니다. 따라서 이 연구의 목표 중 하나는 표준 반딧불이 알고리즘을 수정하여 성능을 개선하는 것이었습니다.

알고리즘의 아이디어 자체는 매우 독창적입니다. 그러나 모든 것을 그대로 두고 그 특성을 개선하지 않는 것은 유감입니다. 그래서 저는 무작위 구성 요소를 레비 비행으로 대체하여 알고리즘을 수정하려고 시도했습니다. 레비의 비행이 모든 알고리즘의 검색 능력을 향상시킬 수 있는 것은 아닙니다. 저는 뻐꾸기 검색 알고리즘을 고려한 후 이 방법을 사용하여 다른 알고리즘을 개선하려고 시도했지만 예상한 결과를 얻지 못했습니다. 이는 알고리즘 안의 내부 검색 전략이 이를 보완하는 것과 어떤 식으로 든 일관성이 있어야 합니다. 이 특별한 경우 레비 비행을 적용하자 알고리즘의 성능이 극적으로 향상되는 놀라운 효과가 나타났습니다. 이에 대해서는 테스트 결과와 관련한 부분에서 자세히 설명하겠습니다.

다음은 코드에서 변경이 이루어진 부분입니다. 첫째 고전적 버전에서는 광도가 가장 좋은 반딧불이가 현재 위치에서 임의의 방향으로 이동합니다. 그런 다음 최고의 반딧불이는 현재 위치가 아닌 솔루션 전체를 개선하기 위해 최고의 글로벌 위치로부터 이동합니다. 이동 벡터를 고려하여 동일한 알파 계수를 가진 레비 비행 분포(꼬리가 무거운 분포)의 임의의 숫자를 최적 해의 좌표에 추가합니다. 이를 통해 주변 지역을 세분화하여 글로벌 솔루션의 좌표를 개선할 수 있었습니다.

보시다시피 나머지 반딧불이의 동작은 이제 레비 비행의 무작위 요소에 맞게 조정되었고 동일한 고전적인 규칙을 따릅니다. 이것이 알고리즘에 적용된 전체 수정 사항입니다.

//flight--------------------------------------------------------------------
for (int i = 0; i < swarmSize; i++)
{
  if (fireflies [i].f >= maxF)
  {
    for (int c = 0; c < params; c++)
    {
      r1 = RNDfromCI (0.0, 1.0);
      r1 = r1 > 0.5 ? 1.0 : -1.0;
      r2 = RNDfromCI (1.0, 20.0);

      fireflies [i].c [c] = cB [c] + alpha * r1 * pow (r2, -2.0) * v [c];
      fireflies [i].c [c] = SeInDiSp (fireflies [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }
  else
  {
    for (int c = 0; c < params; c++)
    {
      r1 = RNDfromCI (0.0, 1.0);
      r1 = r1 > 0.5 ? 1.0 : -1.0;
      r2 = RNDfromCI (1.0, 20.0);

      Xi = fireflies [i].c [c];
      Xj = fireflies [att [i].i].c [c];

      fireflies [i].c [c] = Xj + beta * (Xi - Xj) + alpha * r1 * pow (r2, -2.0) * v [c];
      fireflies [i].c [c] = SeInDiSp (fireflies [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }
}

그림 3의 레비의 비행 함수 차트. 함수 방정식의 지수가 알고리즘의 동작에 어떤 영향을 미칠 수 있을까요? 제 연구에 따르면 디그리가 증가할수록 짧은 점프에 비해 긴(헤비테일) 점프의 수는 감소하는 반면 최적 해에 가까운 좌표를 세분화하는 알고리즘 능력은 향상됩니다. 김 점프가 거의 없기 때문에 국부적인 극한에 갇힐 확률이 높아집니다. 이 효과는 이산 함수를 분석할 때 더 눈에 띄는 반면 부드러운 함수에서는 그다지 두드러지지 않습니다. 반대로 지수가 감소하면 긴 점프의 횟수가 증가하고 알고리즘의 검색 기능은 향상되지만 수렴의 정확도는 악화됩니다. 그러므로 우리는 정확도와 검색 사이의 중간 지점이 필요합니다. 또한 이는 최적화 문제에 따라 달라질 수 있습니다.


Levi

그림 3. 레비 비행 함수, 각도 0.5...3.0 


이제 테스트 스탠드에서 알고리즘의 수정된 버전의 결과로 넘어가 보겠습니다. 아래에서 고전적 버전에 비해 오리지널 버전의 성능이 얼마나 향상되었는지 확인할 수 있습니다.

2022.12.16 13:07:15.925 Test_AO_FAm (EURUSD,M1) =============================
2022.12.16 13:07:21.544 Test_AO_FAm (EURUSD,M1) 1 Skin's; Func 10000 실행 결과: 4.854437214435259
2022.12.16 13:07:21.544 Test_AO_FAm (EURUSD,M1) 점수: 0.98473
2022.12.16 13:07:29.518 Test_AO_FAm (EURUSD,M1) 20 Skin's; Func 10000 실행 결과: 4.588539001298423
2022.12.16 13:07:29.518 Test_AO_FAm (EURUSD,M1) 점수: 0.92124
2022.12.16 13:08:12.587 Test_AO_FAm (EURUSD,M1) 500 Skin's; Func 10000 실행 결과: 1.981278990090829
2022.12.16 13:08:12.587 Test_AO_FAm (EURUSD,M1) 점수: 0.29872
2022.12.16 13:08:12.587 Test_AO_FAm (EURUSD,M1) =============================
2022.12.16 13:08:18.336 Test_AO_FAm (EURUSD,M1) 1 Forest's; Func 10000 실행 결과: 1.7665409595127233
2022.12.16 13:08:18.336 Test_AO_FAm (EURUSD,M1) 점수: 0.99924
2022.12.16 13:08:26.432 Test_AO_FAm (EURUSD,M1) 20 Forest's; Func 10000 실행 결과: 0.6261364994589462
2022.12.16 13:08:26.432 Test_AO_FAm (EURUSD,M1) 점수: 0.35417
2022.12.16 13:09:10.587 Test_AO_FAm (EURUSD,M1) 500 Forest's; Func 10000 실행 결과: 0.14269062630878
2022.12.16 13:09:10.587 Test_AO_FAm (EURUSD,M1) 점수: 0.08071
2022.12.16 13:09:10.587 Test_AO_FAm (EURUSD,M1) =============================
2022.12.16 13:09:16.393 Test_AO_FAm (EURUSD,M1) 1 Megacity's; Func 10000 실행 결과: 10.0
2022.12.16 13:09:16.393 Test_AO_FAm (EURUSD,M1) 점수: 0.83333
2022.12.16 13:09:24.373 Test_AO_FAm (EURUSD,M1) 20 Megacity's; Func 10000 실행 결과: 1.7899999999999998
2022.12.16 13:09:24.373 Test_AO_FAm (EURUSD,M1) 점수: 0.14917
2022.12.16 13:10:09.298 Test_AO_FAm (EURUSD,M1) 500 Megacity's; Func 10000 실행 결과: 0.5076
2022.12.16 13:10:09.298 Test_AO_FAm (EURUSD,M1) 점수: 0.04230
2022.12.16 13:10:09.298 Test_AO_FAm (EURUSD,M1) =============================
2022.12.16 13:10:09.298 Test_AO_FAm (EURUSD,M1) C_AO_FAm에 대한 모든 점수: 0.5181804234713119

보시다시피 수정된 알고리즘은 더 나은 결과를 보여줄 뿐만 아니라 평점 테이블에서 상위의 위치를 차지합니다. 다음 섹션에서 결과를 자세히 살펴보겠습니다. 아래는 테스트 스탠드에 있는 알고리즘의 수정된 버전의 애니메이션입니다.

피부

  FAm 피부 테스트 함수

숲

  FAm 테스트 함수

메가시티

  FAm 메가시티 테스트 함수


3. 테스트 결과

수정된 반딧불이 알고리즘(FAm)은 모든 테스트에서 우수한 성능을 보였습니다. 일반적으로 결과는 알고리즘의 설정에 따라 달라집니다. 일부 설정의 경우 두 개의 변수를 사용하여 세 가지 함수 모두에서 100% 수렴이 이루어졌습니다. 알고리즘의 높은 확장성은 40개 및 1000개의 매개변수를 사용하는 테스트에서 리더십을 제공합니다. 베타 및 감마 매개변수는 강력한 영향을 미치며 높은 수렴도와 국부적 극한값에 갇히지 않는 저항성을 모두 얻을 수 있게 합니다. 결과는 매우 다양하며 이는 일반적으로 알고리즘의 단점 때문일 수 있습니다. 다른 모든 조건이 동일하다면 이 알고리즘이 앞서 고려한 알고리즘 중 가장 강력합니다. 저는 이 알고리즘을 머신 러닝 및 인공 지능 작업, 특히 신경망 학습을 포함한 매우 광범위한 작업에 사용할 것을 권장합니다.

아래는 수정된 반딧불이 알고리즘이 선두를 차지한 최종 평점 표입니다. 안타깝게도 고전적인 알고리즘은 독창성에도 불구하고 좋은 결과를 얻지 못했습니다. 튜닝 매개변수를 선택해도 성공하지 못했습니다.

AO

설명

피부

피부 최종

숲 최종

메가시티(개별)

메가시티 최종

최종 결과

2 params(1 F)

40 params(20F)

1000 params(500 F)

2 params(1 F)

40 params(20F)

1000 params(500 F)

2 params(1 F)

40 params(20F)

1000 params(500 F)

FAm

반딧불이 알고리즘 M

0.98473

0.92124

0.29872

0.73490

0.99924

0.35417

0.08071

0.47804

0.83333

0.14917

0.04230

0.34160

0.51817889

COAm

뻐꾸기 최적화 알고리즘 M

1.00000

0.85911

0.14316

0.66742

0.99283

0.28787

0.04551

0.44207

1.00000

0.24917

0.03537

0.42818

0.51255778

ACOm

개미 군집 최적화 M

0.98229

0.79108

0.12602

0.63313

1.00000

0.62077

0.11521

0.57866

0.38333

0.44000

0.02377

0.28237

0.49805222

ABCm

인공 꿀벌 군집 M

1.00000

0.63922

0.08076

0.57333

0.99908

0.20112

0.03785

0.41268

1.00000

0.16333

0.02823

0.39719

0.46106556

ABC

인공 꿀벌 군집

0.99339

0.73381

0.11118

0.61279

0.99934

0.21437

0.04215

0.41862

0.85000

0.16833

0.03130

0.34988

0.46043000

GWO

회색 늑대 최적화

0.99900

0.48033

0.18924

0.55619

0.83844

0.08755

0.02555

0.31718

1.00000

0.10000

0.02187

0.37396

0.41577556

FSS

물고기 떼 검색

0.99391

0.5692

0.11341

0.55884

0.85172

0.12143

0.03223

0.33513

0.91667

0.08583

0.02583

0.34278

0.41224778

PSO

파티클 스웜 최적화

0.99627

0.38080

0.05089

0.47599

0.93772

0.14540

0.04856

0.37723

1.00000

0.09333

0.02233

0.37189

0.40836667

FA

반딧불이 알고리즘

0.99603

0.59468

0.06082

0.55051

0.89271

0.17546

0.03863

0.36893

0.68333

0.13250

0.02410

0.27998

0.39980649

RND

랜덤

0.99932

0.44276

0.06827

0.50345

0.83126

0.11524

0.03048

0.32566

0.83333

0.09000

0.02403

0.31579

0.38163222


이 기사부터 해서 저는 테스트 당시 최고의 알고리즘의 경우 점수가 100점이고 최악의 알고리즘은 1점인 히스토그램을 게시하겠습니다. 이를 통해 평가표 알고리즘의 최종 결과의 척도를 명확하게 볼 수 있기 때문에 시각적 인식 측면에서 가장 편리한 표시 방법이라고 생각합니다. 이제 랜덤 알고리즘이 리더보다 얼마나 뒤처지는지 확인할 수 있습니다.

등급

그림 4. 테스트 알고리즘의 최종 결과 히스토그램


아시다시피 메타휴리스틱 알고리즘은 검색 엔진에 합리적인 가정과 함께 무작위성의 속성을 사용하여 최적화 문제를 해결하는 근사 메서드로서 솔루션 공간을 검토하고 사용하여 무작위로 생성된 유효한 솔루션 세트에서 반복을 통해 사용 가능한 솔루션의 품질을 개선하려고 시도합니다. 이러한 알고리즘이 최적이라고 보장할 수는 없지만 이들 알고리즘은 합리적이고 수용 가능한 솔루션을 제공하기 위해 테스트를 거친 것들입니다. 또한 문제의 행동이 큰 영향을 미치지 않는다는 점에서 장점이 있으며 많은 작업에서 이러한 장점이 유용합니다. 사용 가능한 알고리즘이 많기 때문에 우리는 문제 행동에 따라 문제 해결에 적합한 알고리즘을 선택할 수 있습니다.

진화 알고리즘이 등장한 이후 휴리스틱 알고리즘에 대한 많은 연구가 진행되었습니다. 새로운 알고리즘의 구현은 주요 연구 분야 중 하나였습니다. 현재 40개 이상의 메타휴리스틱 알고리즘이 있습니다. 대부분은 자연에서 시나리오를 시뮬레이션 하여 만들어집니다.

장단점은 반딧불 알고리즘(FAm)의 수정된 버전을 참조합니다.

장점:
  • 간단한 구현. 쉽게 수정할 수 있습니다.
  • 높은 확장성.
  • 높은 컨버전스(알고리즘 설정에 따라 달라질 수 있음).
  • 검색 공간의 영역을 로컬 극한을 중심으로 별도의 그룹으로 클러스터링하는 기능.

단점:
  • 설정이 최적화 결과에 미치는 영향이 큽니다.
  • 일부 설정에서는 알고리즘이 로컬 극한값에서 멈추는 경향이 있습니다.

각각의 기사에는 이전의 모든 기사에서 다룬 알고리즘 코드의 최신 버전이 업데이트된 아카이브가 포함되어 있습니다. 각각의 새로운 기사는 저자의 축적 된 개인적인 경험이며 결론과 판단은 이 목적을 위해 개발 된 특수 테스트 스탠드에서 수행 된 실험을 기반으로 합니다.



MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/11873

모집단 최적화 알고리즘: 박쥐 알고리즘(BA) 모집단 최적화 알고리즘: 박쥐 알고리즘(BA)
이 기사에서는 부드러운 함수에서 좋은 수렴을 보이는 박쥐 알고리즘(BA)에 대해 알아볼 것입니다.
MQL5에서 ONNX 모델을 사용하는 방법 MQL5에서 ONNX 모델을 사용하는 방법
ONNX(Open Neural Network Exchange)는 머신 러닝 모델을 나타내기 위해 구축된 개방형 형식입니다. 이 기사에서는 금융 시계열을 예측하기 위해 CNN-LSTM 모델을 만드는 방법에 대해 살펴보겠습니다. 또한 MQL5 Expert Advisor에서 생성된 ONNX 모델을 사용하는 방법도 보여드리겠습니다.
엑셀러레이터 오실레이터를 사용하여 거래 시스템을 설계하는 방법을 알아보세요 엑셀러레이터 오실레이터를 사용하여 거래 시스템을 설계하는 방법을 알아보세요
이 기사는 인기 있는 기술 지표를 기반으로 거래 시스템을 설계하는 방법과 관련한 시리즈의 새로운 글입니다. 우리는 엑셀러레이터 오실레이터 지표라는 새로운 지표에 대해 알아보고 이를 활용하여 거래 시스템을 설계하는 방법을 알아볼 것입니다.
Expert Advisor 개발 기초부터(23부): 새로운 주문 시스템(VI) Expert Advisor 개발 기초부터(23부): 새로운 주문 시스템(VI)
이제 주문 시스템을 더욱 유연하게 만들어 볼 것입니다. 여기서는 포지션 스톱 레벨을 훨씬 더 빠르게 변경할 수 있도록 코드를 더 유연하게 변경하는 방법을 알아보겠습니다.