Diskussion zum Artikel "Wie man ONNX-Modelle in MQL5 verwendet" - Seite 6

 
Fehler bei der Verwendung von Modell-Klassifikatoren.

Regression funktioniert mit allem, die Ausgabe ist eine Zahl.

Aber wenn Sie einen beliebigen Chat bitten, einen MLP-Klassifikator zu schreiben, kann der Expert Advisor die Ausgabedaten dieses Modells nicht erkennen: "Kaufen", "Verkaufen", "Halten". Entweder "1", "2", "3", oder "0", "1", "2".

Der Fehler fliegt raus

2025.02.12 08:13:46.866 Core 01 2021.01.01 00:00:00 Fehler beim Setzen des Ausgabeformulars: 5808
2025.02.12 08:13:46.866 Core 01 2021.01.01 00:00:00 ONNX: ungültiges Handle an OnnxRelease-Funktion übergeben, Inspektionscode 'X È$Zë3E' (291:7)

Keiner der Chats, nicht einmal Dipsic, versteht oder weiß, wie das Problem zu beheben ist, und generiert mögliche Codes, die ebenfalls zu diesem Fehler führen.

Alle Chats sagen dasselbe: Da es sich um einen MLP-Klassifikator handelt, hat er nur 3 Ausgänge, je nach Ihren Labels (ich füttere ihn mit einer csv-Datei, in der die letzte Spalte eines der drei Labels einer einfachen Klassifizierung ist: buy, sell, hold. Ich habe String- und numerische Werte in dieser Spalte ausprobiert).

Dann dieser Block

.
const long output_shape[] = {1,1};
   if(!OnnxSetOutputShape(ExtHandle,0,output_shape))
     {
      Print("OnnxSetOutputShape error ",GetLastError());
      return(INIT_FAILED);
     }
Er ändert die Initialisierung des Arrays

.
const long output_shape[] = {1,3};
   if(!OnnxSetOutputShape(ExtHandle,0,output_shape))
     {
      Print("OnnxSetOutputShape error ",GetLastError());
      return(INIT_FAILED);
     }


Und es erscheint ein Fehler.

Ich versuche, zu drucken.

Print(OnnxGetOutputCount(ExtHandle));

Ich erhalte 2.

Ich verstehe nichts.



Wenn jemand versteht, was der Fehler ist, lassen Sie es mich bitte wissen.

Python-Code für Klassifikator - jeder, sie alle erzeugen den gleichen Fehler.

Zum Beispiel, eine der Implementierungen:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.neural_network import MLPClassifier
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType

# Daten laden
file_path = '....csv'
data = pd.read_csv(file_path)

# Aufteilung in Attribute (X) und Bezeichnungen (y)
X = data.iloc[:, :160].values  # Die ersten 160 Spalten sind Eingabedaten.
y = data.iloc[:, 160].values   # Die letzte Spalte ist die Zielbezeichnung.

# Kodierung von String-Bezeichnungen in numerische Bezeichnungen
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)

# Normalisierung der Daten
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# Aufteilung in Trainings- und Testproben
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_encoded, test_size=0.2, random_state=42)

# Erstellen eines MLP-Klassifikators
mlp = MLPClassifier(hidden_layer_sizes=(128, 64), activation='relu', solver='adam', max_iter=500, random_state=42)
mlp.fit(X_train, y_train)

# Schätzung der Genauigkeit des Modells
accuracy = mlp.score(X_test, y_test)
print(f"Accuracy: {accuracy * 100:.2 f}%")

# Speichern des Modells im ONNX-Format
initial_type = [('float_input', FloatTensorType([None, 160]))]  # 160 Eingabemerkmale
onnx_model = convert_sklearn(mlp, initial_types=initial_type)

# Speichern des ONNX-Modells
onnx_file_path = 'model.onnx'
with open(onnx_file_path, "wb") as f:
    f.write(onnx_model.SerializeToString())

print(f"Model saved as {onnx_file_path}")


Das heißt, das Modell selbst, das in Python läuft. Es errechnet etwas

runfile('....py', wdir='...')
Accuracy: 54.16%
Model saved as model.onnx

Aber der Berater kann das nicht akzeptieren.

 
In einer gesunden Gemeinschaft wird die Codegenerierung nicht diskutiert oder auch nur irgendwie in Betracht gezogen. Es ist nicht schlecht, über den ONNX-Bug Bescheid zu wissen, wegen dem Multiclass nicht unterstützt wird.
 
Es muss nicht diskutiert werden
Das ist nicht die Frage.
 
Ivan Butko #:
Es muss nicht diskutiert werden
Das ist nicht die Frage.

Versuchen Sie {2,3} oder {3}.

Bitten Sie das Python-Skript, die richtige Dimension des Outputs auszugeben.

aber höchstwahrscheinlich nur {1}, gibt es eine Struktur zurück, bei der die Felder bereits den Ausgaben entsprechen.


Zum Beispiel habe ich für einen binären Klassifikator ist

const long output_shape[] = {1};
   if(!OnnxSetOutputShape(ExtHandle, 0, output_shape))
     {
      Print("OnnxSetOutputShape 1 error ", GetLastError());
      return(INIT_FAILED);
     }
 

Dann erstellen Sie einfach eine Struktur im Code

static vector out(1);

   struct output
     {
      long           label[];
      float          tensor[];
     };

   output out2[];
   
   OnnxRun(ExtHandle, ONNX_DEBUG_LOGS, f, out, out2);

   double sig = out2[0].tensor[1];

Das Beschriftungsfeld enthält die Klassenwerte und der Tensor die Wahrscheinlichkeiten

 
Falsch: label enthält Klassenwerte und tensor enthält Wahrscheinlichkeiten. Nun, die Ausgabedimension ist eigentlich 2,2, aber da die Struktur zurückgegeben wird, sollte sie auf 1 gesetzt werden
 
Maxim Dmitrievsky #:
Falsch: label enthält Klassenwerte und tensor enthält Wahrscheinlichkeiten. Die Ausgabedimension ist also im Wesentlichen 2,2, aber da die Struktur zurückgegeben wird, sollten Sie 1 einsetzen.
Vielen Dank

UPD

Zum Wesen der Architekturen: Die Regression in dem Artikel befasst sich mit Vangulation. Und Klassifizierung scheint mehr Sinn zu machen. Und siehe da - es stellt sich heraus, dass es in der nativen Funktionalität ein Problem damit gibt.

Subjektiv: Wenn das Ziel als nächster Preis (oder eine andere quantitative Angabe) markiert ist, beginnt der NS von einer Seite zur anderen zu schwanken.

Und wenn das Ziel als Buy-Sell-Hold markiert ist, passt sich der NS zumindest an die Anzahl der erfolgreichen Einträge an, ohne auf die Größe zu achten. Und auf die Entfernung wird diese "Ignoranz" durch eine gewisse Nivellierung kompensiert, sozusagen als Rauschtherapie. Imho habe ich die Klassifizierung natürlich wenig in einer anderen Implementierung ausprobiert. Deshalb wollte ich hier
 
Ivan Butko #:
Dankeschön
Sie können Ihr Netz auch über Netron visualisieren und es wird die Dimension und den Ausgangstyp anzeigen
 
Ivan Butko #:
Vielen Dank

UPD

Was die Architekturen betrifft: Die Regression in dem Artikel befasst sich mit Vangulation. Und Klassifizierung scheint mehr Sinn zu machen. Und hier sind wir - es stellt sich heraus, ein Problem mit ihm in der nativen Funktionalität sein.

Subjektiv: Wenn das Ziel als nächster Preis (oder eine andere quantitative Angabe) markiert ist, beginnt der NS von einer Seite zur anderen zu schwanken.

Und wenn das Ziel als Kaufen-Verkaufen-Halten markiert ist, passt sich der NS zumindest an die Anzahl der erfolgreichen Eingänge an, ohne auf die Größe zu achten. Und auf die Entfernung wird diese "Ignoranz" durch eine gewisse Nivellierung kompensiert, sozusagen als Rauschtherapie. Imho habe ich die Klassifizierung natürlich wenig in einer anderen Implementierung ausprobiert. Deshalb wollte ich hier

Dafür ist das Preprocessing, das Sie nicht respektieren, da :) um zuerst die Spreu vom Weizen zu trennen, und dann zu trainieren, die getrennten Körner vorherzusagen.

Wenn die Vorverarbeitung gut ist, ist die Ausgabe auch nicht ganz so schlecht

 

Gibt es eine Möglichkeit, dieses Skript für neuere Python-Versionen (3.10-3.12) zu reparieren?

Ich habe eine Menge Probleme beim Versuch, es mit 3.9 zum Laufen zu bringen.

tx