English Русский Español Português
preview
Kompetitiver Lernalgorithmus (CLA)

Kompetitiver Lernalgorithmus (CLA)

MetaTrader 5Handel |
13 0
Andrey Dik
Andrey Dik

Inhalt

  1. Einführung
  2. Implementierung des Algorithmus
  3. Testergebnisse


Einführung

In den letzten Jahrzehnten wurden viele bioinspirierte Algorithmen vorgeschlagen, von Ameisenkolonien und Partikelschwärmen bis hin zu Grauwölfen und Walen. Die menschliche Gesellschaft mit ihren komplexen sozialen Interaktionen kann jedoch auch als reiche Ideenquelle für effektive Optimierungsmethoden dienen. Diese Idee ist die Grundlage für den kompetitiven Lernalgorithmus (CLA).

CLA verwendet eine Metapher des Bildungsprozesses, bei der die Population von Lösungen durch Schüler dargestellt wird, die in Klassen organisiert sind. Der Algorithmus modelliert elegant drei Arten des Lernens: vom Besten der Klasse (Lehrer), aus persönlicher Erfahrung und durch klassenübergreifende Interaktion. Dieser Ansatz bietet ein Gleichgewicht zwischen der Erkundung des Suchraums und der Nutzung der gefundenen guten Lösungen, was für eine effektive Optimierung entscheidend ist.

In diesem Artikel untersuchen wir detailliert die Prinzipien des CLA, seine mathematische Grundlage, Implementierungsmerkmale und vergleichen seine Effektivität mit anderen populären Metaheuristiken anhand unserer Standardtestfunktionen.


Implementierung des Algorithmus

Der kompetitive Lernalgorithmus basiert auf einer Metapher des Bildungsprozesses in der Schule. In dieser Metapher repräsentieren Schüler mögliche Lösungen für das Optimierungsproblem, Klassen sind Gruppen von Schülern, Lehrer sind jeweils die besten Schüler ihrer Klasse, Wissen entspricht Koordinaten im Suchraum und die Bewertung entspricht dem Wert der Fitnessfunktion.

Der Algorithmus beginnt mit einer Initialisierung, die mit dem Beginn des Schuljahres verglichen werden kann. Eine Population von beispielsweise 198 Schülern wird erstellt, die in 9 Klassen zu je 22 Schülern unterteilt sind. Jedem Schüler wird zufällig anfängliches „Wissen“ zugewiesen – Koordinaten im Suchraum.

Der Lernprozess ist iterativ, und in jeder Iteration lernen die Schüler auf drei verschiedene Arten. Die erste Methode ist das lehrergeführte Lernen, bei dem jeder Schüler vom Besten seiner Klasse lernt, und je schwächer eine Klasse abschneidet, desto intensiver lernen ihre Schüler, aber mit der Zeit nimmt die Lernintensität für alle ab. Die zweite Methode ist das persönliche Training, das erst nach der vierten Iteration beginnt. In diesem Modus erinnert sich der Schüler an seine besten Ergebnisse der letzten vier „Unterrichtsstunden“ und versucht, zu seiner persönlichen Bestleistung zurückzukehren. Die dritte Methode ist das Lernen von anderen Klassen, das ebenfalls nach der vierten Iteration beginnt. Mit einer Wahrscheinlichkeit von 50 % lernt ein Schüler von dem über alle Klassen hinweg berechneten Durchschnittslehrer, was hilft, ein Steckenbleiben in lokalen Optima zu vermeiden.

Nach jedem Trainingszyklus wird der Fortschritt bewertet. Der beste Schüler jeder Klasse wird identifiziert und zum Lehrer, die Gesamtbewertung der Klasse wird unter Berücksichtigung der Leistung aller Schüler berechnet und die global beste gefundene Lösung wird aktualisiert.

Der Algorithmus verwendet fünf Schlüsselparameter:

  • popSize – Gesamtzahl der Schüler,
  • numClasses – Anzahl der Klassen,
  • beta – Einfluss aller Schüler einer Klasse auf deren Gesamtbewertung,
  • gamma – Wahrscheinlichkeit, von anderen Klassen zu lernen,
  • deltaIter – Iteration, nach der das erweiterte Lernen unter Nutzung der eigenen Erfahrung und klassenübergreifender Interaktionen beginnt.

Der Algorithmus implementiert mehrere intelligente Mechanismen. Adaptive Lernfaktoren sorgen für intensiveres Lernen bei schwächeren Klassen und eine allmähliche Verlangsamung des Lernens im Zeitverlauf, wie es im realen Bildungsprozess geschieht. Das Gleichgewicht zwischen Exploration und Exploitation wird durch aktive Exploration in den frühen Phasen erreicht, gefolgt von einer Konzentration auf die besten gefundenen Lösungen. Der Speichermechanismus ermöglicht es dem Algorithmus, sich an die Historie jedes Schülers zu erinnern und bei Bedarf zu guten Entscheidungen aus der Vergangenheit zurückzukehren.

Mathematisch lässt sich die Wissensaktualisierung eines Schülers als Summe aus dem aktuellen Wissen und drei Komponenten darstellen: Anleitung durch den Klassenlehrer, persönliche historische Erfahrung und Wissen, das vom Durchschnittslehrer über alle Klassen hinweg gewonnen wurde. Diese Formel bietet ein Gleichgewicht zwischen dem Folgen des Anführers, der Nutzung eigener Erfahrung und der Erforschung neuer Bereiche.

Letztendlich wird die Effektivität des Algorithmus durch mehrere Faktoren bestimmt. Vielfalt wird durch mehrere Klassen erreicht, die unterschiedliche Richtungen im Suchraum erkunden. Der Wettbewerb zwischen Schülern um eine Lehrposition fördert bessere Lösungen. Kooperation durch Wissensaustausch zwischen den Klassen hilft, eine vorzeitige Konvergenz zu verhindern. Adaptivität bietet zusätzliche Hilfe für schwache Klassen, und der Speichermechanismus speichert Informationen über gute Lösungen.

CLA_L

Abb. 1. Funktionsweise des Algorithmus

Die Abbildung der Funktionsweise des Algorithmus zeigt drei Hauptschritte: Initialisierung, Trainingsphase und Evaluierung mit Aktualisierung. Fangen wir nun an, Pseudocode für den CLA_L-Algorithmus zu schreiben.

WAS WIR VORAB BENÖTIGEN:
– 198 Schüler (unsere Lösungen)
– 9 Klassen (Schülergruppen)
– Parameter β = 0,9 (wie wichtig sind alle Schüler in der Klasse)
– Parameter γ = 0,5 (Chance, von anderen Klassen zu lernen)
– Nach der 4. Iteration zusätzliche Lernarten einbeziehen
– Funktion zur Bewertung der Lösungsqualität

FANGEN WIR AN:

1. EINE SCHULE ERSTELLEN:
   – 198 Schüler auf 9 Klassen verteilen (je 22)
   – Jedem Schüler eine zufällige Anfangsposition im Suchraum zuweisen
   – In jeder Klasse den besten Schüler auswählen – er wird zum Lehrer
– Ein Journal erstellen, um die Historie jedes Schülers aufzuzeichnen

2. LERNPROZESS (iterativer Prozess):
   
   Schritt 1: Lernintensität bestimmen
– Für jede Klasse berechnen wir, wie aktiv die Schüler lernen müssen
– Schwache Klassen (mit einem schlechten Rang) lernen intensiver
– Mit der Zeit lernt jeder weniger intensiv (wie im echten Leben)
   
   Schritt 2: Finden des „Durchschnittslehrers“
– Die Positionen aller Lehrer einnehmen
– Den Durchschnittswert berechnen
   – Dies wird ein schulweiter Wissensstandard sein
   
   Schritt 3: Jeder Schüler lernt:
   
   Für jeden Schüler:
   
   a) IMMER vom eigenen Lehrer LERNEN:
      – Die Position des Klassenlehrers bestimmen
      – Sich in deren Richtung bewegen
      – Die Schrittweite hängt vom Lernfaktor der Klasse ab
   
   b) Nach der 4. Iteration rufen wir unsere Erfahrung ab:
      – Ins Journal schauen: Wo war ich in den letzten 4 Lektionen am besten?
      – Mit einer gewissen zufälligen Kraft zu dieser Position zurückkehren
      – Dies hilft, gute Lösungen zu bewahren
   
   c) Nach der 4. Iteration von anderen Klassen lernen:
      – Werfen einer Münze (mit einer Wahrscheinlichkeit von 50 %)
– Mit einer Wahrscheinlichkeit von 50 % wird auf den „durchschnittlichen Lehrer“ geschaut
      – Der Schüler bewegt sich ein Stück in diese Richtung.
      – Dies hilft beim Erfahrungsaustausch zwischen den Klassen
   
   Schritt 4: Alle Schüler auswerten
   – Jeder Schüler erhält einen Fitnesswert
   – Je besser die Position, desto höher der Fitnesswert
   
   Schritt 5: Die Schulhierarchie aktualisieren
   
   Für jede Klasse:
   – Einen neuen besten Schüler finden – er wird zum Lehrer
   – Den Gesamtwert der Klasse berechnen:
     * Den Fitnesswert des Lehrers nehmen
     * Den durchschnittlichen Fitnesswert aller Schüler addieren (multipliziert mit β)
   – Klassenrang bestimmen:
     * Die besten Klassen erhalten einen niedrigen Rang (1, 2, 3...)
     * Die schlechtesten Klassen erhalten einen hohen Rang
   
   Schritt 6: Die beste Lösung merken
   – Wenn ein Lehrer besser ist als unser Rekordwert
   – Als neuen Rekord speichern
   
   Schritt 7: Verlauf speichern
   – Die aktuellen Positionen aller Schüler speichern
   – Dies wird für das persönliche Training benötigt

3. ABSCHLUSS:
   – Rückgabe der besten gefundenen Lösung
   – Und dessen Fitnesswert

Beginnen wir nun mit dem Schreiben des Algorithmus-Codes. Die Klasse C_AO_CLA_l erbt von der Basisklasse C_AO und implementiert einen Algorithmus, der auf dem Konzept des kompetitiven Lernens basiert. Die Klasse enthält eine Reihe von benutzerkonfigurierbaren Parametern:

  • popSize – Populationsgröße (Anzahl der „Agenten“ oder „Schüler“);
  • numClasses – Anzahl der Klassen, in die Agenten unterteilt sind;
  • beta – Parameter, der wahrscheinlich die Geschwindigkeit des Lernens oder der Anpassung beeinflusst;
  • gamma – ein weiterer Parameter, der sich auf den Lernprozess bezieht;
  • deltaIter – die Iterationsnummer, nach der bestimmte Phasen des Algorithmus aktiviert werden.

Der Konstruktor initialisiert die Hauptparameter, legt den Namen und die Beschreibung des Algorithmus fest, setzt Standardwerte für die Variablen und dimensioniert das „params“-Array, das zum Speichern von Informationen über die Algorithmusparameter verwendet wird.

Methoden:

  • SetParams() aktualisiert die Werte der internen Variablen der Klasse (Algorithmusparameter) unter Verwendung der Werte aus dem „params“-Array. Dies ermöglicht es, extern festgelegte Parameter zu ändern.
  • Init() – initialisiert den Algorithmus. Übernimmt Parameter zur Definition der Grenzen und der Schrittweite der Parameteränderung.
  • Moving() – Hauptmethode für das „Bewegen“ von Agenten (Durchführung von Iterationen und Schritten des Algorithmus).
  • Revision() – Methode, die mit der Korrektur oder Verbesserung von Entscheidungen verbunden ist.
  • Injection() – Methode zum Einfügen von neuem Wissen oder neuen Daten in einen Agenten.
Felder der Klasse:
  • numClasses, beta, gamma, deltaIter – Algorithmusparameter.
  • currentIter, studentsPerClass, totalIters – interne Variablen zur Steuerung des Algorithmusablaufs.
  • teachers[] – Array von S_AO_Agent-Strukturen, die die „Lehrer“ in jeder Klasse (Ankerpunkte) repräsentieren.
  • classRanks[] – Klassenränge, die deren Leistung widerspiegeln.
  • classTotalCosts[] – Gesamtkosten oder „Kosten“ jeder Klasse.
  • CL [] – temporäres Array zur Berechnung des durchschnittlichen Wissens der Lehrer.
  • UpdateTeachersAndCosts() – interne Methode zur Aktualisierung von Informationen über Lehrer und deren Kosten.
  • UpdateClassRanks() – interne Methode zur Aktualisierung von Klassenrängen.
  • UpdateStudentsKnowledge() – interne Methode zur Aktualisierung von Wissen oder „Schüler“-Parametern.
//————————————————————————————————————————————————————————————————————
class C_AO_CLA_l : public C_AO
{
  public: //----------------------------------------------------------
  ~C_AO_CLA_l () { }
  C_AO_CLA_l ()
  {
    ao_name = "CLA_L";
    ao_desc = "Competitive Learning Algorithm";
    ao_link = "https://www.mql5.com/en/articles/18857";

    popSize        = 198;
    numClasses     = 3;
    beta           = 0.3;
    gamma          = 0.8;
    deltaIter      = 2;

    ArrayResize (params, 5);

    params [0].name = "popSize";     params [0].val = popSize;
    params [1].name = "numClasses";  params [1].val = numClasses;
    params [2].name = "beta";        params [2].val = beta;
    params [3].name = "gamma";       params [3].val = gamma;
    params [4].name = "deltaIter";   params [4].val = deltaIter;
  }

  void SetParams ()
  {
    popSize    = (int)params [0].val;
    numClasses = (int)params [1].val;
    beta       = params      [2].val;
    gamma      = params      [3].val;
    deltaIter  = (int)params [4].val;
  }

  bool Init (const double &rangeMinP  [],
             const double &rangeMaxP  [],
             const double &rangeStepP [],
             const int     epochsP = 0);

  void Moving   ();
  void Revision ();
  void Injection (const int popPos, const int coordPos, const double value) { }

  //------------------------------------------------------------------
  int    numClasses;
  double beta;
  double gamma;
  int    deltaIter;

  private: //---------------------------------------------------------
  int    currentIter;
  int    studentsPerClass;
  int    totalIters;

  // Structures for classes
  S_AO_Agent teachers        [];
  double     classRanks      [];
  double     classTotalCosts [];

  // Temporary array
  double     CL [];             // Average knowledge of teachers

  // Auxiliary methods
  void   UpdateTeachersAndCosts  ();
  void   UpdateClassRanks        ();
  void   UpdateStudentsKnowledge ();
};
//————————————————————————————————————————————————————————————————————

Die Methode Init() der Klasse C_AO_CLA_l initialisiert den Algorithmus, bevor er mit der Arbeit beginnt. Der Ablauf ist in mehrere Phasen unterteilt. Standardinitialisierung: die Methode StandardInit() wird aufgerufen und führt die Standardinitialisierung für den Optimierungsalgorithmus durch. Sie empfängt die Schrittparameter rangeMinP, rangeMaxP und rangeStepP. Wenn die Standardinitialisierung fehlschlägt, gibt die Methode Init() „false“ zurück.

Initialisierung der Algorithmusparameter: setzt den aktuellen Iterationszähler auf „0“ zurück, legt die Gesamtzahl der Iterationen fest, die der Algorithmus ausführen soll, unter Verwendung des im Argument epochsP übergebenen Wertes, und berechnet die Anzahl der „Schüler“ (Agenten) in jeder Klasse durch Division der Populationsgröße durch die Anzahl der Klassen. Als Nächstes prüft die Methode, ob mindestens ein Schüler in jeder Klasse vorhanden ist. Anschließend initialisiert die „for“-Schleife jeden Agenten in der Population. Für das Array a wird die Methode Init() für jeden Agenten aufgerufen, um dessen Koordinaten-Array zu initialisieren.

Die „for“-Schleife initialisiert einen „Lehrer“ für jede Klasse, setzt den Rang jeder Klasse auf 1.0 und setzt die anfänglichen „Kosten“ jeder Klasse auf einen negativen Maximalwert, um sicherzustellen, dass später eine bessere Lösung gefunden wird. Wenn alle Initialisierungsschritte erfolgreich abgeschlossen wurden, gibt die Methode „true“ zurück.

//————————————————————————————————————————————————————————————————————
bool C_AO_CLA_l::Init (const double &rangeMinP  [],
                       const double &rangeMaxP  [],
                       const double &rangeStepP [],
                       const int epochsP = 0)
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false;

  //------------------------------------------------------------------
  currentIter = 0;
  totalIters = epochsP;
  studentsPerClass = popSize / numClasses;

  if (studentsPerClass < 1)
  {
    Print ("Error: Too few students per class");
    return false;
  }

  // Adjust the population size
  //spopSize = studentsPerClass * numClasses;
  ArrayResize (a, popSize);
  for (int i = 0; i < popSize; i++) a [i].Init (coords);

  // Initialize class structures
  ArrayResize (teachers, numClasses);
  ArrayResize (classRanks, numClasses);
  ArrayResize (classTotalCosts, numClasses);

  for (int i = 0; i < numClasses; i++)
  {
    teachers        [i].Init (coords);
    classRanks      [i] = 1.0;
    classTotalCosts [i] = -DBL_MAX;
  }

  // Temporary array
  ArrayResize (CL, coords);

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

Die Methode Moving() der Klasse C_AO_CLA_l implementiert eine Iteration des Hauptoptimierungsalgorithmus, prüft, ob es sich um die erste Iteration handelt, und falls dies der Fall ist (d. h. „revision“ ist „false“), initialisiert die Methode die Positionen aller Agenten in der Population auf Zufallswerte im angegebenen Bereich. Sie iteriert über alle Agenten in der Population und für jeden Agenten über alle seine Koordinaten.

Für jede Koordinate generiert die Methode einen Zufallswert „val“ im Bereich von rangeMin[c] bis rangeMax[c], unter Verwendung der Methode u.RNDfromCI(), die eine Funktion zur Generierung von Zufallszahlen bereitstellt. Sie weist val der Koordinate a[i].c[c] des Agenten i zu, nachdem sie ihn zuvor begrenzt hat, sodass er innerhalb des zulässigen Bereichs liegt und dem angegebenen Schritt rangeStep[c] entspricht. Die Methode u.SeInDiSp() wird verwendet, die eine Überprüfung und Anpassung der Werte durchführt.

Nach der Initialisierung der Population wird ein Flag gesetzt, um anzuzeigen, dass die Initialisierung durchgeführt wurde. Wenn dies nicht die erste Iteration ist, wird der aktuelle Iterationszähler inkrementiert. Die Methode UpdateStudentsKnowledge() wird aufgerufen, um den Hauptmechanismus für das Training oder die Anpassung von Agenten gemäß den Prinzipien des kompetitiven Lernens, die im CLA_L-Algorithmus verwendet werden, zu implementieren. Die Logik dieser Methode bestimmt, wie Agenten interagieren, Informationen austauschen und ihre Positionen im Suchraum der Lösungen verbessern.

//————————————————————————————————————————————————————————————————————
void C_AO_CLA_l::Moving ()
{
  // Initial population setup
  if (!revision)
  {
    for (int i = 0; i < popSize; i++)
    {
      for (int c = 0; c < coords; c++)
      {
        double val = u.RNDfromCI (rangeMin [c], rangeMax [c]);
        a [i].c [c] = u.SeInDiSp (val, rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }
    revision = true;
    return;
  }

  currentIter++;

  // Update students' knowledge
  UpdateStudentsKnowledge ();
}
//————————————————————————————————————————————————————————————————————

Die Methode UpdateStudentsKnowledge() ist für die Aktualisierung der Position jedes Schülers (Agenten) während der Optimierung verantwortlich. Der aktuelle Optimierungsfortschritt wird berechnet. Zwei wichtige Lernfaktoren werden berechnet:

  • TF (Teaching Factor) – zeigt, wie viel ein Schüler von einem Lehrer lernt.
  • CF (Confirmatory Factor) – zeigt das Ausmaß, in dem ein Schüler das Durchschnittswissen der Lehrer berücksichtigt. Diese Faktoren hängen vom Fortschritt des Schülers und dem Klassenrang ab.

Als Nächstes wird der Durchschnittswert der Koordinaten aller „aktiven“ Lehrer (Lehrer, deren Fitnesswert gültig ist) berechnet. Dieses Durchschnittswissen wird in einem temporären Array gespeichert. Für jeden Schüler (Agenten) wird die Klasse bestimmt, der der Schüler angehört, und für jede Koordinate des Schülers wird eine neue Schülerposition berechnet, indem die aktuelle Koordinate mit den „Wissensquellen“ summiert wird. Der Schüler lernt von seinem Lehrer, indem er seine Position um einen Betrag anpasst, der proportional zur Differenz zwischen der Koordinate des Lehrers und seiner eigenen ist, multipliziert mit TF. Wenn genügend Iterationen vergangen sind (currentIter > deltaIter) und der Schüler eine „beste Lösung“ hat, lernt der Schüler aus seiner früheren erfolgreichen Erfahrung, indem er seine Position in Richtung der besten Koordinate anpasst, multipliziert mit einem Zufallsfaktor.

Wenn genügend Iterationen vergangen sind und die Anzahl der Lehrer gültig ist, lernt der Schüler aus dem Durchschnittswissen aller Lehrer und passt seine Position in Richtung der durchschnittlichen Koordinate, multipliziert mit CF, mit einer gewissen Wahrscheinlichkeit (1-gamma) an. Grenzen (Beschränkungen) werden auf jede Schüler-Koordinate angewendet, um sicherzustellen, dass der Wert innerhalb des zulässigen Bereichs liegt. Der Wert wird angepasst, um den zulässigen Werten unter Berücksichtigung der Schrittweite des Suchraums zu entsprechen.

//————————————————————————————————————————————————————————————————————
void C_AO_CLA_l::UpdateStudentsKnowledge ()
{
  // Calculate learning factors for the current iteration
  double progress = (double)currentIter / (double)MathMax (totalIters, 100);

  // Calculate the average knowledge of all teachers (CL)
  ArrayInitialize (CL, 0.0);
  int validTeachers = 0;

  for (int k = 0; k < numClasses; k++)
  {
    // Make sure the teacher is initialized
    if (teachers [k].f > -DBL_MAX)
    {
      for (int c = 0; c < coords; c++)
      {
        CL [c] += teachers [k].c [c];
      }
      validTeachers++;
    }
  }

  if (validTeachers > 0)
  {
    for (int c = 0; c < coords; c++)
    {
      CL [c] /= validTeachers;
    }
  }

  // Update each student
  for (int i = 0; i < popSize; i++)
  {
    int classIdx = i / studentsPerClass;

    // Teaching Factor - decreases with progress
    double TF = MathExp (-0.6 * progress * classRanks [classIdx]);
    TF = MathMax (0.1, MathMin (1.0, TF));

    // Confirmatory Factor
    double CF = MathExp (-0.5 * progress * classRanks [classIdx]);
    CF = MathMax (0.1, MathMin (1.0, CF));

    // Update the student position
    for (int c = 0; c < coords; c++)
    {
      double newPos = a [i].c [c];

      // a) Teacher Learning - learn from the class teacher
      if (teachers [classIdx].f > -DBL_MAX)
      {
        newPos += TF * (teachers [classIdx].c [c] - a [i].c [c]);
      }

      // b) Personal Learning - learn from your best solution
      if (currentIter > deltaIter && a [i].fB > -DBL_MAX)
      {
        double PF = u.RNDprobab ();
        newPos += PF * (a [i].cB [c] - a [i].c [c]);
      }

      // c) Confirmatory Learning - learn from the average of all teachers
      if (currentIter > deltaIter && validTeachers > 0)
      {
        double rnd = u.RNDprobab ();
        if (rnd >= gamma) // Participate with probability (1-gamma)
        {
          newPos += CF * (CL [c] - a [i].c [c]);
        }
      }

      // Apply borders
      a [i].c [c] = u.SeInDiSp (newPos, rangeMin [c], rangeMax [c], rangeStep [c]);
    }
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode Revision() in der Klasse C_AO_CLA_l wird verwendet, um Informationen über die besten Lösungen jedes Agenten zu aktualisieren sowie die globale beste Lösung und die entsprechenden Parameter zu aktualisieren.

Für jeden Agenten wird geprüft, ob sich sein aktueller Zielfunktionswert (a[i].f) im Vergleich zu seinem gespeicherten besten Wert (a[i].fB) verbessert hat. Falls ja, wird der beste Wert gespeichert und die entsprechenden Koordinaten werden kopiert. Nach der Überprüfung aller Agenten werden die globalen Parameter aktualisiert, falls einer von ihnen einen besseren Funktionswert als das aktuelle globale Maximum (fB) erzielt hat: fB ist der global beste Funktionswert und cB sind die Koordinaten dieser besten Lösung.

Als Nächstes wird die Methode UpdateTeachersAndCosts() aufgerufen, die Informationen über die besten Lehrer aktualisiert. Am Ende wird UpdateClassRanks() aufgerufen, um die Klassenränge neu zu berechnen, was die Priorität bei der Auswahl bestimmter Lösungen in nachfolgenden Iterationen beeinflusst.

//————————————————————————————————————————————————————————————————————
void C_AO_CLA_l::Revision ()
{
  for (int i = 0; i < popSize; i++)
  {
    // Update personal best positions
    if (a [i].f > a [i].fB)
    {
      a [i].fB = a [i].f;
      ArrayCopy (a [i].cB, a [i].c);
    }
    // Update the global best one
    if (a [i].f > fB)
    {
      fB = a [i].f;
      ArrayCopy (cB, a [i].c);
    }
  }

  // Update teachers 
  UpdateTeachersAndCosts ();

  // Update class ranks
  UpdateClassRanks ();
}
//————————————————————————————————————————————————————————————————————

Die Methode UpdateTeachersAndCosts() wird verwendet, um Informationen über Lehrer in jeder Klasse zu aktualisieren und die Gesamtkosten der Klasse zu berechnen. Die Methode durchläuft alle im System definierten Klassen. Für jede Klasse werden die Anfangs- und Endindizes der in dieser Klasse enthaltenen Schüler (Agenten) bestimmt.

Um den besten Schüler der Klasse zu finden, werden Variablen initialisiert, um den besten Funktionswert, den Index des besten Schülers, die Summe der Funktionswerte aller Schüler in der Klasse und die Anzahl der gültigen Schüler zu speichern. Der Zyklus durchläuft alle Schüler in der aktuellen Klasse. Für jeden Schüler wird geprüft, ob seine Lösung gültig ist, und wenn die Lösung gültig ist, dann: der Fitnesswert des Schülers wird zu sumFitness addiert, der Zähler der gültigen Schüler wird erhöht, und wenn der Fitnesswert des aktuellen Schülers besser als der aktuelle Bestwert bestFitness ist, dann wird dieser aktualisiert und bestIdx wird aktualisiert.

Nachdem der beste Schüler der Klasse gefunden wurde, wird geprüft, ob es mindestens einen gültigen Schüler in der Klasse gab (validStudents > 0). Wenn die Bedingung erfüllt ist, werden die Koordinaten des besten Schülers in die Koordinaten des Lehrers der entsprechenden Klasse kopiert und der Wert der Funktion des besten Schülers wird dem Wert der Funktion des Lehrers zugewiesen.

Der Durchschnittswert der Funktion aller Schüler in der Klasse avgFitness wird berechnet. Die gesamten „Kosten“ der Klasse werden als Summe aus dem Wert der Funktion des besten Schülers und dem Produkt aus dem „Beta“-Koeffizienten und dem Durchschnittswert der Funktion aller Schüler berechnet. Es ist eine Kombination aus Lehrereffektivität und der durchschnittlichen Klassenleistung.

//————————————————————————————————————————————————————————————————————
void C_AO_CLA::UpdateTeachersAndCosts ()
{
  for (int k = 0; k < numClasses; k++)
  {
    int startIdx = k * studentsPerClass;
    int endIdx = startIdx + studentsPerClass;

    double bestFitness = -DBL_MAX;
    int bestIdx = startIdx;
    double sumFitness = 0.0;
    int validStudents = 0;

    // Find the best student (teacher) in the class
    for (int i = startIdx; i < endIdx; i++)
    {
      if (a[i].f > -DBL_MAX) // Validity check
      {
        sumFitness += a[i].f;
        validStudents++;
        
        if (a[i].f > bestFitness)
        {
          bestFitness = a[i].f;
          bestIdx = i;
        }
      }
    }

    // Update the teacher
    if (validStudents > 0)
    {
      ArrayCopy (teachers[k].c, a[bestIdx].c);
      teachers[k].f = bestFitness;
      
      // Calculate the class total cost
      double avgFitness = sumFitness / validStudents;
      classTotalCosts[k] = bestFitness + beta * avgFitness;
    }
  }
}
//————————————————————————————————————————————————————————————————————

Die Methode UpdateClassRanks() wird verwendet, um die Ränge der Klassen basierend auf ihren Gesamtkosten zu bestimmen, was charakterisiert, wie effektiv die Klasse ist. Der Prozess beginnt mit der Ermittlung der minimalen und maximalen Kosten unter allen gültigen Klassen. Wenn alle Klassen denselben Wert haben oder keine gültigen Klassen vorhanden sind, wird für alle derselbe Rang 1 festgelegt.

Wenn es Unterschiede bei den Kosten gibt, werden diese Werte normalisiert – jeder Kostenwert wird auf einen Bereich von 0 bis 1 normiert. Danach wird eine Inversion durchgeführt: Klassen mit höheren Kosten erhalten einen niedrigeren Rang nahe 1, und solche mit niedrigeren Kosten erhalten einen maximalen Rang, der der Anzahl der Klassen entspricht.

Jeder Rangwert wird dann auf einen Minimal- und Maximalwert begrenzt, um Werte außerhalb des zulässigen Bereichs zu vermeiden. Letztendlich werden den Klassen basierend auf den Ergebnissen dieser Methode Ränge entsprechend ihrer Leistung zugewiesen.

//————————————————————————————————————————————————————————————————————
void C_AO_CLA_l::UpdateClassRanks ()
{
  // Find the min and max costs among valid classes
  double minCost   = DBL_MAX;
  double maxCost   = -DBL_MAX;
  int validClasses = 0;

  for (int k = 0; k < numClasses; k++)
  {
    if (classTotalCosts [k] > -DBL_MAX)
    {
      if (classTotalCosts [k] < minCost) minCost = classTotalCosts [k];
      if (classTotalCosts [k] > maxCost) maxCost = classTotalCosts [k];
      validClasses++;
    }
  }

  if (validClasses == 0 || maxCost - minCost < 1e-10)
  {
    // All classes have the same score
    for (int k = 0; k < numClasses; k++) classRanks [k] = 1.0;
  }
  else
  {
    // Ranking: best classes (high cost) get low rank
    for (int k = 0; k < numClasses; k++)
    {
      if (classTotalCosts [k] > -DBL_MAX)
      {
        // Normalize from 0 to 1
        double normalized = (classTotalCosts [k] - minCost) / (maxCost - minCost);

        // Inversion: the best get a rank close to 1
        classRanks [k] = 1.0 + (1.0 - normalized) * (numClasses - 1.0);

        // Limitation
        classRanks [k] = MathMax (1.0, MathMin ((double)numClasses, classRanks [k]));
      }
      else
      {
        classRanks [k] = numClasses; // Worst rank for uninitialized
      }
    }
  }
}
//————————————————————————————————————————————————————————————————————


Testergebnisse

Dem Test zufolge liefert der CLA_L-Algorithmus recht gute Ergebnisse.

CLA_L|Competitive Learning Algorithm|198.0|3.0|0.3|0.8|2.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.6482993681242128
25 Hilly's; Func runs: 10000; result: 0.5535249826770444
500 Hilly's; Func runs: 10000; result: 0.2584959913710746
=============================
5 Forest's; Func runs: 10000; result: 0.8027208362980616
25 Forest's; Func runs: 10000; result: 0.49540442971179494
500 Forest's; Func runs: 10000; result: 0.20048686632188017
=============================
5 Megacity's; Func runs: 10000; result: 0.6353846153846153
25 Megacity's; Func runs: 10000; result: 0.2716923076923076
500 Megacity's; Func runs: 10000; result: 0.10086153846153936
=============================
All score: 3.96687 (44.08%)

Die Visualisierung zeigt, dass der Algorithmus anfangs gute Suchfähigkeiten aufweist, die sich jedoch aufgrund lokaler Fallen verschlechtern, was in der zweiten Hälfte des Algorithmusbetriebs zu einer Stagnation führt.

Hilly

CLA_L mit der Testfunktion Hilly

Forest

CLA_L mit der Testfunktion Forest

Megacity

CLA_L mit der Testfunktion Megacity

Basierend auf den Ergebnissen der Arbeit des Algorithmus wird die CLA_L-Rangliste zu Informationszwecken bereitgestellt.

# AO Beschreibung Hilly Hilly
Final
Forest Forest
Final
Megacity (discrete) Megacity
Final
Final
Result
% of
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)
1ANSSuche über die gesamte Nachbarschaft0.949480.847760.438572.235811.000000.923340.399882.323230.709230.634770.230911.574916.13468.15
2CLACode-Lock-Algorithmus (joo)0.953450.871070.375902.200420.989420.917090.316422.222940.796920.693850.193031.683806.10767.86
3AMOmOptimierung der Tiermigration M0.903580.843170.462842.209590.990010.924360.465982.380340.567690.591320.237731.396755.98766.52
4(P+O)ES(P+O) Evolutionsstrategien0.922560.881010.400212.203790.977500.874900.319452.171850.673850.629850.186341.490035.86665.17
5CTAKometenschweif-Algorithmus (joo)0.953460.863190.277702.094350.997940.857400.339492.194840.887690.564310.105121.557125.84664.96
6TETAZeit-Evolutions-Reise-Algorithmus (Joo)0.913620.823490.319902.057010.970960.895320.293242.159520.734620.685690.160211.580525.79764.41
7SDSmstochastische Diffusionssuche M0.930660.854450.394762.179880.999830.892440.196192.088460.723330.611000.106701.441035.70963.44
8BOAmBillard-Optimierungsalgorithmus M0.957570.825990.252352.035901.000000.900360.305022.205380.735380.525230.095631.356255.59862.19
9AAmAlgorithmus für das Bogenschießen M0.917440.708760.421602.047800.925270.758020.353282.036570.673850.552000.237381.463235.54861.64
10ESGEntwicklung sozialer Gruppen (joo)0.999060.796540.350562.146161.000000.828630.131021.959650.823330.553000.047251.423585.52961.44
11SIASimuliertes isotropes Glühen (Joo)0.957840.842640.414652.215130.982390.795860.205071.983320.686670.493000.090531.270205.46960.76
12EOmextremal_optimization_M0.761660.772420.317471.851550.999990.767510.235272.002770.747690.539690.142491.429875.28458.71
13BBObiogeografisch basierte Optimierung0.949120.694560.350311.993990.938200.673650.256821.868670.746150.482770.173691.402615.26558.50
14ACSkünstliche, kooperative Suche0.755470.747440.304071.806981.000000.888610.224132.112740.690770.481850.133221.305835.22658.06
15DAdialektischer Algorithmus0.861830.700330.337241.899400.981630.727720.287181.996530.703080.452920.163671.319675.21657.95
16BHAmAlgorithmus für schwarze Löcher M0.752360.766750.345831.864930.935930.801520.271772.009230.650770.516460.154721.321955.19657.73
17ASOAnarchische Gesellschaftsoptimierung0.848720.746460.314651.909830.961480.791500.238031.991010.570770.540620.166141.277525.17857.54
18RFOOptimierung des Royal Flush (joo)0.833610.737420.346291.917330.894240.738240.240981.873460.631540.502920.164211.298675.08956.55
19AOSmSuche nach atomaren Orbitalen M0.802320.704490.310211.817020.856600.694510.219961.771070.746150.528620.143581.418355.00655.63
20TSEASchildkrötenpanzer-Evolutionsalgorithmus (joo)0.967980.644800.296721.909490.994490.619810.227081.841390.690770.426460.135981.253225.00455.60
21BSABacktracking-Suchalgorithmus0.973090.545340.290981.809410.999990.585430.217471.802890.847690.369530.129781.347004.95955.10
22DEdifferentielle Evolution0.950440.616740.303081.870260.953170.788960.166521.908650.786670.360330.029531.176534.95555.06
23SRAAlgorithmus für erfolgreiche Gastronomen (joo)0.968830.634550.292171.895550.946370.555060.191241.692670.749230.440310.125261.314804.90354.48
24CROOptimierung chemischer Reaktionen0.946290.661120.298531.905930.879060.584220.211461.674730.758460.426460.126861.311784.89254.36
25BIOOptimierung der Blutvererbung (joo)0.815680.653360.308771.777810.899370.653190.217601.770160.678460.476310.139021.293784.84253.80
26BSAVogelschwarm-Algorithmus0.893060.649000.262501.804550.924200.711210.249391.884790.693850.326150.100121.120124.80953.44
27DEAAlgorithmus zur Echoortung bei Delfinen0.759950.675720.341711.777380.895820.642230.239411.777460.615380.440310.151151.206844.76252.91
28HSHarmoniesuche0.865090.687820.325271.878180.999990.680020.095901.775920.620000.422670.054581.097254.75152.79
29SSGSetzen, Säen und Wachsen0.778390.649250.395431.823080.859730.624670.174291.658690.646670.441330.105981.193984.67651.95
30BCOmOptimierung mit der bakteriellen Chemotaxis M0.759530.622680.314831.697040.893780.613390.225421.732590.653850.420920.144351.219124.64951.65
31ABOOptimierung des afrikanischen Büffels0.833370.622470.299641.755480.921700.586180.197231.705110.610000.431540.132251.173784.63451.49
32(PO)ES(PO) Evolutionsstrategien0.790250.626470.429351.846060.876160.609430.195911.681510.590000.379330.113221.082554.61051.22
33FBAFraktal-basierter Algorithmus0.790000.651340.289651.730990.871580.568230.188771.628580.610770.460620.123981.195374.55550.61
34TSmTabu-Suche M0.877950.614310.291041.783300.928850.518440.190541.637830.610770.382150.121571.114494.53650.40
35BSOBrainstorming-Optimierung0.937360.576160.296881.810410.931310.558660.235371.725340.552310.290770.119140.962224.49849.98
36WOAmWal-Optimierungsalgorithmus M0.845210.562980.262631.670810.931000.522780.163651.617430.663080.411380.113571.188034.47649.74
37AEFAAlgorithmus für künstliche elektrische Felder0.877000.617530.252351.746880.927290.726980.180641.834900.666150.116310.095080.877544.45949.55
38AEOAlgorithmus zur Optimierung auf der Grundlage künstlicher Ökosysteme0.913800.467130.264701.645630.902230.437050.214001.553270.661540.308000.285631.255174.45449.49
39CAmKamel-Algorithmus M0.786840.560420.351331.698590.827720.560410.243361.631490.648460.330920.134181.113564.44449.37
40ACOmAmeisen-Kolonie-Optimierung M0.881900.661270.303771.846930.858730.586800.150511.596040.596670.373330.024720.994724.43849.31
41CMAESAnpassung der Kovarianzmatrix mittels Evolutionsstrategie0.762580.720890.000001.483470.820560.796160.000001.616720.758460.490770.000001.249234.34948.33
42BFO-GAOptimierung der bakteriellen Futtersuche – ga0.891500.551110.315291.757900.969820.396120.063051.428990.726670.275000.035251.036924.22446.93
43SOAeinfacher Optimierungsalgorithmus0.915200.469760.270891.655850.896750.374010.169841.440600.695380.280310.108521.084224.18146.45
44ABHAAlgorithmus für künstliche Bienenstöcke0.841310.542270.263041.646630.878580.477790.171811.528180.509230.338770.103970.951974.12745.85
45ACMOOptimierung atmosphärischer Wolkenmodelle0.903210.485460.304031.692700.802680.378570.191781.373030.623080.244000.107950.975034.04144.90
CLA_LAlgorithmus des kompetitiven Lernens0.648290.553520.258491.460300.802720.495400.200481.498600.635380.271690.100861.007933.96744.08
RWRandom Walk0.487540.321590.257811.066940.375540.219440.158770.753750.279690.149170.098470.527342.34826.09


Zusammenfassung

Der wettbewerbsorientierte Lernalgorithmus (CLA_L) zeigt eine durchschnittliche Leistung bei der Lösung von Standardoptimierungsproblemen. Die Analyse der Funktionsweise des Algorithmus ergab eine charakteristische Zweiphasendynamik: eine aktive Explorationsphase in den ersten Iterationen und eine vorzeitige Stagnationsphase in der zweiten Hälfte des Optimierungsprozesses.

Die Unterteilung der Population in Klassen gewährleistet eine gute Abdeckung des Suchraums in den frühen Stadien. Jede Klasse erkundet ihren eigenen Bereich, was zu einer globalen Suche beiträgt. Das Bildungsmodell macht den Algorithmus anschaulich und leicht interpretierbar. Die Konzepte von Lehrern, Schülern und verschiedenen Lernarten sind natürlich zu verstehen. Lernfaktoren, die vom Klassenrang abhängen, sollten theoretisch ein Gleichgewicht zwischen Exploration und Exploitation bieten. Die Kombination aus drei Lernarten (Lehrerlernen, persönliches Lernen und Lernen vom durchschnittlichen Lehrer) schafft das Potenzial, lokale Optima zu vermeiden. Trotz der Diversifizierungsmechanismen neigt der Algorithmus dazu, in lokalen Optima stecken zu bleiben. 

Der CLA-Algorithmus stellt ein interessantes Konzept dar, eine Bildungsmetapher auf Optimierungsprobleme anzuwenden. Trotz des innovativen Ansatzes und der guten Anfangsleistung erfordert der Algorithmus erhebliche Modifikationen, um mit modernen Metaheuristiken konkurrenzfähig zu sein. Die größte Herausforderung bleibt die Gewährleistung eines Gleichgewichts zwischen Exploration und Exploitation während des gesamten Optimierungsprozesses.

Tabelle

Abbildung 2. Farbcodierung der Algorithmen nach Test

Histogramm

Abbildung 3. Histogramm der Algorithmus-Testergebnisse (Skala von 0 bis 100, je höher, desto besser, wobei 100 das maximal mögliche theoretische Ergebnis ist; im Archiv befindet sich ein Skript zur Berechnung der Bewertungstabelle)

Vor- und Nachteile von CLA_L:

Vorteile:

  1. Schnell.

Nachteile:

  1. Eine große Anzahl von externen Parametern.
  2. Neigt dazu, in lokalen Optima stecken zu bleiben.

Dem Artikel ist ein Archiv mit den aktuellen Versionen der Algorithmuscodes beigefügt. Der Autor des Artikels übernimmt keine Verantwortung für die absolute Richtigkeit der Beschreibung der kanonischen Algorithmen. An vielen von ihnen wurden Änderungen vorgenommen, um die Suchmöglichkeiten zu verbessern. Die in den Artikeln dargelegten Schlussfolgerungen und Urteile beruhen auf den Ergebnissen der Experimente.


Im Artikel verwendete Programme

#NameTypBeschreibung
1#C_AO.mqh
Include
Übergeordnete Klasse von Populationsoptimierungsalgorithmen
2#C_AO_enum.mqh
Include
Enumeration der Algorithmen zur Populationsoptimierung
3TestFunctions.mqh
Include
Bibliothek mit Testfunktionen
4
TestStandFunctions.mqh
Include
Bibliothek mit Funktionen für die Testumgebung
5
Utilities.mqh
Include
Bibliothek mit Hilfsfunktionen
6
CalculationTestResults.mqh
Include
Skript zur Berechnung der Ergebnisse in der Vergleichstabelle
7
Testing AOs.mq5
SkriptDie einheitliche Testumgebung für alle Algorithmen zur Populationsoptimierung
8
Simple use of population optimization algorithms.mq5
Skript
Ein einfaches Beispiel für die Verwendung von Algorithmen zur Populationsoptimierung ohne Visualisierung
9
Test_AO_CLA_L.mq5
SkriptCLA_L-Teststand

Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/18857

Beigefügte Dateien |
CLA_I.zip (250.43 KB)
Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Von der Grundstufe bis zur Mittelstufe: Arbeiten mit Dateien in der Sandbox von MetaTrader 5 Von der Grundstufe bis zur Mittelstufe: Arbeiten mit Dateien in der Sandbox von MetaTrader 5
Wissen Sie, was eine Sandbox ist? Wissen Sie, wie man damit arbeitet? Wenn Sie eine der beiden Fragen mit „Nein“ beantworten, lesen Sie diesen Artikel, um das grundlegende Funktionsprinzip einer Sandbox zu verstehen. Sie werden auch verstehen, warum MetaTrader 5 eine Sandbox verwendet, um die Integrität einiger seiner internen Daten zu schützen. Das hier präsentierte Material dient rein zu Lehrzwecken. Unter keinen Umständen sollten Sie die Anwendung als fertiges Produkt ansehen, dessen Zweck etwas anderes ist, als die vorgestellten Konzepte zu studieren.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
Quantenneuronales Netz in MQL5 (Teil I): Erstellen der Include-Datei Quantenneuronales Netz in MQL5 (Teil I): Erstellen der Include-Datei
Der Artikel stellt einen neuen Ansatz zur Erstellung von Handelssystemen auf der Grundlage quantenmechanischer Prinzipien und künstlicher Intelligenz vor. Der Autor beschreibt die Entwicklung eines einzigartigen neuronalen Netzes, das über klassisches maschinelles Lernen hinausgeht, indem es Quantenmechanik mit modernen KI-Architekturen kombiniert.