Das Array Input , welches eine Kopie von X ist lässt sich ab dem Loop nicht mehr adressieren? Jemand nh idee warum und wie ich das umgehen kann?
Das sollte es nicht geben, das Array sollte auch von der Schleife aus adressierbar sein. Der Fehler liegt irgendwo anders. Bei Dir fehlt übrigens eine schließende Klammer am Ende.
Ach ja, könnte sein, dass das ArrayResize Dein Input auf Länge 0 setzt warum auch immer.
static datetime lastBar; input uint b_L1=-1, b_L2=-1, b_L3 = -1, b_L4 = -1, b_L5=-1; input bool testen = true; input int Layers = 4; //Layers inkl Inp- % Outp-Layer int NeuronenArray[]; //Neuronenarray NUR soviele Layer wie auch neuronen deklariert double weight_L1[],weight_L2[],weight_L3[],weight_L4[],weight_L5[]; //Layer L0 = InputLayer input int Neuronen_L1 = 6; input int Neuronen_L2 = 6; input int Neuronen_L3 = 6; input int Neuronen_L4 = 3; input int Neuronen_L5 = 0; double RSI[]; string my_symbol; // variable for storing the symbol ENUM_TIMEFRAMES my_timeframe; // variable for storing the time frame //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { //--- save the current chart symbol for further operation of the EA on this very symbol my_symbol=Symbol(); //--- save the current time frame of the chart for further operation of the EA on this very time frame my_timeframe=PERIOD_CURRENT; //--- save the minimum lot of the transaction to be performed // lot_size=SymbolInfoDouble(my_symbol,SYMBOL_VOLUME_MIN); ArraySetAsSeries(RSI,true); ArrayResize(NeuronenArray,Layers); for (int i=0;i<Layers;i++) { //--- preparation for placing weights into the array if (i+1 == 1){NeuronenArray[i] = Neuronen_L1; ArrayResize(weight_L1,NeuronenArray[0]);/*Print(weight_L1[0]);Print(weight_L1[1]);Print(weight_L1[2]);Print(weight_L1[3]);Print(weight_L1[4]);*/} if (i+1 == 2){NeuronenArray[i] = Neuronen_L2; ArrayResize(weight_L2,NeuronenArray[1]);} if (i+1 == 3){NeuronenArray[i] = Neuronen_L3; ArrayResize(weight_L3,NeuronenArray[2]);} if (i+1 == 4){NeuronenArray[i] = Neuronen_L4; ArrayResize(weight_L4,NeuronenArray[3]);} if (i+1 == 5){NeuronenArray[i] = Neuronen_L5; ArrayResize(weight_L5,NeuronenArray[4]);} if (i+1 == Layers) {NeuronenArray[i] = 3; // Letzter Layer MUSS 3 haben-> weil 1 = Buy, 0 = hold , -1 = sell break;} // weil ist ja der letzte } if (testen == true) { for (int i=0;i<Layers;i++) { int Neuronen = 0; if (i+1 == 1) {Neuronen = NeuronenArray[i]; ArrayFill(weight_L1,0,Neuronen,0.5);/*Print(weight_L1[0]);Print(weight_L1[1]);Print(weight_L1[2]);Print(weight_L1[3]);Print(weight_L1[4])*/;} if (i+1 == 2) {Neuronen = NeuronenArray[i]; ArrayFill(weight_L2,0,Neuronen,0.5);} if (i+1 == 3) {Neuronen = NeuronenArray[i]; ArrayFill(weight_L3,0,Neuronen,0.5);} if (i+1 == 4) {Neuronen = NeuronenArray[i]; ArrayFill(weight_L4,0,Neuronen,0.5);} if (i+1 == 5) {Neuronen = NeuronenArray[i]; ArrayFill(weight_L5,0,Neuronen,0.5);} } } //--- return 0, initialization complete lastBar = iTime(_Symbol,my_timeframe,0); return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) {} //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { double h[]; // outputarray of NN double X[]; // Vorerst: [0] = Closeprice(stationarized),[1] = Closepricebefore (stationarized), [2] = Closeprice(stationarized), [3] = DayOfWeek, [4] = Hour, [5] = RSI //ArraySetAsSeries(X,true); ArrayResize(X,6); int rsi_handle = iRSI(my_symbol,my_timeframe,10,PRICE_CLOSE); CopyBuffer(rsi_handle,0,1,0,RSI); // Neue Bar -> set X -> calculate NN -> h == buy/sell/hold datetime newBar = iTime(my_symbol,my_timeframe,0); if(lastBar < newBar) { lastBar = newBar; X[0]=iClose(my_symbol,my_timeframe,2) - iClose(my_symbol,my_timeframe,1); X[1]=iClose(my_symbol,my_timeframe,3) - iClose(my_symbol,my_timeframe,2); X[2]=iClose(my_symbol,my_timeframe,4) - iClose(my_symbol,my_timeframe,3); X[3]= DayOfWeek(); X[4]= Hour(); X[5]= rsi_handle; // ja ich weiß, ist nicht die richtige lösung aber mit buffer scheint es probleme zu geben die ich später lösen werde //Print (X[0],X[1],X[2],X[3],X[4],X[5]); for (int i=0;i<ArraySize(h);i++) {Print(h[i]);} simple_looped_nn_calc(Layers,X,h, weight_L1,weight_L2,weight_L3,weight_L4,weight_L5,b_L1); } //... ... ... } //+------------------------------------------------------------------+ //| Neuron calculation function | //+------------------------------------------------------------------+ double CalculateNeuron(double &x[],double &w[]) { //--- variable for storing the weighted sum of inputs double NET=0.0; //--- Using a loop we obtain the weighted sum of inputs based on the number of inputs for(int n=0;n<ArraySize(x);n++) { NET+=x[n]*w[n]; } //--- multiply the weighted sum of inputs by the additional coefficient NET*=0.4; //--- send the weighted sum of inputs to the activation function and return its value return(ActivateNeuron(NET)); } //+------------------------------------------------------------------+ //| Activation function | //+------------------------------------------------------------------+ double ActivateNeuron(double x) { //--- variable for storing the activation function results double Out; //--- sigmoid Out=1/(1+exp(-x)); //--- return the activation function value return(Out); } //+------------------------------------------------------------------+ void simple_looped_nn_calc(int n_layers,double& X[], double& h[],/*double &w[]*/double& w_L1[],double& w_L2[],double& w_L3[],double& w_L4[],double& w_L5[], double b)//b muss als array umgestaltet werden { double Input[]; //double h[]; <---- das hier muss ausserhalb deklariert werden for(int l=0;l<n_layers;l++) { if (l+1 == 1) {ArrayResize(Input,ArraySize(X)); ArrayCopy(Input,X); Print(ArraySize(X)); Print(X[1]);Print(Input[1]);} else if (l+1 >1) {ArrayResize(Input,ArraySize(h)); ArrayCopy(Input,h);} double w_l[]; int next_l_Size = 0; if (l==1){ArrayResize(w_l,ArraySize(w_L1)); ArrayCopy(w_l,w_L1); next_l_Size = ArraySize(w_L2);} else if(l==2){ArrayResize(w_l,ArraySize(w_L2)); ArrayCopy(w_l,w_L2); next_l_Size = ArraySize(w_L3);} else if(l==3){ArrayResize(w_l,ArraySize(w_L3)); ArrayCopy(w_l,w_L3); next_l_Size = ArraySize(w_L4);} else if(l==4){ArrayResize(w_l,ArraySize(w_L4)); ArrayCopy(w_l,w_L4); next_l_Size = ArraySize(w_L5);} else if(l==5){ArrayResize(w_l,ArraySize(w_L5)); ArrayCopy(w_l,w_L5); next_l_Size = 1;} else if (l>5){Alert("ERROR ... wrong layer size");} ArrayResize(h,ArraySize(w_l)); //for(int i=0;i<ArraySize(w_l);i++) // { Print("____bis hier hin läuft es top_____",Input[1]); for (int i=0; i< next_l_Size; i++) {Print("____ab dem loop ist das Input Array wieder leer____",Input[1]); double f_sum =0; for (int j=0; next_l_Size*i+j< ArraySize(w_l); j++) { f_sum += w_l[next_l_Size*i+j] * Input[j]; } f_sum += b_L1; h[i] = ActivateNeuron(f_sum); } } } int DayOfWeek() { MqlDateTime tm; TimeCurrent(tm); return(tm.day_of_week); } int Hour() { MqlDateTime tm; TimeCurrent(tm); return(tm.hour); }
ist wie gesagt nur der prototyp (nur halb fertig). Inputs und alles was notwendig ist, ist drin (habe bereits nahezu alles überflüssige gestrichen).
Aber wie erwähnt taucht das problem nur bis zum (mit Prints) markierten loop auf. danach ist es futsch.
Das Resize() soll die größe des original Input Arrays (X oder h, wobei es sich um den input einer vorherigen Neuronenschicht handelt) auf Input[] übertragen und anschließend , damit dieses eine exakte kopie darstellt mit dessen werten befüllen.
ist wie gesagt nur der prototyp (nur halb fertig). Inputs und alles was notwendig ist, ist drin (habe bereits nahezu alles überflüssige gestrichen).
Aber wie erwähnt taucht das problem nur bis zum (mit Prints) markierten loop auf. danach ist es futsch.
Das Resize() soll die größe des original Input Arrays (X oder h, wobei es sich um den input einer vorherigen Neuronenschicht handelt) auf Input[] übertragen und anschließend , damit dieses eine exakte kopie darstellt mit dessen werten befüllen.
Dein Input wird im 2. loop der Schleife wo der Blaue Punkt ist überschrieben mit dem Array h was LEER ist.
Gewollt oder nicht musst du selber entscheiden.
Du siehst auch wie man einen Breakpoint mit Bedingung setzen kann um ein ganz bestimmten Zeitpunkt im Programm zu finden
if (ArraySize(Input) < 6) { DebugBreak(); }
Unten rechst siehst du die Variablem zu dem "Fehlerzeitpunk" und kannst selbst nachvollziehen warum danach das Input Array leer ist.
ArrayCopy(Input,h)
h ist leer und macht Input somit auch leer
Bayne,
Ich durchblicke den Code nicht so auf die Schnelle, daher nur Dinge, die mir auf den ersten Blick auffallen:
1. Bist Du sicher, dass das mit den Gewichten so funktioniert und dass diese Arrays nicht mindestens zweidimensional sein müssten? Aus den Array-Koordinaten muss doch hervorgehen, welches Neuron mit welchem verbunden ist ("Stichwort fully connected NN"). Oder halt dreimeinsional, wenn Du es flexibler halten möchtest und das Bezugslayer enthalten sein soll (also statt W1[][], W2[][]... usw. einfach W[layer][][]. Beispiel: W[3][9][7] könnte dann das Gewicht sein, das Neuron9 aus Layer 3 mit dem Neuron7 aus dem Folgelayer(3+1=4) verbindet.
2. Warum schreibst Du die Bedingung l+1=1? Diese Bedingung ist nur <true> wenn l==0, also könntest Du auch gleich schreiben if (l==0){}.
Genauso: if (l+1>1){} ist das Gleiche wie if (l>1){}. So wie Du es schreibst ist es nicht intuitiv.
3. Die Funktionen am Ende gehen viel knapper mit z.B.
MqlDateTime tm;
und dann nur einmal in OnTick
TimeToStruct(TimeCurrent(),tm);
dann wäre z.B. "hour_of_day" schlicht tm.hour; es gibt keinen Grund, die Zeit pro Tick mehrmals (=über Deine separate Funktionen) auszulesen. Das sind die kleinen Details, von denen sich am Ende ein paar hundert summieren und ein Programm langsam machen.
4. Ich würde später mit unterschiedlichen Aktivierungsfunktionen experimentieren (tanh, ReLu, ELu...). Außerdem einen NaN-Error-Schutz in die Funktion einbauen mittels if (!MathIsValidNumber(Out)){....
Danke Christian, aber das hätte man doch ganz leicht mit dem Debugger selbst herausfinden können!
Wie heißt es so schön: Hilf Dir selbst, dann hilft Dir Gott!
if (l==1){ArrayResize(w_l,ArraySize(w_L1)); ArrayCopy(w_l,w_L1); next_l_Size = ArraySize(w_L2);} else if(l==2){ArrayResize(w_l,ArraySize(w_L2)); ArrayCopy(w_l,w_L2); next_l_Size = ArraySize(w_L3);} else if(l==3){ArrayResize(w_l,ArraySize(w_L3)); ArrayCopy(w_l,w_L3); next_l_Size = ArraySize(w_L4);} else if(l==4){ArrayResize(w_l,ArraySize(w_L4)); ArrayCopy(w_l,w_L4); next_l_Size = ArraySize(w_L5);} else if(l==5){ArrayResize(w_l,ArraySize(w_L5)); ArrayCopy(w_l,w_L5); next_l_Size = 1;} else if (l>5){Alert("ERROR ... wrong layer size");}
hieran lag es schlussendlich, falls es einer auch gefunden habe: es hätte mit if (l == 0){ArrayResize(...)... anfangen müssen.
Danke euch dennoch
@Carl Schreiber: Ich war heute nacht nach 2 stunden debuggen so blind und habe dauerhaft an der falschen stelle gesucht.
Ich debugge selbstverständlich erstmal selber und frage idr nur im forum, wenn ich selbst nicht weiter weiß, also keine Sorge, dennoch danke euch für euer geschultes Adlerauge :)
PS: keine sorge die 2d Arrays kommen noch, ich musste erstmal nur einen einstieg finden was in die Arrays reingehört.
@Chris70 kannst du mir sagen wie ich ein 2d array Resizen kann? Die 2. Dimension meine ich. Lese überall das geht nicht. ( Die Anzahlen der Neuronen in diesem NN sind je nach layer unterschiedlich groß und variieren, denn ich will die layeranzahl als Input in den Strategy Tester packen (momentan sind es halt 5 manuell geschriebene), Multi arrays wären also platzsparender)
@Chris70 kannst du mir sagen wie ich ein 2d array Resizen kann? Die 2. Dimension meine ich. Lese überall das geht nicht. ( Die Anzahlen der Neuronen in diesem NN sind je nach layer unterschiedlich groß und variieren)
Absolut korrekt. Du wirst daher also praktisch nicht darum herumkommen, überzudimensionieren auf ein Niveau, das realistischerweise nicht überschritten wird. Irgendwo musss man da einen Kompromiss machen. Wenn für die einzelnen Dimensionen mit unterschiedlichen Größen gerechnet wird, macht es natürlich Sinn, nur die kleineren Größen statisch festzulegen und die potentiell größte Dimension an die dynamische erste Position zu legen. Wenn Du dann mal "Glück" hast und dieese Dimenson doch nciht so groß ist, hat man dann nicht so viele unnötige / überzählige Elemente. Am Beispiel der Gewichte könnte man also z.B. postulieren, dass die Anzahl der Neuronen pro Layer potentiell deutlich größer sein kann als die Zahl der Layer, insofern ist Dein Einwand gut: die Reihenfolge Weight[Senderneuron][Empfängerneuron][Senderlayer] kann so Vorteile haben (gegenüber Senderlayer auf der ersten/dynamischen Position). Da definierst Du z.B. double W[][200][10];. Vergiss übrigens die Bias-Neuronen nicht - oder handhabe einfach das nullte Neuron pro Layer als Bias; dann aber bei der Gewichtsvernetzung daran denken, dass die Bias-Neuronen nur Ausgangs-Gewichte haben, aber keine Eingangsgewichte.
edit: noch eine Sache: warum kopierst Du überhaupt das X-Array auf das erste Layer? Wo ist der Vorteil anstelle der Konvention "der cell-state von Layer 0 IST mein X-Vektor"? Der einzige Unterschied zwischen Eingang und Folgelayers ist, dass die Backpropagation am Eingangslayer beendet ist und dass das Einganglayer halt nur Ausgangsgewichte hat. Das kann man aber alles über for-loops regeln.
Nächste Schriite für Dich sind dann wahrscheinlich die Input-Normalisierung und die Funktionen für random-Initialisierung, Laden und Speichern der Gewichts-Matrix, oder? Und dann halt die Backpropagation... Viel Spaß!
Danke Christian, aber das hätte man doch ganz leicht mit dem Debugger selbst herausfinden können!
Ab und zu gebe ich noch gerne mal eine Hilfestellung,ohne mich in den Code einzuarbeiten.
Das können gerne andere machen, das Rad erfinde ich nicht neu :-)
Absolut korrekt. Du wirst daher also praktisch nicht darum herumkommen, überzudimensionieren auf ein Niveau, das realistischerweise nicht überschritten wird. Irgendwo musss man da einen Kompromiss machen. Wenn für die einzelnen Dimensionen mit unterschiedlichen Größen gerechnet wird, macht es natürlich Sinn, nur die kleineren Größen statisch festzulegen und die potentiell größte Dimension an die dynamische erste Position zu legen. Wenn Du dann mal "Glück" hast und dieese Dimenson doch nciht so groß ist, hat man dann nicht so viele unnötige / überzählige Elemente. Am Beispiel der Gewichte könnte man also z.B. postulieren, dass die Anzahl der Neuronen pro Layer potentiell deutlich größer sein kann als die Zahl der Layer, insofern ist Dein Einwand gut: die Reihenfolge Weight[Senderneuron][Empfängerneuron][Senderlayer] kann so Vorteile haben (gegenüber Senderlayer auf der ersten/dynamischen Position). Da definierst Du z.B. double W[][200][10];. Vergiss übrigens die Bias-Neuronen nicht - oder handhabe einfach das nullte Neuron pro Layer als Bias; dann aber bei der Gewichtsvernetzung daran denken, dass die Bias-Neuronen nur Ausgangs-Gewichte haben, aber keine Eingangsgewichte.
edit: noch eine Sache: warum kopierst Du überhaupt das X-Array auf das erste Layer? Wo ist der Vorteil anstelle der Konvention "der cell-state von Layer 0 IST mein X-Vektor"? Der einzige Unterschied zwischen Eingang und Folgelayers ist, dass die Backpropagation am Eingangslayer beendet ist und dass das Einganglayer halt nur Ausgangsgewichte hat. Das kann man aber alles über for-loops regeln.
Nächste Schriite für Dich sind dann wahrscheinlich die Input-Normalisierung und die Funktionen für random-Initialisierung, Laden und Speichern der Gewichts-Matrix, oder? Und dann halt die Backpropagation... Viel Spaß!

- 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.
Das Array Input , welches eine Kopie von X ist lässt sich ab dem Loop nicht mehr adressieren? Jemand nh idee warum und wie ich das umgehen kann?