Diskussion zum Artikel "Neuronale Netze leicht gemacht (Teil 66): Explorationsprobleme beim Offline-Lernen"
Dmitry Hallo. Hier steht, dass Sie 5 Agenten eingesetzt und damit 100 Pässe gesammelt haben. Haben Sie die Sammlung 20 Mal durchgeführt? Sonst werden nur 5 Pässe von 5 Agenten gesammelt. Außerdem, wenn Sie den Expert Advisor mit denselben Parametern ausführen, berechnet er nicht neu, sondern holt das Ergebnis aus dem Cache. Oder haben Sie diese 5 Agenten bei jeder nachfolgenden Erfassung verschoben? Bitte erklären Sie diesen Punkt.
Ich habe ihn 20 Mal ausgeführt, aber den Cache vor der Ausführung geleert. Sie können die Agenten nicht verschieben, weil die Modelldatei an die Agentennummer gebunden ist. Wenn Sie also jedes Mal die Agenten verschieben, wird ein neues Zufallsmodell erstellt, und wir werden nicht den gewünschten Effekt erzielen.
Ich habe es 20 Mal ausgeführt, aber den Cache vor dem Start geleert. Man kann die Agenten nicht verschieben, weil die Modelldatei mit der Agentennummer verknüpft ist. Wenn die Agenten verschoben werden, wird daher jedes Mal ein neues Zufallsmodell erstellt, und wir werden nicht den gewünschten Effekt erzielen.
dann Agent auf 5 und Optimierung auf 20 setzen
Insgesamt 100...
dann Agent auf 5 und Optimierung auf 20 setzen
Insgesamt 100...
Hallo,
Wie viele Kerne haben Sie verwendet?
Ich weiß nicht, wie MetaTrader Tester die Eingaben für die einzelnen Kerne auswählt. Die Hauptidee in der Online-Studie ist die Verwendung eines vortrainierten Modells von einem Durchgang zum anderen. Aber wenn der Tester Optimithation 1..4 zu Agent 1 in einem Durchgang laufen lässt, verwenden sie alle ein zufälliges (nicht vortrainiertes) Modell.
Ich weiß nicht, wie MetaTrader Tester die Eingaben für jeden Kern auswählt. Die Hauptidee in der Online-Studie ist die Verwendung eines vortrainierten Modells von einem Durchgang zum anderen. Aber wenn Tester laufen Optimithation 1..4 zu Agent 1 in einem Durchgang die sie alle verwenden zufällige (nicht pretrained) Modell.
Ich habe auch einige Indikatoren und Parameter hinzugefügt, insgesamt 27 BarDescr.... Momentum, Bands & Ichimoku Kinko Hyo =)
int OnInit()
{
Symbol setzen und aktualisieren
if(! Symb.Name(_Symbol))
return INIT_FAILED;
Symb.Refresh();
//---
if(! RSI. Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice))
return INIT_FAILED;
//---
if(! CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice))
return INIT_FAILED;
//---
if(! ATR. Create(Symb.Name(), TimeFrame, ATRPeriod))
return INIT_FAILED;
//---
if(! MACD. Create(Symb.Name(), TimeFrame, FastPeriod, SlowPeriod, SignalPeriod, MACDPrice)))
return INIT_FAILED;
//---
if (! Momentum.Create(Symb.Name(), TimeFrame, MomentumMaPeriod, MomentumApplied))
return INIT_FAILED;
Initialisieren Sie den Ichimoku Kinko Hyo Indikator
if (! Ichimoku.Create(Symb.Name(), TimeFrame, Ichimokutenkan_senPeriod, Ichimokukijun_senPeriod, Ichimokusenkou_span_bPeriod)))
return INIT_FAILED;
//---
if (! Bands.Create(Symb.Name(), TimeFrame, BandsMaPeriod, BandsMaShift, BandsDeviation, BandsApplied))
return INIT_FAILED;
//---
if(! RSI. BufferResize(HistoryBars) || ! CCI.BufferResize(HistoryBars) ||
! ATR. BufferResize(HistoryBars) || ! MACD. BufferResize(HistoryBars))
{
PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
return INIT_FAILED;
}
//---
void OnTick()
{
//---
if(! IsNewBar())
zurück;
//---
int bars = CopyRates(Symb.Name(), TimeFrame, iTime(Symb.Name(), TimeFrame, 1), HistoryBars, Rates);
if(! ArraySetAsSeries(Kurse, true))
zurückgeben;
//---
RSI. Refresh();
CCI.Refresh();
ATR. Aktualisieren();
MACD. Aktualisieren();
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
Ichimoku-Werte für den aktuellen Balken aktualisieren
Ichimoku.Refresh();
--- Historische Daten
float atr = 0;
for (int b = 0; b < (int)HistoryBars; b++)
{
float open = (float)Kurse[b].open;
float close = (float)Kurse[b].close;
float rsi = (float)RSI. Main(b);
float cci = (float)CCI.Main(b);
atr = (float)ATR. Main(b);
float macd = (float)MACD. Main(b);
float sign = (float)MACD. Signal(b);
float mome = (float)Momentum.Main(b);
float bandzup = (float)Bands.Upper(b);
float bandzb = (float)Bands.Base(b);
float bandzlo = (float)Bands.Lower(b);
float tenkan = (float)Ichimoku.TenkanSen(0); Den berechneten Wert verwenden
float kijun = (float)Ichimoku.KijunSen(1); Verwende den berechneten Wert
float senkasa = (float)Ichimoku.SenkouSpanA(2); Verwende den berechneten Wert
float senkb = (float)Ichimoku.SenkouSpanB(3); Verwende den berechneten Wert
Prüfung auf EMPTY_VALUE und Division durch Null
if (rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE ||
sign == EMPTY_VALUE || mome == EMPTY_VALUE || bandzup == EMPTY_VALUE || bandzb == EMPTY_VALUE ||
bandzlo == EMPTY_VALUE || tenkan == EMPTY_VALUE || kijun == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkasa == EMPTY_VALUE ||
senkb == EMPTY_VALUE || kijun == 0.0 || senkb == 0.0)
{
weiter;
}
Sicherstellen, dass die Größe der Puffer innerhalb der Schleife nicht geändert wird
int shift = b * BarDescr;
sState.state[shift] = (float)(Raten[b].close - open);
sState.state[shift + 1] = ((float)(Kurse[b].close - open) + (tenkan - kijun)) / 2.0f;
sState.state[shift + 2] = (float)(Kurse[b].hoch - offen);
sState.state[shift + 3] = (float)(Kurse[b].low - open);
sState.state[shift + 4] = (float)(Kurse[b].high - close);
sState.state[shift + 5] = (float)(Kurse[b].low - close);
sState.state[shift + 6] = (tenkan - kijun);
sState.state[shift + 7] = (float)(Kurse[b].tick_volume / 1000.0f);
sState.state[shift + 8] = ((float)(Kurse[b].high) - (float)(Kurse[b].low));
sState.state[shift + 9] = (bandzup - bandzlo);
sState.state[shift + 10] = rsi;
sState.state[shift + 11] = cci;
sState.state[shift + 12] = atr;
sState.state[shift + 13] = macd;
sState.state[shift + 14] = sign;
sState.state[shift + 15] = mome;
sState.state[shift + 16] = (float)(Rates[b].open - tenkan);
sState.state[shift + 17] = (float)(Kurse[b].open - kijun);
sState.state[shift + 18] = (float)(Kurse[b].open - bandzb);
sState.state[shift + 19] = (float)(Kurse[b].open - senkasa);
sState.state[shift + 20] = (float)(Kurse[b].open - senkb);
sState.state[shift + 21] = (float)(Kurse[b].close - tenkan);
sState.state[shift + 22] = (float)(Kurse[b].close - kijun);
sState.state[shift + 23] = (float)(Kurse[b].close - bandzb);
sState.state[shift + 24] = (float)(Kurse[b].close - senkasa);
sState.state[shift + 25] = (float)(Kurse[b].close - senkb);
sState.state[shift + 26] = senkasa - senkb;
//---
RSI.Refresh();
CCI.Refresh();
ATR.Refresh();
MACD.Refresh();
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
// Aktualisieren der Ichimoku-Werte für den aktuellen Balken
Ichimoku.Refresh();
//---
Print("Zustand 0: ", sState.state[shift]);
Print("Zustand 1: ", sState.state[shift + 1]);
Print("Zustand 2: ", sState.state[shift + 2]);
Print("Zustand 3: ", sState.state[shift + 3]);
Print("Zustand 4: ", sState.state[shift + 4]);
Print("Zustand 5: ", sState.state[shift + 5]);
Print("Zustand 6: ", sState.state[shift + 6]);
Print("Zustand 7: ", sState.state[shift + 7]);
Print("Zustand 8: ", sState.state[shift + 8]);
Print("Zustand 9: ", sState.state[shift + 9]);
Print("Zustand 10: ", sState.state[shift + 10]);
Print("Zustand 11: ", sState.state[shift + 11]);
Print("Zustand 12: ", sState.state[shift + 12]);
Print("Zustand 13: ", sState.state[shift + 13]);
Print("Zustand 14: ", sState.state[shift + 14]);
Print("Zustand 15: ", sState.state[shift + 15]);
Print("Zustand 16: ", sState.state[shift + 16]);
Print("Zustand 17: ", sState.state[shift + 17]);
Print("Zustand 18: ", sState.state[shift + 18]);
Print("Zustand 19: ", sState.state[shift + 19]);
Print("Zustand 20: ", sState.state[shift + 20]);
Print("Zustand 21: ", sState.state[shift + 21]);
Print("Zustand 22: ", sState.state[shift + 22]);
Print("Zustand 23: ", sState.state[shift + 23]);
Print("Zustand 24: ", sState.state[shift + 24]);
Print("Zustand 25: ", sState.state[shift + 25]);
Print("Zustand 26: ", sState.state[shift + 26]);
Print("Tenkan Sen: ", tenkan);
Print("Kijun Sen: ", kijun);
Print("Senkou Span A: ", senkasa);
Print("Senkou Span B: ", senkb);
}
bState.AssignArray(sState.state);
Ich habe auch einige Indikatoren und Parameter hinzugefügt, insgesamt 27 BarDescr.... Momentum, Bands & Ichimoku Kinko Hyo =)
int OnInit()
{
Symbol setzen und aktualisieren
if(! Symb.Name(_Symbol))
return INIT_FAILED;
Symb.Refresh();
//---
if(! RSI. Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice))
return INIT_FAILED;
//---
if(! CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice))
return INIT_FAILED;
//---
if(! ATR. Create(Symb.Name(), TimeFrame, ATRPeriod))
return INIT_FAILED;
//---
if(! MACD. Create(Symb.Name(), TimeFrame, FastPeriod, SlowPeriod, SignalPeriod, MACDPrice))
return INIT_FAILED;
//---
if (! Momentum.Create(Symb.Name(), TimeFrame, MomentumMaPeriod, MomentumApplied))
return INIT_FAILED;
Initialisieren Sie den Ichimoku Kinko Hyo Indikator
If (! Ichimoku.Create(Symb.Name(), TimeFrame, Ichimokutenkan_senPeriod, Ichimokukijun_senPeriod, Ichimokusenkou_span_bPeriod))
return INIT_FAILED;
//---
if (! Bands.Create(Symb.Name(), TimeFrame, BandsMaPeriod, BandsMaShift, BandsDeviation, BandsApplied))
return INIT_FAILED;
//---
if(! RSI. BufferResize(HistoryBars) || ! CCI.BufferResize(HistoryBars) ||
! ATR. BufferResize(HistoryBars) || ! MACD. BufferResize(HistoryBars))
{
PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
return INIT_FAILED;
}
//---
void OnTick()
{
//---
if(! IsNewBar())
zurück;
//---
int bars = CopyRates(Symb.Name(), TimeFrame, iTime(Symb.Name(), TimeFrame, 1), HistoryBars, Rates);
if(! ArraySetAsSeries(Kurse, true))
zurückgeben;
//---
RSI. Aktualisieren();
CCI.Refresh();
ATR. Refresh();
MACD. Aktualisieren();
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
Ichimoku-Werte für den aktuellen Balken aktualisieren
Ichimoku.Refresh();
--- Historische Daten
float atr = 0;
for (int b = 0; b < (int)HistoryBars; b++)
{
float open = (float)Raten[b].open;
float close = (float)Kurse[b].close;
float rsi = (float)RSI. Main(b);
float cci = (float)CCI.Main(b);
atr = (float)ATR. Main(b);
float macd = (float)MACD. Main(b);
float vorzeichen = (float)MACD. Signal(b);
float mome = (float)Momentum.Main(b);
float bandzup = (float)Bands.Upper(b);
float bandzb = (float)Bands.Base(b);
float bandzlo = (float)Bands.Lower(b);
float tenkan = (float)Ichimoku.TenkanSen(0); Den berechneten Wert verwenden
float kijun = (float)Ichimoku.KijunSen(1); Verwende den berechneten Wert
float senkasa = (float)Ichimoku.SenkouSpanA(2); Verwende den berechneten Wert
float senkb = (float)Ichimoku.SenkouSpanB(3); Verwende den berechneten Wert
Prüfung auf EMPTY_VALUE und Division durch Null
if (rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE ||
sign == EMPTY_VALUE || mome == EMPTY_VALUE || bandzup == EMPTY_VALUE || bandzb == EMPTY_VALUE || bandzb == EMPTY_VALUE ||
bandzlo == EMPTY_VALUE || tenkan == EMPTY_VALUE || kijun == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkasa == EMPTY_VALUE ||
senkb == EMPTY_VALUE || kijun == 0.0 || senkb == 0.0)
{
weiter;
}
Sicherstellen, dass die Größe von Puffern innerhalb der Schleife nicht geändert wird
int shift = b * BarDescr;
sState.state[shift] = (float)(Rates[b].close - open);
sState.state[shift + 1] = ((float)(Kurse[b].close - open) + (tenkan - kijun)) / 2.0f;
sState.state[shift + 2] = (float)(Kurse[b].high - open);
sState.state[shift + 3] = (float)(Kurse[b].low - open);
sState.state[shift + 4] = (float)(Kurse[b].high - close);
sState.state[shift + 5] = (float)(Kurse[b].low - close);
sState.state[shift + 6] = (tenkan - kijun);
sState.state[shift + 7] = (float)(Kurse[b].tick_volume / 1000.0f);
sState.state[shift + 8] = ((float)(Kurse[b].hoch) - (float)(Kurse[b].niedrig));
sState.state[shift + 9] = (bandzup - bandzlo);
sState.state[shift + 10] = rsi;
sState.state[shift + 11] = cci;
sState.state[shift + 12] = atr;
sState.state[shift + 13] = macd;
sState.state[shift + 14] = sign;
sState.state[shift + 15] = mome;
sState.state[shift + 16] = (float)(Rates[b].open - tenkan);
sState.state[shift + 17] = (float)(Kurse[b].open - kijun);
sState.state[shift + 18] = (float)(Kurse[b].open - bandzb);
sState.state[shift + 19] = (float)(Kurse[b].open - senkasa);
sState.state[shift + 20] = (float)(Kurse[b].open - senkb);
sState.state[shift + 21] = (float)(Kurse[b].close - tenkan);
sState.state[shift + 22] = (float)(Kurse[b].close - kijun);
sState.state[shift + 23] = (float)(Kurse[b].close - bandzb);
sState.state[shift + 24] = (float)(Kurse[b].close - senkasa);
sState.state[shift + 25] = (float)(Kurse[b].close - senkb);
sState.state[shift + 26] = senkasa - senkb;
//---
RSI.Refresh();
CCI.Refresh();
ATR.Refresh();
MACD.Refresh();
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
// Aktualisieren der Ichimoku-Werte für den aktuellen Balken
Ichimoku.Refresh();
//---
Print("Zustand 0: ", sState.state[shift]);
Print("Zustand 1: ", sState.state[shift + 1]);
Print("Zustand 2: ", sState.state[shift + 2]);
Print("Zustand 3: ", sState.state[shift + 3]);
Print("Zustand 4: ", sState.state[shift + 4]);
Print("Zustand 5: ", sState.state[shift + 5]);
Print("Zustand 6: ", sState.state[shift + 6]);
Print("Zustand 7: ", sState.state[shift + 7]);
Print("Zustand 8: ", sState.state[shift + 8]);
Print("Zustand 9: ", sState.state[shift + 9]);
Print("Zustand 10: ", sState.state[shift + 10]);
Print("Zustand 11: ", sState.state[shift + 11]);
Print("Zustand 12: ", sState.state[shift + 12]);
Print("Zustand 13: ", sState.state[shift + 13]);
Print("Zustand 14: ", sState.state[shift + 14]);
Print("Zustand 15: ", sState.state[shift + 15]);
Print("Zustand 16: ", sState.state[shift + 16]);
Print("Zustand 17: ", sState.state[shift + 17]);
Print("Zustand 18: ", sState.state[shift + 18]);
Print("Zustand 19: ", sState.state[shift + 19]);
Print("Zustand 20: ", sState.state[shift + 20]);
Print("Zustand 21: ", sState.state[shift + 21]);
Print("Zustand 22: ", sState.state[shift + 22]);
Print("Zustand 23: ", sState.state[shift + 23]);
Print("Zustand 24: ", sState.state[shift + 24]);
Print("Zustand 25: ", sState.state[shift + 25]);
Print("Zustand 26: ", sState.state[shift + 26]);
Print("Tenkan Sen: ", tenkan);
Print("Kijun Sen: ", kijun);
Print("Senkou Span A: ", senkasa);
Print("Senkou Span B: ", senkb);
}
bState.AssignArray(sState.state);
JimReaper - Wie viele Zyklen haben Sie Ihre Version untersucht, bevor Sie das Ergebnis in Ihrem Bild erhielten (Datenerfassung - Training). Und wie lange hat es gedauert?
Wie ist Ihr Computer konfiguriert (Prozessor, Grafikkarte, RAM)?
Vielen Dank!
dann Agent auf 5 und Optimierung auf 20 setzen
Insgesamt 100...
Ich sehe, dass im Code auf Agent verwiesen wird, aber ich sehe keine Optimierung. Wurde der Code von Ihnen ergänzt, um diesen neuen Parameter zu verwenden?
Danke
Paul
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Neuer Artikel Neuronale Netze leicht gemacht (Teil 66): Explorationsprobleme beim Offline-Lernen :
Modelle werden offline mit Daten aus einem vorbereiteten Trainingsdatensatz trainiert. Dies bietet zwar gewisse Vorteile, hat aber den Nachteil, dass die Informationen über die Umgebung stark auf die Größe des Trainingsdatensatzes komprimiert werden. Das wiederum schränkt die Möglichkeiten der Erkundung ein. In diesem Artikel wird eine Methode vorgestellt, die es ermöglicht, einen Trainingsdatensatz mit möglichst unterschiedlichen Daten zu füllen.
Die ExORL-Methode kann in 3 Hauptphasen unterteilt werden. Die erste Stufe ist die Sammlung von nicht gekennzeichneten Sondierungsdaten. In dieser Phase können verschiedene unüberwachte Lernalgorithmen eingesetzt werden. Die Autoren der Methode schränken die Bandbreite der anwendbaren Algorithmen nicht ein. Darüber hinaus verwenden wir im Prozess der Interaktion mit der Umgebung in jeder Episode eine Strategie π, die von der Geschichte der vorherigen Interaktionen abhängt. Jede Episode wird im Datensatz als Folge eines Zustands St, einer Aktion At und des darauf folgenden Zustands St+1 gespeichert. Die Sammlung von Trainingsdaten wird fortgesetzt, bis der Trainingsdatensatz vollständig gefüllt ist. Die Größe dieses Trainingsdatensatzes ist durch die technischen Spezifikationen oder die verfügbaren Ressourcen begrenzt.
Nach dem Sammeln eines Datensatzes von Zuständen und Aktionen besteht der nächste Schritt darin, die Daten anhand einer vorgegebenen Belohnungsfunktion zu vergleichen. In dieser Phase wird die Belohnung für jedes Tupel im Datensatz bewertet.
Die praktische Erfahrung zeigt die Möglichkeit der parallelen Nutzung in einem Wiedergabepuffer, der mit verschiedenen Methoden gesammelt wird. Ich habe sowohl die Trajektorien verwendet, die von der zuvor besprochenen EA Research.mq5 gesammelt wurden, als auch die EA ResearchExORL.mq5. Der erste zeigt die Vor- und Nachteile der erlernten Akteurspolitik auf. Die zweite ermöglicht es uns, die Umgebung so weit wie möglich zu erkunden und die noch nicht berücksichtigten Möglichkeiten zu bewerten.
Im Laufe des iterativen Modelltrainings ist es mir gelungen, seine Leistung zu verbessern.
Während die Anzahl der Handelsgeschäfte während des Testzeitraums generell auf ein Drittel zurückging (56 gegenüber 176), stiegen die Gewinne um fast das Dreifache. Der Betrag des maximal profitablen Handelsgeschäfts hat sich mehr als verdoppelt. Und das durchschnittliche, profitable Handelsgeschäft stieg um das Fünffache. Außerdem ist ein Anstieg des Saldos während des gesamten Testzeitraums zu beobachten. Infolgedessen hat sich der Gewinnfaktor des Modells von 1,3 auf 2,96 erhöht.
Autor: Dmitriy Gizlyk