Scikit-learn kütüphanesinin sınıflandırma modelleri ve bunların ONNX'e aktarılması
Teknolojinin gelişmesi, veri işleme algoritmaları oluşturmaya yönelik temelde yeni bir yaklaşımın ortaya çıkmasına neden olmuştur. Önceden, her bir özel görevi çözmek için, ilgili algoritmaların açık bir şekilde biçimlendirilmesi ve geliştirilmesi gerekiyordu.
Makine öğreniminde bilgisayar, verileri işlemenin en iyi yollarını kendi kendine bulmayı öğrenir. Makine öğrenimi modelleri, sınıflandırma görevlerini (sabit bir sınıf kümesinin olduğu ve amacın her bir sınıfa ait belirli bir özellik kümesinin olasılıklarını bulmak olduğu) ve regresyon görevlerini (amacın belirli bir özellik kümesine dayalı olarak hedef değişkenin sayısal değerini hesaplamak olduğu) başarıyla çözebilir. Bu temel bileşenlere dayanarak daha karmaşık veri işleme modelleri oluşturulabilir.
Scikit-learn kütüphanesi hem sınıflandırma hem de regresyon için çok sayıda araç sağlar. Belirli yöntemlerin ve modellerin seçimi verilerin karakteristiğine bağlıdır, çünkü farklı yöntemler göreve bağlı olarak değişen etkinliğe sahip olabilir ve farklı sonuçlar sağlayabilir.
“ONNX Runtime is now open source” başlıklı basın bülteninde, ONNX Runtime'ın ONNX-ML profilini de desteklediği belirtilmektedir:
ONNX-ML profili, ONNX'in makine öğrenimi (ML) modelleri için özel olarak tasarlanmış bir parçasıdır. Sınıflandırma, regresyon, kümeleme vb. gibi çeşitli ML model türlerini, ONNX'i destekleyen çeşitli platformlarda ve ortamlarda kullanılabilecek uygun bir biçimde tanımlamak ve temsil etmek için tasarlanmıştır. ONNX-ML profili, makine öğrenimi modellerinin iletimini, dağıtımını ve yürütülmesini basitleştirerek onları daha erişilebilir ve taşınabilir hale getirir.
Bu makalede, Fisher'ın iris sınıflandırma görevini çözmek için Scikit-learn paketindeki tüm sınıflandırma modellerinin uygulanmasını inceleyeceğiz. Ayrıca bu modelleri ONNX formatına dönüştürmeye ve elde edilen modelleri MQL5 programlarında kullanmaya çalışacağız.
Ek olarak, orijinal modellerin doğruluğunu tam iris veri setindeki ONNX versiyonlarıyla karşılaştıracağız.
İçindekiler
- 1. Fisher'ın iris veri kümesi
- 2. Sınıflandırma için modeller
Scikit-learn sınıflandırıcılarının listesi
Modellerde farklı çıktı temsilleri iris.mqh - 2.1. SVC Classifier
2.1.1. SVC Classifier modelini oluşturmak için kod
2.1.2. SVC Classifier modeliyle çalışmak için MQL5 kodu
2.1.3. SVC Classifier modelinin ONNX gösterimi - 2.2. LinearSVC Classifier
2.2.1. LinearSVC Classifier modelini oluşturmak için kod
2.2.2. LinearSVC Classifier modeliyle çalışmak için MQL5 kodu
2.2.3. LinearSVC Classifier modelinin ONNX gösterimi - 2.3. NuSVC Classifier
2.3.1. NuSVC Classifier modelini oluşturmak için kod
2.3.2. NuSVC Classifier modeliyle çalışmak için MQL5 kodu
2.3.3. NuSVC Classifier modelinin ONNX gösterimi - 2.4. Radius Neighbors Classifier
2.4.1. Radius Neighbors Classifier modelini oluşturmak için kod
2.4.2. Radius Neighbors Classifier modeliyle çalışmak için MQL5 kodu
2.4.3. Radius Neighbors Classifier modelinin ONNX gösterimi - 2.5. Ridge Classifier
2.5.1. Ridge Classifier modelini oluşturmak için kod
2.5.2. Ridge Classifier modeliyle çalışmak için MQL5 kodu
2.5.3. Ridge Classifier modelinin ONNX gösterimi - 2.6. Ridge ClassifierCV
2.6.1. Ridge ClassifierCV modelini oluşturmak için kod
2.6.2. Ridge ClassifierCV modeliyle çalışmak için MQL5 kodu
2.6.3. Ridge ClassifierCV modelinin ONNX gösterimi - 2.7. Random Forest Classifier
2.7.1. Random Forest Classifier modelini oluşturmak için kod
2.7.2. Random Forest Classifier modeliyle çalışmak için MQL5 kodu
2.7.3. Random Forest Classifier modelinin ONNX gösterimi - 2.8. Gradient Boosting Classifier
2.8.1. Gradient Boosting Classifier modelini oluşturmak için kod
2.8.2. Gradient Boosting Classifier modeliyle çalışmak için MQL5 kodu
2.8.3. Gradient Boosting Classifier modelinin ONNX gösterimi - 2.9. Adaptive Boosting Classifier
2.9.1. Adaptive Boosting Classifier modelini oluşturmak için kod
2.9.2. Adaptive Boosting Classifier modeliyle çalışmak için MQL5 kodu
2.9.3. Adaptive Boosting Classifier modelinin ONNX gösterimi - 2.10. Bootstrap Aggregating Classifier
2.10.1. Bootstrap Aggregating Classifier modelini oluşturmak için kod
2.10.2. Bootstrap Aggregating Classifier modeliyle çalışmak için MQL5 kodu
2.10.3. Bootstrap Aggregating Classifier modelinin ONNX gösterimi - 2.11. K-Nearest Neighbors (K-NN) Classifier
2.11.1. K-Nearest Neighbors (K-NN) Classifier modelini oluşturmak için kod
2.11.2. K-Nearest Neighbors (K-NN) Classifier modeliyle çalışmak için MQL5 kodu
2.11.3. K-Nearest Neighbors (K-NN) Classifier modelinin ONNX gösterimi - 2.12. Decision Tree Classifier
2.12.1. Decision Tree Classifier modelini oluşturmak için kod
2.12.2. Decision Tree Classifier modeliyle çalışmak için MQL5 kodu
2.12.3. Decision Tree Classifier modelinin ONNX gösterimi - 2.13. Logistic Regression Classifier
2.13.1. Logistic Regression Classifier modelini oluşturmak için kod
2.13.2. Logistic Regression Classifier modeliyle çalışmak için MQL5 kodu
2.13.3. Logistic Regression Classifier modelinin ONNX gösterimi - 2.14. LogisticRegressionCV Classifier
2.14.1. LogisticRegressionCV Classifier modelini oluşturmak için kod
2.14.2. LogisticRegressionCV Classifier modeliyle çalışmak için MQL5 kodu
2.14.3. LogisticRegressionCV Classifier modelinin ONNX gösterimi - 2.15. Passive-Aggressive (PA) Classifier
2.15.1. Passive-Aggressive (PA) Classifier modelini oluşturmak için kod
2.15.2. Passive-Aggressive (PA) Classifier modeliyle çalışmak için MQL5 kodu
2.15.3. Passive-Aggressive (PA) Classifier modelinin ONNX gösterimi - 2.16. Perceptron Classifier
2.16.1. Perceptron Classifier modelini oluşturmak için kod
2.16.2. Perceptron Classifier modeliyle çalışmak için MQL5 kodu
2.16.3. Perceptron Classifier modelinin ONNX gösterimi - 2.17. Stochastic Gradient Descent Classifier
2.17.1. Stochastic Gradient Descent Classifier modelini oluşturmak için kod
2.17.2. Stochastic Gradient Descent Classifier modeliyle çalışmak için MQL5 kodu
2.17.3. Stochastic Gradient Descent Classifier modelinin ONNX gösterimi - 2.18. Gaussian Naive Bayes (GNB) Classifier
2.18.1. Gaussian Naive Bayes (GNB) Classifier modelini oluşturmak için kod
2.18.2. Gaussian Naive Bayes (GNB) Classifier modeliyle çalışmak için MQL5 kodu
2.18.3. Gaussian Naive Bayes (GNB) Classifier modelinin ONNX gösterimi - 2.19. Multinomial Naive Bayes (MNB) Classifier
2.19.1. Multinomial Naive Bayes (MNB) Classifier modelini oluşturmak için kod
2.19.2. Multinomial Naive Bayes (MNB) Classifier modeliyle çalışmak için MQL5 kodu
2.19.3. Multinomial Naive Bayes (MNB) Classifier modelinin ONNX gösterimi - 2.20. Complement Naive Bayes (CNB) Classifier
2.20.1. Complement Naive Bayes (CNB) Classifier modelini oluşturmak için kod
2.20.2. Complement Naive Bayes (CNB) Classifier modeliyle çalışmak için MQL5 kodu
2.20.3. Complement Naive Bayes (CNB) Classifier modelinin ONNX gösterimi - 2.21. Bernoulli Naive Bayes (BNB) Classifier
2.21.1. Bernoulli Naive Bayes (BNB) Classifier modelini oluşturmak için kod
2.21.2. Bernoulli Naive Bayes (BNB) Classifier modeliyle çalışmak için MQL5 kodu
2.21.3. Bernoulli Naive Bayes (BNB) Classifier modelinin ONNX gösterimi - 2.22. Multilayer Perceptron Classifier
2.22.1. Multilayer Perceptron Classifier modelini oluşturmak için kod
2.22.2. Multilayer Perceptron Classifier modeliyle çalışmak için MQL5 kodu
2.22.3. Multilayer Perceptron Classifier modelinin ONNX gösterimi - 2.23. Linear Discriminant Analysis (LDA) Classifier
2.23.1. Linear Discriminant Analysis (LDA) Classifier modelini oluşturmak için kod
2.23.2. Linear Discriminant Analysis (LDA) Classifier modeliyle çalışmak için MQL5 kodu
2.23.3. Linear Discriminant Analysis (LDA) Classifier modelinin ONNX gösterimi - 2.24. Hist Gradient Boosting
2.24.1. Histogram-Based Gradient Boosting Classifier modelini oluşturmak için kod
2.24.2. Histogram-Based Gradient Boosting Classifier modeliyle çalışmak için MQL5 kodu
2.24.3. Histogram-Based Gradient Boosting Classifier modelinin ONNX gösterimi - 2.25. CategoricalNB Classifier
2.25.1. CategoricalNB Classifier modelini oluşturmak için kod
2.25.2. CategoricalNB Classifier modeliyle çalışmak için MQL5 kodu
2.25.3. CategoricalNB Classifier modelinin ONNX gösterimi - 2.26. ExtraTreeClassifier
2.26.1. ExtraTreeClassifier modelini oluşturmak için kod
2.26.2. ExtraTreeClassifier modeliyle çalışmak için MQL5 kodu
2.26.3. ExtraTreeClassifier modelinin ONNX gösterimi - 2.27. ExtraTreesClassifier
2.27.1. ExtraTreesClassifier modelini oluşturmak için kod
2.27.2. ExtraTreesClassifier modeliyle çalışmak için MQL5 kodu
2.27.3. ExtraTreesClassifier modelinin ONNX gösterimi - 2.28. Tüm modellerin doğruluğunun karşılaştırılması
2.28.1. Tüm modelleri hesaplamak ve bir doğruluk karşılaştırma grafiği oluşturmak için kod
2.28.2. Tüm ONNX modellerini çalıştırmak için MQL5 kodu - 2.29. ONNX'e dönüştürülemeyen Scikit-learn sınıflandırma modelleri
- 2.29.1. DummyClassifier
2.29.1.1. DummyClassifier modelini oluşturmak için kod - 2.29.2. GaussianProcessClassifier
2.29.2.1. GaussianProcessClassifier modelini oluşturmak için kod - 2.29.3. LabelPropagation Classifier
2.29.3.1. LabelPropagation Classifier modelini oluşturmak için kod - 2.29.4. LabelSpreading Classifier
2.29.4.1. LabelSpreading Classifier modelini oluşturmak için kod - 2.29.5. NearestCentroid Classifier
2.29.5.1. NearestCentroid Classifier modelini oluşturmak için kod - 2.29.6. Quadratic Discriminant Analysis Classifier
2.29.6.1. Quadratic Discriminant Analysis Classifier modelini oluşturmak için kod - Sonuç
1. Fisher'ın iris veri kümesi
İris veri kümesi, makine öğrenimi alanında en iyi bilinen ve en yaygın kullanılan veri kümelerinden biridir. İlk olarak 1936 yılında istatistikçi ve biyolog R.A. Fisher tarafından tanıtılmış ve o zamandan beri sınıflandırma görevleri için klasik bir veri kümesi haline gelmiştir.
İris veri kümesi, üç iris çiçeği türünün (Iris setosa, Iris virginica ve Iris versicolor) çanak ve taç yapraklarının ölçümlerinden oluşur.
Şekil 1. Iris setosa
Şekil 2. Iris virginica
Şekil 3. Iris versicolor
İris veri kümesi, her üç türden 50'şer örnek olmak üzere 150 iris çiçeği örneğinden oluşmaktadır. Her örnek dört sayısal özelliğe sahiptir (santimetre cinsinden ölçülür):
- Çanak yaprak uzunluğu (sepal length)
- Çanak yaprak genişliği (sepal width)
- Taç yaprak uzunluğu (petal length)
- Taç yaprak genişliği (petal width)
Her örnek ayrıca iris çiçeği türünü (Iris setosa, Iris virginica veya Iris versicolor) belirten ilgili bir sınıfa sahiptir. Bu sınıflandırma özelliği, iris veri kümesini sınıflandırma ve kümeleme gibi makine öğrenimi görevleri için ideal bir veri kümesi haline getirmektedir.
MetaEditor Python komut dosyalarıyla çalışmaya olanak tanır. Bir Python komut dosyası oluşturmak için MetaEditor'da "Dosya" menüsünden "Yeni"ye tıklayın ve böylece oluşturulacak nesneyi seçmek için bir iletişim kutusu görünecektir (bkz. Şekil 4).
Şekil 4. MQL5 Sihirbazında Python komut dosyası oluşturma - Adım 1
Ardından, komut dosyası için bir ad girin, örneğin "IRIS.py" (bkz. Şekil 5).
Şekil 5. MQL5 Sihirbazında Python komut dosyası oluşturma - Adım 2 - Komut dosyası adı
Devamında, hangi kütüphanelerin kullanılacağını belirtebilirsiniz. Bizim durumumuzda, bu alanları boş bırakacağız (bkz. Şekil 6).
Şekil 6. MQL5 Sihirbazında Python komut dosyası oluşturma - Adım 3
İris veri setini analiz etmeye başlamanın bir yolu da verileri görselleştirmektir. Grafiksel bir gösterim, verilerin yapısını ve özellikler arasındaki ilişkileri daha iyi anlamamızı sağlar.
Örneğin, farklı iris çiçeği türlerinin özellik uzayında nasıl dağıldığını görmek için bir dağılım grafiği oluşturabilirsiniz.
Python komut dosyası kodu:
# The script shows the scatter plot of the Iris dataset features # Copyright 2023, MetaQuotes Ltd. # https://mql5.com import matplotlib.pyplot as plt from sklearn import datasets # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # extract sepal length and sepal width (the first two features) sepal_length = X[:, 0] sepal_width = X[:, 1] # create a scatter plot plt.figure(figsize=(8, 6)) plt.scatter(sepal_length, sepal_width, c=y, cmap=plt.cm.Set1, edgecolor='k') plt.xlabel('Sepal Length (cm)') plt.ylabel('Sepal Width (cm)') plt.title('Scatter Plot for Sepal Length and Sepal Width') plt.colorbar(label='Iris Species', ticks=[0, 1, 2]) plt.show() # save the scatter plot to a file (optional) # plt.savefig('scatter_plot_sepal_length_width.png') # Extract petal length and petal width (the third and fourth features) petal_length = X[:, 2] petal_width = X[:, 3] # create a scatter plot plt.figure(figsize=(8, 6)) plt.scatter(petal_length, petal_width, c=y, cmap=plt.cm.Set1, edgecolor='k') plt.xlabel('Petal Length (cm)') plt.ylabel('Petal Width (cm)') plt.title('Scatter Plot for Petal Length and Petal Width') plt.colorbar(label='Iris Species', ticks=[0, 1, 2]) plt.show() # save the scatter plot to a file (optional) # plt.savefig('scatter_plot_petal_length_width.png')
Bu kodu çalıştırmak için MetaEditor'a kopyalamanız (bkz. Şekil 7) ve "Derle"ye tıklamanız gerekir.
Şekil 7. MetaEditor'da IRIS.py komut dosyası
Sonrasında, grafikler ekranda görünecektir:
Şekil 8. Çanak yaprak uzunluğu/çanak yaprak genişliği grafiği ile MetaEditor'da IRIS.py komut dosyası
Şekil 9. Şekil 9. Taç yaprak uzunluğu/taç yaprak genişliği grafiği ile MetaEditor'da IRIS.py komut dosyası
Onlara daha yakından bakalım.
Şekil 10. Çanak yaprak uzunluğu/çanak yaprak genişliği dağılım grafiği
Bu grafikte, farklı iris çiçeği türlerinin çanak yaprak uzunluğu ve çanak yaprak genişliğine göre nasıl dağıldığını görüyoruz. Iris setosa'nın diğer iki türe kıyasla tipik olarak daha kısa ve daha geniş çanak yapraklara sahip olduğunu gözlemliyoruz.
Şekil 11. Taç yaprak uzunluğu/taç yaprak genişliği dağılım grafiği
Bu grafikte, farklı iris çiçeği türlerinin taç yaprak uzunluğu ve taç yaprak genişliğine göre nasıl dağıldığını görüyoruz. Iris setosa'nın en kısa ve en dar taç yapraklara, Iris virginica'nın en uzun ve en geniş taç yapraklara sahip olduğunu ve Iris versicolor'un bu ikisinin arasında kaldığını gözlemliyoruz.
İris veri kümesi, makine öğrenimi modellerini eğitmek ve test etmek için ideal bir veri kümesidir. Bunu, bir sınıflandırma görevi için makine öğrenimi modellerinin etkinliğini analiz etmek için kullanacağız.
2. Sınıflandırma için modeller
Sınıflandırma, makine öğrenimindeki temel görevlerden biridir ve amacı, verileri belirli özelliklere göre farklı kategorilere veya sınıflara ayırmaktır.
Şimdi scikit-learn paketindeki ana makine öğrenimi modellerini inceleyelim.
Scikit-learn sınıflandırıcılarının listesi
Scikit-learn'deki mevcut sınıflandırıcıların listesini görüntülemek için aşağıdaki kodu kullanabilirsiniz:
# ScikitLearnClassifiers.py # The script lists all the classification algorithms available in scikit-learn # Copyright 2023, MetaQuotes Ltd. # https://mql5.com # print Python version from platform import python_version print("The Python version is ", python_version()) # print scikit-learn version import sklearn print('The scikit-learn version is {}.'.format(sklearn.__version__)) # print scikit-learn classifiers from sklearn.utils import all_estimators classifiers = all_estimators(type_filter='classifier') for index, (name, ClassifierClass) in enumerate(classifiers, start=1): print(f"Classifier {index}: {name}")
Çıktı:
Python The scikit-learn version is 1.2.2.
Python Classifier 1: AdaBoostClassifier
Python Classifier 2: BaggingClassifier
Python Classifier 3: BernoulliNB
Python Classifier 4: CalibratedClassifierCV
Python Classifier 5: CategoricalNB
Python Classifier 6: ClassifierChain
Python Classifier 7: ComplementNB
Python Classifier 8: DecisionTreeClassifier
Python Classifier 9: DummyClassifier
Python Classifier 10: ExtraTreeClassifier
Python Classifier 11: ExtraTreesClassifier
Python Classifier 12: GaussianNB
Python Classifier 13: GaussianProcessClassifier
Python Classifier 14: GradientBoostingClassifier
Python Classifier 15: HistGradientBoostingClassifier
Python Classifier 16: KNeighborsClassifier
Python Classifier 17: LabelPropagation
Python Classifier 18: LabelSpreading
Python Classifier 19: LinearDiscriminantAnalysis
Python Classifier 20: LinearSVC
Python Classifier 21: LogisticRegression
Python Classifier 22: LogisticRegressionCV
Python Classifier 23: MLPClassifier
Python Classifier 24: MultiOutputClassifier
Python Classifier 25: MultinomialNB
Python Classifier 26: NearestCentroid
Python Classifier 27: NuSVC
Python Classifier 28: OneVsOneClassifier
Python Classifier 29: OneVsRestClassifier
Python Classifier 30: OutputCodeClassifier
Python Classifier 31: PassiveAggressiveClassifier
Python Classifier 32: Perceptron
Python Classifier 33: QuadraticDiscriminantAnalysis
Python Classifier 34: RadiusNeighborsClassifier
Python Classifier 35: RandomForestClassifier
Python Classifier 36: RidgeClassifier
Python Classifier 37: RidgeClassifierCV
Python Classifier 38: SGDClassifier
Python Classifier 39: SVC
Python Classifier 40: StackingClassifier
Python Classifier 41: VotingClassifier
Bu sınıflandırıcılar listesinde kolaylık sağlamak için farklı renklerle vurgulanmışlardır. Temel sınıflandırıcılara ihtiyaç duyan modeller sarı renkle vurgulanmıştır, diğer modeller ise bağımsız olarak kullanılabilir.
İleriye baktığımızda, yeşil renkli modellerin ONNX formatına başarıyla aktarıldığını, kırmızı renkli modellerin ise scikit-learn 1.2.2'nin mevcut sürümünde dönüştürme sırasında hatalarla karşılaştığını belirtmek gerekir.
Modellerde farklı çıktı temsilleri
Farklı modellerin çıktı verilerini farklı şekilde temsil ettiği unutulmamalıdır, bu nedenle ONNX'e dönüştürülen modellerle çalışırken dikkatli olunmalıdır.
Fisher'ın iris sınıflandırma görevi için, girdi tensörleri tüm bu modeller için aynı biçime sahiptir:
1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
ONNX modellerinin çıktı tensörleri farklıdır.
1. İleri işleme gerektirmeyen modeller:
- SVC Classifier;
- LinearSVC Classifier;
- NuSVC Classifier;
- Radius Neighbors Classifier;
- Ridge Classifier;
- Ridge Classifier CV.
1. Name: label, Data Type: tensor(int64), Shape: [None]
2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Bu modeller sonucu (sınıf numarasını) ileri işleme gerektirmeden ilk çıktı tamsayı tensörü "label" içinde açıkça geri döndürür.
2. Sonuçları ileri işleme gerektiren modeller:
- Random Forest Classifier;
- Gradient Boosting Classifier;
- AdaBoost Classifier;
- Bagging Classifier;
- K-NN_Classifier;
- Decision Tree Classifier;
- Logistic Regression Classifier;
- Logistic Regression CV Classifier;
- Passive-Aggressive Classifier;
- Perceptron Classifier;
- SGD Classifier;
- Gaussian Naive Bayes Classifier;
- Multinomial Naive Bayes Classifier;
- Complement Naive Bayes Classifier;
- Bernoulli Naive Bayes Classifier;
- Multilayer Perceptron Classifier;
- Linear Discriminant Analysis Classifier;
- Hist Gradient Boosting Classifier;
- Categorical Naive Bayes Classifier;
- ExtraTree Classifier;
- ExtraTrees Classifier.
1. Name: output_label, Data Type: tensor(int64), Shape: [None]
2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Bu modeller, sınıfların ve her bir sınıfa ait olma olasılıklarının bir listesini geri döndürür.
Bu durumlarda sonucu elde etmek için, seq(map(int64, tensor(float)) (en yüksek olasılığa sahip öğeyi bulma) gibi ileri işleme gereklidir.
Bu nedenle, ONNX modelleriyle çalışırken dikkatli olmak ve bu hususları göz önünde bulundurmak çok önemlidir. Farklı sonuç işlemeye ilişkin bir örnek 2.28.2'deki komut dosyasında sunulmuştur.
iris.mqh
Modelleri MQL5'te tam iris veri kümesi üzerinde test etmek için veri hazırlığı gereklidir. Bu amaçla PrepareIrisDataset() fonksiyonu kullanılacaktır.
Bu fonksiyonları iris.mqh dosyasına taşımak uygundur.
//+------------------------------------------------------------------+ //| Iris.mqh | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Structure for the IRIS Dataset sample | //+------------------------------------------------------------------+ struct sIRISsample { int sample_id; // sample id (1-150) double features[4]; // SepalLengthCm,SepalWidthCm,PetalLengthCm,PetalWidthCm string class_name; // class ("Iris-setosa","Iris-versicolor","Iris-virginica") int class_id; // class id (0,1,2), calculated by function IRISClassID }; //--- Iris dataset sIRISsample ExtIRISDataset[]; int Exttotal=0; //+------------------------------------------------------------------+ //| Returns class id by class name | //+------------------------------------------------------------------+ int IRISClassID(string class_name) { //--- if(class_name=="Iris-setosa") return(0); else if(class_name=="Iris-versicolor") return(1); else if(class_name=="Iris-virginica") return(2); //--- return(-1); } //+------------------------------------------------------------------+ //| AddSample | //+------------------------------------------------------------------+ bool AddSample(const int Id,const double SepalLengthCm,const double SepalWidthCm,const double PetalLengthCm,const double PetalWidthCm, const string Species) { //--- ExtIRISDataset[Exttotal].sample_id=Id; //--- ExtIRISDataset[Exttotal].features[0]=SepalLengthCm; ExtIRISDataset[Exttotal].features[1]=SepalWidthCm; ExtIRISDataset[Exttotal].features[2]=PetalLengthCm; ExtIRISDataset[Exttotal].features[3]=PetalWidthCm; //--- ExtIRISDataset[Exttotal].class_name=Species; ExtIRISDataset[Exttotal].class_id=IRISClassID(Species); //--- Exttotal++; //--- return(true); } //+------------------------------------------------------------------+ //| Prepare Iris Dataset | //+------------------------------------------------------------------+ bool PrepareIrisDataset(sIRISsample &iris_samples[]) { ArrayResize(ExtIRISDataset,150); Exttotal=0; //--- AddSample(1,5.1,3.5,1.4,0.2,"Iris-setosa"); AddSample(2,4.9,3.0,1.4,0.2,"Iris-setosa"); AddSample(3,4.7,3.2,1.3,0.2,"Iris-setosa"); AddSample(4,4.6,3.1,1.5,0.2,"Iris-setosa"); AddSample(5,5.0,3.6,1.4,0.2,"Iris-setosa"); AddSample(6,5.4,3.9,1.7,0.4,"Iris-setosa"); AddSample(7,4.6,3.4,1.4,0.3,"Iris-setosa"); AddSample(8,5.0,3.4,1.5,0.2,"Iris-setosa"); AddSample(9,4.4,2.9,1.4,0.2,"Iris-setosa"); AddSample(10,4.9,3.1,1.5,0.1,"Iris-setosa"); AddSample(11,5.4,3.7,1.5,0.2,"Iris-setosa"); AddSample(12,4.8,3.4,1.6,0.2,"Iris-setosa"); AddSample(13,4.8,3.0,1.4,0.1,"Iris-setosa"); AddSample(14,4.3,3.0,1.1,0.1,"Iris-setosa"); AddSample(15,5.8,4.0,1.2,0.2,"Iris-setosa"); AddSample(16,5.7,4.4,1.5,0.4,"Iris-setosa"); AddSample(17,5.4,3.9,1.3,0.4,"Iris-setosa"); AddSample(18,5.1,3.5,1.4,0.3,"Iris-setosa"); AddSample(19,5.7,3.8,1.7,0.3,"Iris-setosa"); AddSample(20,5.1,3.8,1.5,0.3,"Iris-setosa"); AddSample(21,5.4,3.4,1.7,0.2,"Iris-setosa"); AddSample(22,5.1,3.7,1.5,0.4,"Iris-setosa"); AddSample(23,4.6,3.6,1.0,0.2,"Iris-setosa"); AddSample(24,5.1,3.3,1.7,0.5,"Iris-setosa"); AddSample(25,4.8,3.4,1.9,0.2,"Iris-setosa"); AddSample(26,5.0,3.0,1.6,0.2,"Iris-setosa"); AddSample(27,5.0,3.4,1.6,0.4,"Iris-setosa"); AddSample(28,5.2,3.5,1.5,0.2,"Iris-setosa"); AddSample(29,5.2,3.4,1.4,0.2,"Iris-setosa"); AddSample(30,4.7,3.2,1.6,0.2,"Iris-setosa"); AddSample(31,4.8,3.1,1.6,0.2,"Iris-setosa"); AddSample(32,5.4,3.4,1.5,0.4,"Iris-setosa"); AddSample(33,5.2,4.1,1.5,0.1,"Iris-setosa"); AddSample(34,5.5,4.2,1.4,0.2,"Iris-setosa"); AddSample(35,4.9,3.1,1.5,0.2,"Iris-setosa"); AddSample(36,5.0,3.2,1.2,0.2,"Iris-setosa"); AddSample(37,5.5,3.5,1.3,0.2,"Iris-setosa"); AddSample(38,4.9,3.6,1.4,0.1,"Iris-setosa"); AddSample(39,4.4,3.0,1.3,0.2,"Iris-setosa"); AddSample(40,5.1,3.4,1.5,0.2,"Iris-setosa"); AddSample(41,5.0,3.5,1.3,0.3,"Iris-setosa"); AddSample(42,4.5,2.3,1.3,0.3,"Iris-setosa"); AddSample(43,4.4,3.2,1.3,0.2,"Iris-setosa"); AddSample(44,5.0,3.5,1.6,0.6,"Iris-setosa"); AddSample(45,5.1,3.8,1.9,0.4,"Iris-setosa"); AddSample(46,4.8,3.0,1.4,0.3,"Iris-setosa"); AddSample(47,5.1,3.8,1.6,0.2,"Iris-setosa"); AddSample(48,4.6,3.2,1.4,0.2,"Iris-setosa"); AddSample(49,5.3,3.7,1.5,0.2,"Iris-setosa"); AddSample(50,5.0,3.3,1.4,0.2,"Iris-setosa"); AddSample(51,7.0,3.2,4.7,1.4,"Iris-versicolor"); AddSample(52,6.4,3.2,4.5,1.5,"Iris-versicolor"); AddSample(53,6.9,3.1,4.9,1.5,"Iris-versicolor"); AddSample(54,5.5,2.3,4.0,1.3,"Iris-versicolor"); AddSample(55,6.5,2.8,4.6,1.5,"Iris-versicolor"); AddSample(56,5.7,2.8,4.5,1.3,"Iris-versicolor"); AddSample(57,6.3,3.3,4.7,1.6,"Iris-versicolor"); AddSample(58,4.9,2.4,3.3,1.0,"Iris-versicolor"); AddSample(59,6.6,2.9,4.6,1.3,"Iris-versicolor"); AddSample(60,5.2,2.7,3.9,1.4,"Iris-versicolor"); AddSample(61,5.0,2.0,3.5,1.0,"Iris-versicolor"); AddSample(62,5.9,3.0,4.2,1.5,"Iris-versicolor"); AddSample(63,6.0,2.2,4.0,1.0,"Iris-versicolor"); AddSample(64,6.1,2.9,4.7,1.4,"Iris-versicolor"); AddSample(65,5.6,2.9,3.6,1.3,"Iris-versicolor"); AddSample(66,6.7,3.1,4.4,1.4,"Iris-versicolor"); AddSample(67,5.6,3.0,4.5,1.5,"Iris-versicolor"); AddSample(68,5.8,2.7,4.1,1.0,"Iris-versicolor"); AddSample(69,6.2,2.2,4.5,1.5,"Iris-versicolor"); AddSample(70,5.6,2.5,3.9,1.1,"Iris-versicolor"); AddSample(71,5.9,3.2,4.8,1.8,"Iris-versicolor"); AddSample(72,6.1,2.8,4.0,1.3,"Iris-versicolor"); AddSample(73,6.3,2.5,4.9,1.5,"Iris-versicolor"); AddSample(74,6.1,2.8,4.7,1.2,"Iris-versicolor"); AddSample(75,6.4,2.9,4.3,1.3,"Iris-versicolor"); AddSample(76,6.6,3.0,4.4,1.4,"Iris-versicolor"); AddSample(77,6.8,2.8,4.8,1.4,"Iris-versicolor"); AddSample(78,6.7,3.0,5.0,1.7,"Iris-versicolor"); AddSample(79,6.0,2.9,4.5,1.5,"Iris-versicolor"); AddSample(80,5.7,2.6,3.5,1.0,"Iris-versicolor"); AddSample(81,5.5,2.4,3.8,1.1,"Iris-versicolor"); AddSample(82,5.5,2.4,3.7,1.0,"Iris-versicolor"); AddSample(83,5.8,2.7,3.9,1.2,"Iris-versicolor"); AddSample(84,6.0,2.7,5.1,1.6,"Iris-versicolor"); AddSample(85,5.4,3.0,4.5,1.5,"Iris-versicolor"); AddSample(86,6.0,3.4,4.5,1.6,"Iris-versicolor"); AddSample(87,6.7,3.1,4.7,1.5,"Iris-versicolor"); AddSample(88,6.3,2.3,4.4,1.3,"Iris-versicolor"); AddSample(89,5.6,3.0,4.1,1.3,"Iris-versicolor"); AddSample(90,5.5,2.5,4.0,1.3,"Iris-versicolor"); AddSample(91,5.5,2.6,4.4,1.2,"Iris-versicolor"); AddSample(92,6.1,3.0,4.6,1.4,"Iris-versicolor"); AddSample(93,5.8,2.6,4.0,1.2,"Iris-versicolor"); AddSample(94,5.0,2.3,3.3,1.0,"Iris-versicolor"); AddSample(95,5.6,2.7,4.2,1.3,"Iris-versicolor"); AddSample(96,5.7,3.0,4.2,1.2,"Iris-versicolor"); AddSample(97,5.7,2.9,4.2,1.3,"Iris-versicolor"); AddSample(98,6.2,2.9,4.3,1.3,"Iris-versicolor"); AddSample(99,5.1,2.5,3.0,1.1,"Iris-versicolor"); AddSample(100,5.7,2.8,4.1,1.3,"Iris-versicolor"); AddSample(101,6.3,3.3,6.0,2.5,"Iris-virginica"); AddSample(102,5.8,2.7,5.1,1.9,"Iris-virginica"); AddSample(103,7.1,3.0,5.9,2.1,"Iris-virginica"); AddSample(104,6.3,2.9,5.6,1.8,"Iris-virginica"); AddSample(105,6.5,3.0,5.8,2.2,"Iris-virginica"); AddSample(106,7.6,3.0,6.6,2.1,"Iris-virginica"); AddSample(107,4.9,2.5,4.5,1.7,"Iris-virginica"); AddSample(108,7.3,2.9,6.3,1.8,"Iris-virginica"); AddSample(109,6.7,2.5,5.8,1.8,"Iris-virginica"); AddSample(110,7.2,3.6,6.1,2.5,"Iris-virginica"); AddSample(111,6.5,3.2,5.1,2.0,"Iris-virginica"); AddSample(112,6.4,2.7,5.3,1.9,"Iris-virginica"); AddSample(113,6.8,3.0,5.5,2.1,"Iris-virginica"); AddSample(114,5.7,2.5,5.0,2.0,"Iris-virginica"); AddSample(115,5.8,2.8,5.1,2.4,"Iris-virginica"); AddSample(116,6.4,3.2,5.3,2.3,"Iris-virginica"); AddSample(117,6.5,3.0,5.5,1.8,"Iris-virginica"); AddSample(118,7.7,3.8,6.7,2.2,"Iris-virginica"); AddSample(119,7.7,2.6,6.9,2.3,"Iris-virginica"); AddSample(120,6.0,2.2,5.0,1.5,"Iris-virginica"); AddSample(121,6.9,3.2,5.7,2.3,"Iris-virginica"); AddSample(122,5.6,2.8,4.9,2.0,"Iris-virginica"); AddSample(123,7.7,2.8,6.7,2.0,"Iris-virginica"); AddSample(124,6.3,2.7,4.9,1.8,"Iris-virginica"); AddSample(125,6.7,3.3,5.7,2.1,"Iris-virginica"); AddSample(126,7.2,3.2,6.0,1.8,"Iris-virginica"); AddSample(127,6.2,2.8,4.8,1.8,"Iris-virginica"); AddSample(128,6.1,3.0,4.9,1.8,"Iris-virginica"); AddSample(129,6.4,2.8,5.6,2.1,"Iris-virginica"); AddSample(130,7.2,3.0,5.8,1.6,"Iris-virginica"); AddSample(131,7.4,2.8,6.1,1.9,"Iris-virginica"); AddSample(132,7.9,3.8,6.4,2.0,"Iris-virginica"); AddSample(133,6.4,2.8,5.6,2.2,"Iris-virginica"); AddSample(134,6.3,2.8,5.1,1.5,"Iris-virginica"); AddSample(135,6.1,2.6,5.6,1.4,"Iris-virginica"); AddSample(136,7.7,3.0,6.1,2.3,"Iris-virginica"); AddSample(137,6.3,3.4,5.6,2.4,"Iris-virginica"); AddSample(138,6.4,3.1,5.5,1.8,"Iris-virginica"); AddSample(139,6.0,3.0,4.8,1.8,"Iris-virginica"); AddSample(140,6.9,3.1,5.4,2.1,"Iris-virginica"); AddSample(141,6.7,3.1,5.6,2.4,"Iris-virginica"); AddSample(142,6.9,3.1,5.1,2.3,"Iris-virginica"); AddSample(143,5.8,2.7,5.1,1.9,"Iris-virginica"); AddSample(144,6.8,3.2,5.9,2.3,"Iris-virginica"); AddSample(145,6.7,3.3,5.7,2.5,"Iris-virginica"); AddSample(146,6.7,3.0,5.2,2.3,"Iris-virginica"); AddSample(147,6.3,2.5,5.0,1.9,"Iris-virginica"); AddSample(148,6.5,3.0,5.2,2.0,"Iris-virginica"); AddSample(149,6.2,3.4,5.4,2.3,"Iris-virginica"); AddSample(150,5.9,3.0,5.1,1.8,"Iris-virginica"); //--- ArrayResize(iris_samples,150); for(int i=0; i<Exttotal; i++) { iris_samples[i]=ExtIRISDataset[i]; } //--- return(true); } //+------------------------------------------------------------------+
Üç popüler sınıflandırma yöntemini karşılaştıralım: SVC (Support Vector Classification), LinearSVC (Linear Support Vector Classification) ve NuSVC (Nu Support Vector Classification).
Çalışma prensipleri:
SVC (Support Vector Classification)
Çalışma prensibi: SVC, sınıflar arasındaki marjın maksimize edilmesine dayanan bir sınıflandırma yöntemidir. Sınıfları maksimum düzeyde ayıran ve hiperdüzleme en yakın noktalar olan destek vektörlerini destekleyen optimum bir ayırıcı hiperdüzlem arar.
Çekirdek fonksiyonları: SVC lineer, radyal temel fonksiyon (RBF), polinom vb. gibi çeşitli çekirdek fonksiyonları kullanabilir. Çekirdek fonksiyonu, optimum hiperdüzlemi bulmak için verilerin nasıl dönüştürüleceğini belirler.
LinearSVC (Linear Support Vector Classification)
Çalışma prensibi: LinearSVC, lineer sınıflandırma konusunda özelleşmiş bir SVC çeşididir. Çekirdek fonksiyonlarını kullanmadan optimum bir doğrusal ayırıcı hiperdüzlem arar. Bu, büyük hacimli verilerle çalışırken daha hızlı ve daha verimli olmasını sağlar.
NuSVC (Nu Support Vector Classification)
Çalışma prensibi: NuSVC de destek vektör yöntemlerine dayanır ancak modelin karmaşıklığını ve destek vektörlerinin oranını kontrol eden bir Nu (nu) parametresi ekler. Nu değeri 0 ila 1 aralığındadır ve verilerin ne kadarının destek vektörleri ve hatalar için kullanılabileceğini belirler.
Avantajlar:
SVC
Güçlü algoritma: SVC, çekirdek fonksiyonlarının kullanımı sayesinde karmaşık sınıflandırma görevlerinin üstesinden gelebilir ve doğrusal olmayan verilerle çalışabilir.
Aykırı değerlere karşı dayanıklılık: SVC, ayırıcı hiperdüzlemi oluşturmak için destek vektörlerini kullandığından veri aykırı değerlerine karşı dayanıklıdır.
LinearSVC
Yüksek verimlilik: LinearSVC, özellikle çok fazla veri olduğunda ve doğrusal ayırma görev için uygun olduğunda, büyük veri kümeleriyle uğraşırken daha hızlı ve daha verimlidir.
Lineer sınıflandırma: Problem doğrusal olarak iyi ayrıştırılabiliyorsa, LinearSVC karmaşık çekirdek fonksiyonlarına ihtiyaç duymadan iyi sonuçlar verebilir.
NuSVC
Model karmaşıklığı kontrolü: NuSVC'deki Nu parametresi, modelin karmaşıklığını ve verilere uyum ile genelleme arasındaki dengeyi kontrol etmenizi sağlar.
Aykırı değerlere karşı dayanıklılık: SVC'ye benzer şekilde, NuSVC de aykırı değerlere karşı dayanıklıdır, bu da onu gürültülü verilere sahip görevler için kullanışlı hale getirir.
Sınırlamalar:
SVC
Hesaplama karmaşıklığı: SVC büyük veri kümelerinde ve/veya karmaşık çekirdek fonksiyonları kullanıldığında yavaş olabilir.
Çekirdek hassasiyeti: Doğru çekirdek fonksiyonunu seçmek zorlu bir görev olabilir ve model performansını önemli ölçüde etkileyebilir.
LinearSVC
Doğrusallık kısıtı: LinearSVC doğrusal veri ayrımı ile kısıtlanır ve özellikler ile hedef değişken arasında doğrusal olmayan bağımlılıkların olduğu durumlarda kötü performans gösterebilir.
NuSVC
Nu parametresinin ayarlanması: Nu parametresinin ayarlanması, optimum sonuçlara ulaşmak için zaman ve deneme gerektirebilir.
Görev karakteristiğine ve veri hacmine bağlı olarak, bu yöntemlerin her biri en iyi seçim olabilir. Denemeler yapmak ve belirli sınıflandırma görevi gereksinimlerine en uygun yöntemi seçmek önemlidir.
2.1. SVC Classifier
Support Vector Classification (SVC) sınıflandırma yöntemi, sınıflandırma görevlerini çözmek için yaygın olarak kullanılan güçlü bir makine öğrenimi algoritmasıdır.
Çalışma prensipleri:
- Optimum ayırıcı hiperdüzlem
Çalışma prensibi: SVC'nin arkasındaki ana fikir, özellik uzayında optimum ayırıcı hiperdüzlemi bulmaktır. Bu hiperdüzlem, farklı sınıflardaki nesneler arasındaki ayrımı en üst düzeye çıkarmalı ve hiperdüzleme en yakın veri noktaları olan destek vektörlerini desteklemelidir.
Marjı en üst düzeye çıkarma: SVC, destek vektörlerinin hiperdüzleme olan uzaklığı anlamına gelen sınıflar arasındaki marjı maksimize etmeyi amaçlar. Bu, yöntemin aykırı değerlere karşı dayanıklı olmasını ve yeni verilere iyi genelleme yapmasını sağlar. - Çekirdek fonksiyonlarının kullanımı
Çekirdek fonksiyonları: SVC lineer, radyal temel fonksiyon (RBF), polinom vb. gibi çeşitli çekirdek fonksiyonları kullanabilir. Çekirdek fonksiyonu, orijinal veri uzayında doğrusal ayrılabilirlik olmasa bile, verilerin görevin doğrusal hale geldiği daha yüksek boyutlu bir uzaya yansıtılmasına olanak tanır.
Çekirdek seçimi: Doğru çekirdek fonksiyonunun seçilmesi SVC modelinin performansını önemli ölçüde etkileyebilir. Doğrusal bir hiperdüzlem her zaman en uygun çözüm değildir.
Avantajlar:
- Güçlü algoritma. Karmaşık görevlerin üstesinden gelme: SVC, özellikler ve hedef değişken arasında doğrusal olmayan bağımlılıklar olanlar da dahil olmak üzere karmaşık sınıflandırma görevlerini çözebilir.
- Aykırı değerlere karşı dayanıklılık: Destek vektörlerinin kullanılması, yöntemi veri aykırı değerlerine karşı dayanıklı hale getirir. Tüm veri kümesi yerine destek vektörlerine bağlıdır.
- Çekirdek esnekliği. Verilere uyarlanabilirlik: Farklı çekirdek fonksiyonları kullanma yeteneği, SVC'nin belirli verilere uyum sağlamasına ve doğrusal olmayan ilişkileri keşfetmesine olanak tanır.
- İyi genelleme. Yeni verilere genelleme: SVC modeli yeni verilere iyi bir şekilde genellenebilir ve bu da onu tahmin görevleri için kullanışlı hale getirir.
Sınırlamalar:
- Hesaplama karmaşıklığı. Eğitim süresi: SVC'nin eğitilmesi, özellikle büyük hacimli verilerle veya karmaşık çekirdek fonksiyonlarıyla uğraşırken yavaş olabilir.
- Çekirdek seçimi. Doğru çekirdek fonksiyonunu seçme: Doğru çekirdek fonksiyonunun seçilmesi denemeler yapmayı gerektirebilir ve veri karakteristiğine bağlıdır.
- Özellik ölçeklendirmesine duyarlılık. Veri normalleştirme: SVC özellik ölçeklendirmesine duyarlıdır, bu nedenle eğitimden önce verilerin normalleştirilmesi veya standartlaştırılması önerilir.
- Model yorumlanabilirliği. Yorumlama karmaşıklığı: Doğrusal olmayan çekirdeklerin ve çok sayıda destek vektörünün kullanılması nedeniyle SVC modellerinin yorumlanması karmaşık olabilir.
Özel göreve ve veri hacmine bağlı olarak, SVC yöntemi sınıflandırma görevlerini çözmek için güçlü bir araç olabilir. Bununla birlikte, optimum sonuçlar elde etmek için sınırlamalarını dikkate almak ve parametreleri ayarlamak çok önemlidir.
2.1.1. SVC Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir SVC Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_SVCClassifier.py # The code demonstrates the process of training SVC model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.svm import SVC from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create an SVC Classifier model with a linear kernel svc_model = SVC(kernel='linear', C=1.0) # train the model on the entire dataset svc_model.fit(X, y) # predict classes for the entire dataset y_pred = svc_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of SVC Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(svc_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path +"svc_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of SVC Classifier model in ONNX format:", accuracy_onnx)
MetaEditor'da "Derle" düğmesini kullanarak kodu çalıştırdıktan sonra, yürütme sonuçlarını Günlük sekmesinde görüntüleyebilirsiniz.
Şekil 12. MetaEditor'da Iris_SVMClassifier.py komut dosyasının sonuçları
Iris_SVCClassifier.py komut dosyasının çıktısı:
Python Accuracy of SVC Classifier model: 0.9933333333333333
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 1.00 0.98 0.99 50
Python 2 0.98 1.00 0.99 50
Python
Python accuracy 0.99 150
Python macro avg 0.99 0.99 0.99 150
Python weighted avg 0.99 0.99 0.99 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\svc_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Python
Python Accuracy of SVC Classifier model in ONNX format: 0.9933333333333333
Burada, ONNX modelinin kaydedildiği yol, ONNX modelinin girdi ve çıktı parametrelerinin türleri ve iris veri setini tanımlamadaki doğruluk hakkında bilgi bulabilirsiniz.
SVM Classifier’ı kullanarak veri kümesini tanımlama doğruluğu %99'dur ve ONNX formatına aktarılan model de aynı doğruluk seviyesini göstermektedir.
Şimdi, 150 veri örneğinin her biri için oluşturulan modeli çalıştırarak bu sonuçları MQL5'te doğrulayacağız. Ek olarak, komut dosyası bir toplu veri işleme örneği de içermektedir.
2.1.2. SVC Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_SVCClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "svc_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- ulong input_shape[]= { batch_size, input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- int output1[]; float output2[][3]; //--- ArrayResize(output1,(int)batch_size); ArrayResize(output2,(int)batch_size); //--- ulong output_shape[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape); //--- ulong output_shape2[]= {batch_size,3}; OnnxSetOutputShape(model,1,output_shape2); //--- bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output1,output2); //--- classes are ready in output1[k]; if(res) { for(int k=0; k<(int)batch_size; k++) model_classes_id[k]=output1[k]; } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="SVCClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Komut dosyasının yürütülmesinin sonuçları MetaTrader 5 terminalinin "Uzmanlar" sekmesinde görüntülenir.
Iris_SVCClassifier (EURUSD,H1) model:SVCClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_SVCClassifier (EURUSD,H1) model:SVCClassifier correct results: 99.33% Iris_SVCClassifier (EURUSD,H1) model=SVCClassifier all samples accuracy=0.993333 Iris_SVCClassifier (EURUSD,H1) model=SVCClassifier batch test accuracy=1.000000
SVC modeli 150 örnekten 149'unu doğru bir şekilde sınıflandırmıştır ki bu mükemmel bir sonuçtur. Model, iris veri setinde sadece bir sınıflandırma hatası yapmış ve 84 numaralı örnek için sınıf 1 (virginica) yerine sınıf 2 (versicolor) tahmininde bulunmuştur.
Dışa aktarılan ONNX modelinin tam iris veri setindeki doğruluğunun %99.33 olduğunu ve bunun orijinal modelin doğruluğuyla eşleştiğini belirtmek gerekir.
2.1.3. SVC Classifier modelinin ONNX gösterimi
Oluşturulan ONNX modelini MetaEditor'da görüntüleyebilirsiniz.
Şekil 13. MetaEditor'da svc_iris.onnx ONNX modeli
Modelin mimarisi hakkında daha ayrıntılı bilgi için Netron'u kullanabilirsiniz. Bunu yapmak için, MetaEditor'da modelin açıklamasındaki "Netron'da aç" düğmesine tıklayın.
Şekil 14. Şekil 14. Netron'da svc_iris.onnx ONNX modeli
Şekil 15. Netron'da svc_iris.onnx ONNX modeli (SVMClassifier ONNX operatör parametreleri)
2.2. LinearSVC Classifier
LinearSVC (Linear Support Vector Classification), ikili ve çok sınıflı sınıflandırma görevleri için kullanılan güçlü bir makine öğrenimi algoritmasıdır. Verileri en iyi şekilde ayıran bir hiperdüzlem bulma fikrine dayanır.
LinearSVC’nin prensipleri:
- Optimum hiperdüzlemin bulunması: LinearSVC'nin ana fikri, iki veri sınıfını maksimum düzeyde ayıran en uygun hiperdüzlemi bulmaktır. Bir hiperdüzlem, doğrusal bir denklemle tanımlanan çok boyutlu bir düzlemdir.
- Marjın en aza indirilmesi: LinearSVC, marjları (veri noktaları ile hiperdüzlem arasındaki mesafeler) en aza indirmeyi amaçlar. Marjlar ne kadar büyük olursa, hiperdüzlem sınıfları o kadar etkili bir şekilde ayırır.
- Doğrusal olarak ayrıştırılamayan verilerin işlenmesi: LinearSVC, verileri doğrusal olarak ayrılabilecekleri daha yüksek boyutlu bir uzaya yansıtan çekirdek fonksiyonlarının (kernel trick) kullanımı sayesinde orijinal özellik uzayında doğrusal olarak ayrılamayan verilerle çalışabilir.
LinearSVC'nin avantajları:
- İyi genelleme: LinearSVC iyi bir genelleme yeteneğine sahiptir ve yeni, görülmemiş veriler üzerinde iyi performans gösterebilir.
- Verimlilik: LinearSVC büyük veri kümeleri üzerinde hızlı bir şekilde çalışır ve nispeten az hesaplama kaynağı gerektirir.
- Doğrusal olarak ayrıştırılamayan verilerin işlenmesi: LinearSVC, çekirdek fonksiyonlarını kullanarak doğrusal olarak ayrılamayan verilerle sınıflandırma görevlerini yerine getirebilir.
- Ölçeklenebilirlik: LinearSVC, çok sayıda özelliğe ve önemli veri hacimlerine sahip görevlerde verimli bir şekilde kullanılabilir.
LinearSVC'nin sınırlamaları:
- Sadece doğrusal ayırıcı hiperdüzlemler: LinearSVC yalnızca doğrusal ayırıcı hiperdüzlemler oluşturur, bu da doğrusal olmayan bağımlılıklara sahip karmaşık sınıflandırma görevleri için yetersiz olabilir.
- Parametre seçimi: Doğru parametrelerin seçilmesi (örneğin, düzenlileştirme parametresi) uzman bilgisi veya çapraz doğrulama gerektirebilir.
- Aykırı değerlere hassasiyet: LinearSVC, verilerdeki aykırı değerlere karşı hassas olabilir ve bu da sınıflandırma kalitesini etkileyebilir.
- Model yorumlanabilirliği: LinearSVC kullanılarak oluşturulan modeller, diğer bazı yöntemlere kıyasla daha az yorumlanabilir olabilir.
LinearSVC, genelleme, verimlilik ve doğrusal olarak ayrılamayan verileri işleme konusunda üstün olan güçlü bir sınıflandırma algoritmasıdır. Özellikle veriler doğrusal bir hiperdüzlemle ayrılabildiğinde, çeşitli sınıflandırma görevlerinde uygulama alanı bulur. Bununla birlikte, doğrusal olmayan bağımlılıkların modellenmesini gerektiren karmaşık görevler için LinearSVC daha az uygun olabilir ve bu gibi durumlarda, daha karmaşık karar sınırlarına sahip alternatif yöntemler düşünülmelidir.
2.2.1. LinearSVC Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir LinearSVC Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_LinearSVC.py # The code demonstrates the process of training LinearSVC model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.svm import LinearSVC from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a LinearSVC model linear_svc_model = LinearSVC(C=1.0, max_iter=10000) # train the model on the entire dataset linear_svc_model.fit(X, y) # predict classes for the entire dataset y_pred = linear_svc_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of LinearSVC model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(linear_svc_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "linear_svc_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of LinearSVC model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.96 0.94 0.95 50
Python 2 0.94 0.96 0.95 50
Python
Python accuracy 0.97 150
Python macro avg 0.97 0.97 0.97 150
Python weighted avg 0.97 0.97 0.97 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\linear_svc_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Python
Python Accuracy of LinearSVC model in ONNX format: 0.9666666666666667
2.2.2. LinearSVC Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_LinearSVC.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "linear_svc_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- ulong input_shape[]= { batch_size, input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- int output1[]; float output2[][3]; //--- ArrayResize(output1,(int)batch_size); ArrayResize(output2,(int)batch_size); //--- ulong output_shape[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape); //--- ulong output_shape2[]= {batch_size,3}; OnnxSetOutputShape(model,1,output_shape2); //--- bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output1,output2); //--- classes are ready in output1[k]; if(res) { for(int k=0; k<(int)batch_size; k++) model_classes_id[k]=output1[k]; } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="LinearSVC"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_LinearSVC (EURUSD,H1) model:LinearSVC sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_LinearSVC (EURUSD,H1) model:LinearSVC sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_LinearSVC (EURUSD,H1) model:LinearSVC sample=85 FAILED [class=2, true class=1] features=(5.40,3.00,4.50,1.50] Iris_LinearSVC (EURUSD,H1) model:LinearSVC sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_LinearSVC (EURUSD,H1) model:LinearSVC sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_LinearSVC (EURUSD,H1) model:LinearSVC correct results: 96.67% Iris_LinearSVC (EURUSD,H1) model=LinearSVC all samples accuracy=0.966667 Iris_LinearSVC (EURUSD,H1) model=LinearSVC batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %96.67'dir ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.2.3. LinearSVC Classifier modelinin ONNX gösterimi
Şekil 16. Netron'da LinearSVC Classifier modelinin ONNX gösterimi
2.3. NuSVC Classifier
Nu-Support Vector Classification (NuSVC) yöntemi, Support Vector Machine (SVM) yaklaşımına dayanan güçlü bir makine öğrenimi algoritmasıdır.
NuSVC’nin prensipleri:
- Support Vector Machine (SVM): NuSVC, ikili ve çok sınıflı sınıflandırma görevleri için kullanılan bir SVM çeşididir. SVM'nin temel prensibi, maksimum marjı korurken sınıfları maksimum düzeyde ayıran optimum ayırıcı hiperdüzlemi bulmaktır.
- Nu parametresi: NuSVC'deki önemli bir parametre, modelin karmaşıklığını kontrol eden ve destek vektörleri ve hatalar olarak kullanılabilecek örneklem oranını tanımlayan Nu parametresidir (nu). Nu değeri 0 ila 1 arasında değişir; burada 0.5, örneğin yaklaşık yarısının destek vektörleri ve hatalar olarak kullanılacağı anlamına gelir.
- Parametre ayarlama: Nu parametresi ve diğer hiperparametreler için en uygun değerlerin belirlenmesi, çapraz doğrulama ve eğitim verileri üzerinde en iyi değerlerin aranmasını gerektirebilir.
- Çekirdek fonksiyonları: NuSVC lineer, radyal temel fonksiyon (RBF), polinom vb. gibi çeşitli çekirdek fonksiyonları kullanabilir. Çekirdek fonksiyonu, ayırıcı hiperdüzlemi bulmak için özellik uzayının nasıl dönüştürüleceğini belirler.
NuSVC'nin avantajları:
- Yüksek boyutlu uzaylarda verimlilik: NuSVC yüksek boyutlu uzaylarda verimli bir şekilde çalışabilir, bu da onu çok sayıda özelliğe sahip görevler için uygun hale getirir.
- Aykırı değerlere karşı dayanıklılık: SVM ve özellikle NuSVC, destek vektörlerinin kullanımı nedeniyle verilerdeki aykırı değerlere karşı dayanıklıdır.
- Model karmaşıklığının kontrolü: Nu parametresi, model karmaşıklığının kontrol edilmesine ve genelleme ile veri uyumunun dengelenmesine olanak tanır.
- İyi genelleme: Özellikle SVM ve NuSVC iyi bir genelleme sergileyerek daha önce görülmemiş yeni veriler üzerinde mükemmel performans sağlar.
NuSVC'nin sınırlamaları:
- Büyük veri hacimlerinde verimsizlik: NuSVC, hesaplama karmaşıklığı nedeniyle büyük veri hacimleri üzerinde eğitildiğinde verimsiz olabilir.
- Parametre ayarlama gereksinimi: Nu parametresinin ve çekirdek fonksiyonunun ayarlanması zaman ve hesaplama kaynakları gerektirebilir.
- Çekirdek fonksiyonu doğrusallığı: NuSVC'nin etkinliği önemli ölçüde çekirdek fonksiyonunun seçimine bağlı olabilir ve bazı görevler için farklı fonksiyonlarla denemeler yapmak gerekebilir.
- Model yorumlanabilirliği: SVM ve NuSVC mükemmel sonuçlar sağlar, ancak özellikle doğrusal olmayan çekirdekler kullanıldığında modellerinin yorumlanması karmaşık olabilir.
Nu-Support Vector Classification (NuSVC), aykırı değerlere karşı sağlamlık ve iyi genelleme gibi çeşitli avantajlara sahip SVM'ye dayalı güçlü bir sınıflandırma yöntemidir. Bununla birlikte, etkinliği parametre ve çekirdek fonksiyonu seçimine bağlıdır ve büyük veri hacimleri için verimsiz olabilir. Parametreleri dikkatlice seçmek ve yöntemi belirli sınıflandırma görevlerine uyarlamak çok önemlidir.
2.3.1. NuSVC Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir NuSVC Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_NuSVC.py # The code demonstrates the process of training NuSVC model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.svm import NuSVC from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a NuSVC model nusvc_model = NuSVC(nu=0.5, kernel='linear') # train the model on the entire dataset nusvc_model.fit(X, y) # predict classes for the entire dataset y_pred = nusvc_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of NuSVC model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(nusvc_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "nusvc_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of NuSVC model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.96 0.96 0.96 50
Python 2 0.96 0.96 0.96 50
Python
Python accuracy 0.97 150
Python macro avg 0.97 0.97 0.97 150
Python weighted avg 0.97 0.97 0.97 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\nusvc_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Python
Python Accuracy of NuSVC model in ONNX format: 0.9733333333333334
2.3.2. NuSVC Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_NuSVC.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "nusvc_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- ulong input_shape[]= { batch_size, input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- int output1[]; float output2[][3]; //--- ArrayResize(output1,(int)batch_size); ArrayResize(output2,(int)batch_size); //--- ulong output_shape[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape); //--- ulong output_shape2[]= {batch_size,3}; OnnxSetOutputShape(model,1,output_shape2); //--- bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output1,output2); //--- classes are ready in output1[k]; if(res) { for(int k=0; k<(int)batch_size; k++) model_classes_id[k]=output1[k]; } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="NuSVC"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_NuSVC (EURUSD,H1) model:NuSVC sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_NuSVC (EURUSD,H1) model:NuSVC sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_NuSVC (EURUSD,H1) model:NuSVC sample=107 FAILED [class=1, true class=2] features=(4.90,2.50,4.50,1.70] Iris_NuSVC (EURUSD,H1) model:NuSVC sample=139 FAILED [class=1, true class=2] features=(6.00,3.00,4.80,1.80] Iris_NuSVC (EURUSD,H1) model:NuSVC correct results: 97.33% Iris_NuSVC (EURUSD,H1) model=NuSVC all samples accuracy=0.973333 Iris_NuSVC (EURUSD,H1) model=NuSVC batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %97.33'tür ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.3.3. NuSVC Classifier modelinin ONNX gösterimi
Şekil 17. Netron'da NuSVC Classifier modelinin ONNX gösterimi
2.4. Radius Neighbors Classifier
Radius Neighbors Classifier, nesneler arasındaki yakınlık ilkesine dayalı sınıflandırma görevleri için kullanılan bir makine öğrenimi yöntemidir. Sabit sayıda en yakın komşunun (K) seçildiği klasik K-Nearest Neighbors (K-NN) Classifier’ın aksine, Radius Neighbors Classifier’da nesneler belirli bir yarıçap içindeki en yakın komşulara olan uzaklıklarına göre sınıflandırılır.Radius Neighbors Classifier’ın prensipleri:
- Yarıçapın belirlenmesi: Radius Neighbors Classifier’ın ana parametresi, bir nesne ile komşuları arasında nesnenin komşu sınıfa yakın olarak kabul edildiği maksimum mesafeyi tanımlayan yarıçaptır.
- En yakın komşuları bulma: Eğitim veri kümesindeki diğer tüm nesnelere olan uzaklık her nesne için hesaplanır. Belirtilen yarıçap içinde bulunan nesneler, nesnenin komşuları olarak kabul edilir.
- Oylama: Radius Neighbors Classifier, nesnenin sınıfını belirlemek için komşular arasında çoğunluk oylamasını kullanır. Örneğin, komşuların çoğunluğu A sınıfına aitse, nesne de A sınıfı olarak sınıflandırılacaktır.
- Veri yoğunluğuna uyarlanabilirlik: The Radius Neighbors Classifier, farklı özellik uzayı bölgelerindeki veri yoğunluğunun değişebildiği görevler için uygundur.
- Farklı sınıf şekilleri ile çalışabilme becerisi: Bu yöntem, sınıfların karmaşık ve doğrusal olmayan şekillere sahip olduğu görevlerde iyi performans gösterir.
- Aykırı değerler içeren veriler için uygundur: Radius Neighbors Classifier, belirtilen yarıçapın ötesinde bulunan komşuları göz ardı ettiği için aykırı değerlere karşı K-NN'den daha dayanıklıdır.
- Yarıçap seçimine duyarlılık: Optimum yarıçap değerinin seçilmesi basit olmayan bir görev olabilir ve ayarlama gerektirir.
- Büyük veri kümelerinde verimsizlik: Büyük veri kümeleri için, tüm nesnelere olan uzaklıkları hesaplamak hesaplama açısından maliyetli olabilir.
- Veri yoğunluğuna bağımlılık: Veriler özellik uzayında tekdüze olmayan bir yoğunluğa sahip olduğunda bu yöntem daha az verimli olabilir.
Radius Neighbors Classifier, nesne yakınlığının önemli olduğu ve sınıf şekillerinin karmaşık olabileceği durumlarda değerli bir makine öğrenimi yöntemidir. Görüntü analizi, doğal dil işleme vb. çeşitli alanlarda uygulanabilir.
2.4.1. Radius Neighbors Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Radius Neighbors Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_RadiusNeighborsClassifier.py # The code demonstrates the process of training an Radius Neughbors model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023 MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.neighbors import RadiusNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Radius Neighbors Classifier model radius_model = RadiusNeighborsClassifier(radius=1.0) # train the model on the entire dataset radius_model.fit(X, y) # predict classes for the entire dataset y_pred = radius_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Radius Neighbors Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(radius_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "radius_neighbors_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Radius Neighbors Classifier model in ONNX format:", accuracy_onnx)
Iris_RadiusNeighbors.py komut dosyasının sonuçları:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.94 0.98 0.96 50
Python 2 0.98 0.94 0.96 50
Python
Python accuracy 0.97 150
Python macro avg 0.97 0.97 0.97 150
Python weighted avg 0.97 0.97 0.97 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\radius_neighbors_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Python
Python Accuracy of Radius Neighbors Classifier model in ONNX format: 0.9733333333333334
Orijinal modelin doğruluğu ile ONNX formatında dışa aktarılan modelin doğruluğu aynıdır.
2.4.2. Radius Neighbors Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_RadiusNeighborsClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "radius_neighbors_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- ulong input_shape[]= { batch_size, input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- int output1[]; float output2[][3]; //--- ArrayResize(output1,(int)batch_size); ArrayResize(output2,(int)batch_size); //--- ulong output_shape[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape); //--- ulong output_shape2[]= {batch_size,3}; OnnxSetOutputShape(model,1,output_shape2); //--- bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output1,output2); //--- classes are ready in output1[k]; if(res) { for(int k=0; k<(int)batch_size; k++) model_classes_id[k]=output1[k]; } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="RadiusNeighborsClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_RadiusNeighborsClassifier (EURUSD,H1) model:RadiusNeighborsClassifier sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_RadiusNeighborsClassifier (EURUSD,H1) model:RadiusNeighborsClassifier sample=107 FAILED [class=1, true class=2] features=(4.90,2.50,4.50,1.70] Iris_RadiusNeighborsClassifier (EURUSD,H1) model:RadiusNeighborsClassifier sample=127 FAILED [class=1, true class=2] features=(6.20,2.80,4.80,1.80] Iris_RadiusNeighborsClassifier (EURUSD,H1) model:RadiusNeighborsClassifier sample=139 FAILED [class=1, true class=2] features=(6.00,3.00,4.80,1.80] Iris_RadiusNeighborsClassifier (EURUSD,H1) model:RadiusNeighborsClassifier correct results: 97.33% Iris_RadiusNeighborsClassifier (EURUSD,H1) model=RadiusNeighborsClassifier all samples accuracy=0.973333 Iris_RadiusNeighborsClassifier (EURUSD,H1) model=RadiusNeighborsClassifier batch test accuracy=1.000000
Radius Neighbors Classifier modeli 4 sınıflandırma hatasıyla (78, 107, 127 ve 139 numaralı örnekler) %97.33'lük bir doğruluk oranı göstermiştir.
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %97.33'tür ve bu da orijinal modelin doğruluğuyla eşleşmektedir.
2.4.3. Radius Neighbors Classifier modelinin ONNX gösterimi
Şekil 18. Netron'da Radius Neighbors Classifier modelinin ONNX gösterimi
RidgeClassifier ve RidgeClassifierCV yöntemleri hakkında not
RidgeClassifier ve RidgeClassifierCV, Ridge regresyonuna dayanan iki sınıflandırma yöntemidir, ancak parametrelerin ayarlanma şekli ve hiperparametrelerin otomatik olarak seçilmesi bakımından farklılık gösterirler:
RidgeClassifier:
- RidgeClassifier, ikili ve çok sınıflı sınıflandırma görevleri için kullanılan Ridge regresyonuna dayalı bir sınıflandırma yöntemidir.
- Çok sınıflı sınıflandırma durumunda, RidgeClassifier görevi birden fazla ikili göreve (bire karşı hepsi) dönüştürür ve her biri için bir model oluşturur.
- Alfa düzenlileştirme parametresinin kullanıcı tarafından manuel olarak ayarlanması gerekir, yani denemeler veya doğrulama verilerinin analizi yoluyla en uygun alfa değerini seçmeniz gerekir.
RidgeClassifierCV:
- RidgeClassifierCV, çapraz doğrulama için yerleşik destek ve optimum alfa düzenlileştirme parametresinin otomatik seçimini sağlayan RidgeClassifier'ın bir uzantısıdır.
- Alfa değerini manuel olarak ayarlamak yerine, RidgeClassifierCV'ye araştırılacak alfa değerlerinin bir listesini sağlayabilir ve çapraz doğrulama yöntemini belirtebilirsiniz (örneğin, cv parametresi aracılığıyla).
- RidgeClassifierCV, çapraz doğrulama sırasında en iyi performansı gösteren optimum alfa değerini otomatik olarak seçer.
Dolayısıyla, aralarındaki temel fark, alfa düzenlileştirme parametresi için en uygun değerin seçilmesindeki otomasyon seviyesinde yatmaktadır. RidgeClassifier, alfanın manuel olarak ayarlanmasını gerektirirken RidgeClassifierCV, çapraz doğrulama kullanarak optimum alfa değerinin otomatik olarak seçilmesine olanak tanır. Bunlar arasındaki tercih, ihtiyaçlarınıza ve model ayarlama sürecindeki otomasyon isteğinize bağlıdır.
2.5. Ridge Classifier
Ridge Classifier, modelde L2 düzenlileştirme (Ridge regresyonu) içeren bir lojistik regresyon çeşididir. L2 düzenlileştirme, modelin büyük katsayılarına bir ceza ekleyerek aşırı uyumu azaltmaya ve modelin genelleme yeteneğini geliştirmeye yardımcı olur.
Ridge Classifier’ın prensipleri:
- Olasılıkların tahmini: Lojistik regresyon gibi, Ridge Classifier da lojistik (sigmoid) bir fonksiyon kullanarak bir nesnenin belirli bir sınıfa ait olma olasılığını modeller.
- L2 düzenlileştirme: Ridge Classifier, modelin büyük katsayılarını cezalandıran bir L2 düzenlileştirme terimi ekler. Bu, modelin karmaşıklığını kontrol etmek ve aşırı uyumu azaltmak için yapılır.
- Parametre eğitimi: Ridge Classifier modeli, özellikler ve düzenlileştirme parametresi için ağırlıkları (katsayıları) ayarlamak üzere eğitim veri kümesi üzerinde eğitilir.
Ridge Classifier’ın avantajları:
- Aşırı uyum azaltma: L2 düzenlileştirme, modelin aşırı uyum sağlama eğilimini azaltmaya yardımcı olur, bu da özellikle sınırlı veri olduğunda yararlıdır.
- Çoklu eşdoğrusallığın yönetimi: Ridge Classifier, özelliklerin birbiriyle yüksek oranda ilişkili olduğu çoklu eşdoğrusallık sorunlarını iyi bir şekilde yönetir.
Ridge Classifier’ın sınırlamaları:
- Düzenlileştirme parametresi seçimine duyarlılık: Diğer düzenlileştirme yöntemleri gibi, düzenlileştirme parametresi (alfa) için doğru değeri seçmek ayarlama ve değerlendirme gerektirir.
- Çok sınıflı sınıflandırma kısıtı: Ridge Classifier başlangıçta ikili sınıflandırma için tasarlanmıştır, ancak One-vs-All gibi yaklaşımlar kullanılarak çok sınıflı sınıflandırmaya uyarlanabilir.
Ridge Classifier, aşırı uyumla mücadele etmek ve modelin genelleme yeteneğini geliştirmek için lojistik regresyonun faydalarını düzenlileştirmeyle birleştiren güçlü bir makine öğrenimi yöntemidir. Olasılıksal sınıflandırma ve model karmaşıklığı kontrolünün önemli olduğu çeşitli alanlarda uygulama alanı bulmaktadır.
2.5.1. Ridge Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Ridge Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_RidgeClassifier.py # The code demonstrates the process of training Ridge Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import RidgeClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Ridge Classifier model ridge_model = RidgeClassifier() # train the model on the entire dataset ridge_model.fit(X, y) # predict classes for the entire dataset y_pred = ridge_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Ridge Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(ridge_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "ridge_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Ridge Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.87 0.66 0.75 50
Python 2 0.73 0.90 0.80 50
Python
Python accuracy 0.85 150
Python macro avg 0.86 0.85 0.85 150
Python weighted avg 0.86 0.85 0.85 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\ridge_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Python
Python Accuracy of Ridge Classifier model in ONNX format: 0.8533333333333334
2.5.2. Ridge Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_RidgeClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "ridge_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- ulong input_shape[]= { batch_size, input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- int output1[]; float output2[][3]; //--- ArrayResize(output1,(int)batch_size); ArrayResize(output2,(int)batch_size); //--- ulong output_shape[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape); //--- ulong output_shape2[]= {batch_size,3}; OnnxSetOutputShape(model,1,output_shape2); //--- bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output1,output2); //--- classes are ready in output1[k]; if(res) { for(int k=0; k<(int)batch_size; k++) model_classes_id[k]=output1[k]; } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="RidgeClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=51 FAILED [class=2, true class=1] features=(7.00,3.20,4.70,1.40] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=52 FAILED [class=2, true class=1] features=(6.40,3.20,4.50,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=53 FAILED [class=2, true class=1] features=(6.90,3.10,4.90,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=57 FAILED [class=2, true class=1] features=(6.30,3.30,4.70,1.60] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=62 FAILED [class=2, true class=1] features=(5.90,3.00,4.20,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=65 FAILED [class=2, true class=1] features=(5.60,2.90,3.60,1.30] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=66 FAILED [class=2, true class=1] features=(6.70,3.10,4.40,1.40] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=67 FAILED [class=2, true class=1] features=(5.60,3.00,4.50,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=76 FAILED [class=2, true class=1] features=(6.60,3.00,4.40,1.40] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=79 FAILED [class=2, true class=1] features=(6.00,2.90,4.50,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=85 FAILED [class=2, true class=1] features=(5.40,3.00,4.50,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=86 FAILED [class=2, true class=1] features=(6.00,3.40,4.50,1.60] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=87 FAILED [class=2, true class=1] features=(6.70,3.10,4.70,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=89 FAILED [class=2, true class=1] features=(5.60,3.00,4.10,1.30] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=92 FAILED [class=2, true class=1] features=(6.10,3.00,4.60,1.40] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=109 FAILED [class=1, true class=2] features=(6.70,2.50,5.80,1.80] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier sample=135 FAILED [class=1, true class=2] features=(6.10,2.60,5.60,1.40] Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier correct results: 85.33% Iris_RidgeClassifier (EURUSD,H1) model=RidgeClassifier all samples accuracy=0.853333 Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier FAILED [class=2, true class=1] features=(7.00,3.20,4.70,1.40) Iris_RidgeClassifier (EURUSD,H1) model:RidgeClassifier FAILED [class=2, true class=1] features=(6.40,3.20,4.50,1.50) Iris_RidgeClassifier (EURUSD,H1) model=RidgeClassifier batch test accuracy=0.000000
Tam iris veri kümesinde model, orijinalin doğruluğuna karşılık gelen %85.33'lük bir doğruluk göstermiştir.
2.5.3. Ridge Classifier modelinin ONNX gösterimi
Şekil 19. Netron'da Ridge Classifier modelinin ONNX gösterimi
2.6. RidgeClassifierCV
RidgeClassifierCV sınıflandırma yöntemi, Ridge regresyonuna dayalı ikili ve çok sınıflı sınıflandırma için güçlü bir algoritmadır.
RidgeClassifierCV'nin prensipleri:
- Lineer Ridge regresyonu: RidgeClassifierCV lineer Ridge regresyonuna dayanmaktadır. Bu yöntem, L2 düzenlileştirmenin eklendiği lineer regresyonun bir modifikasyonudur. Düzenlileştirme, özellik ağırlıklarının büyüklüğünü azaltarak aşırı uyumu kontrol etmeye yardımcı olur.
- İkili ve çok sınıflı sınıflandırma: RidgeClassifierCV hem ikili sınıflandırma (sadece iki sınıf olduğunda) hem de çok sınıflı sınıflandırma (ikiden fazla sınıf olduğunda) için kullanılabilir. Çok sınıflı sınıflandırma için, görevi birden fazla ikili göreve dönüştürür (bire karşı hepsi) ve her biri için bir model oluşturur.
- Düzenlileştirme parametresinin otomatik seçimi: RidgeClassifierCV'nin en önemli avantajlarından biri, çapraz doğrulama için yerleşik desteği ve optimum alfa düzenlileştirme parametresinin otomatik seçimidir. Alfa değerini manuel olarak ayarlamak yerine, yöntem farklı alfa değerleri üzerinde yineleme yapar ve çapraz doğrulamaya dayalı olarak en iyisini seçer.
- Çoklu eşdoğrusallığın yönetimi: RidgeClassifierCV, özelliklerin birbiriyle yüksek oranda ilişkili olduğu çoklu eşdoğrusallık sorunlarını iyi bir şekilde yönetir. Düzenlileştirme, her bir özelliğin katkısının kontrol edilmesini sağlayarak modeli korelasyonlu verilere karşı dayanıklı hale getirir.
RidgeClassifierCV'nin avantajları:
- Otomatik hiperparametre seçimi: RidgeClassifierCV'nin önemli avantajlarından biri, çapraz doğrulama kullanarak en uygun alfa değerini otomatik olarak seçebilmesidir. Bu, farklı alfa değerleriyle denemeler yapma ihtiyacını ortadan kaldırır ve iyi sonuçlar elde etme olasılığını artırır.
- Aşırı uyum kontrolü: RidgeClassifierCV tarafından sağlanan L2 düzenlileştirme, model karmaşıklığını kontrol etmeye yardımcı olur ve aşırı uyum riskini azaltır. Bu özellikle sınırlı veriye sahip görevler için önemlidir.
- Şeffaflık ve yorumlanabilirlik: RidgeClassifierCV, yorumlanabilir özellik ağırlıkları sağlayarak her bir özelliğin tahminlere katkısının analiz edilmesine ve özelliklerin önemine ilişkin sonuçlar çıkarılmasına olanak tanır.
- Verimlilik: Yöntem oldukça verimlidir ve büyük veri kümelerine uygulanabilir.
RidgeClassifierCV'nin sınırlamaları:
- Doğrusallık: RidgeClassifierCV, özellikler ve hedef değişken arasında doğrusal ilişkiler olduğunu varsayar. Veriler güçlü doğrusal olmayan ilişkiler sergiliyorsa, yöntem yeterince doğru olmayabilir.
- Özellik ölçeklendirme hassasiyeti: Yöntem, özellik ölçeklendirmesine duyarlıdır. RidgeClassifierCV'yi uygulamadan önce özelliklerin standartlaştırılması veya normalleştirilmesi önerilir.
- Optimum özellik seçimi: RidgeClassifierCV otomatik özellik seçimi yapmaz, bu nedenle hangi özelliklerin modele dahil edileceğine manuel olarak karar vermeniz gerekir.
RidgeClassifierCV sınıflandırma yöntemi, optimum düzenlileştirme parametresinin otomatik seçimi ile ikili ve çok sınıflı sınıflandırma için güçlü bir araçtır. Aşırı uyum kontrolü, yorumlanabilirliği ve verimliliği, onu çeşitli sınıflandırma görevleri için popüler bir seçim haline getirmektedir. Bununla birlikte, sınırlamalarını, özellikle de özellikler ve hedef değişken arasındaki doğrusal ilişkiler varsayımını akılda tutmak önemlidir.
2.6.1. RidgeClassifierCV modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir RidgeClassifierCV modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_RidgeClassifierCV.py # The code demonstrates the process of training RidgeClassifierCV model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import RidgeClassifierCV from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a RidgeClassifierCV model ridge_classifier_cv_model = RidgeClassifierCV() # train the model on the entire dataset ridge_classifier_cv_model.fit(X, y) # predict classes for the entire dataset y_pred = ridge_classifier_cv_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of RidgeClassifierCV model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(ridge_classifier_cv_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "ridge_classifier_cv_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of RidgeClassifierCV model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.87 0.66 0.75 50
Python 2 0.73 0.90 0.80 50
Python
Python accuracy 0.85 150
Python macro avg 0.86 0.85 0.85 150
Python weighted avg 0.86 0.85 0.85 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\ridge_classifier_cv_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: probabilities, Data Type: tensor(float), Shape: [None, 3]
Python
Python Accuracy of RidgeClassifierCV model in ONNX format: 0.8533333333333334
2.6.2. RidgeClassifierCV modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_RidgeClassifierCV.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "ridge_classifier_cv_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- ulong input_shape[]= { batch_size, input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- int output1[]; float output2[][3]; //--- ArrayResize(output1,(int)batch_size); ArrayResize(output2,(int)batch_size); //--- ulong output_shape[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape); //--- ulong output_shape2[]= {batch_size,3}; OnnxSetOutputShape(model,1,output_shape2); //--- bool res=OnnxRun(model,ONNX_DEBUG_LOGS,input_data,output1,output2); //--- classes are ready in output1[k]; if(res) { for(int k=0; k<(int)batch_size; k++) model_classes_id[k]=output1[k]; } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="RidgeClassifierCV"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=51 FAILED [class=2, true class=1] features=(7.00,3.20,4.70,1.40] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=52 FAILED [class=2, true class=1] features=(6.40,3.20,4.50,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=53 FAILED [class=2, true class=1] features=(6.90,3.10,4.90,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=57 FAILED [class=2, true class=1] features=(6.30,3.30,4.70,1.60] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=62 FAILED [class=2, true class=1] features=(5.90,3.00,4.20,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=65 FAILED [class=2, true class=1] features=(5.60,2.90,3.60,1.30] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=66 FAILED [class=2, true class=1] features=(6.70,3.10,4.40,1.40] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=67 FAILED [class=2, true class=1] features=(5.60,3.00,4.50,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=76 FAILED [class=2, true class=1] features=(6.60,3.00,4.40,1.40] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=79 FAILED [class=2, true class=1] features=(6.00,2.90,4.50,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=85 FAILED [class=2, true class=1] features=(5.40,3.00,4.50,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=86 FAILED [class=2, true class=1] features=(6.00,3.40,4.50,1.60] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=87 FAILED [class=2, true class=1] features=(6.70,3.10,4.70,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=89 FAILED [class=2, true class=1] features=(5.60,3.00,4.10,1.30] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=92 FAILED [class=2, true class=1] features=(6.10,3.00,4.60,1.40] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=109 FAILED [class=1, true class=2] features=(6.70,2.50,5.80,1.80] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV sample=135 FAILED [class=1, true class=2] features=(6.10,2.60,5.60,1.40] Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV correct results: 85.33% Iris_RidgeClassifierCV (EURUSD,H1) model=RidgeClassifierCV all samples accuracy=0.853333 Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV FAILED [class=2, true class=1] features=(7.00,3.20,4.70,1.40) Iris_RidgeClassifierCV (EURUSD,H1) model:RidgeClassifierCV FAILED [class=2, true class=1] features=(6.40,3.20,4.50,1.50) Iris_RidgeClassifierCV (EURUSD,H1) model=RidgeClassifierCV batch test accuracy=0.000000
ONNX modelinin performansı, orijinal scikit-learn modelinin performansıyla mükemmel bir şekilde eşleşmektedir (%85.33).
2.6.3. RidgeClassifierCV modelinin ONNX gösterimi
Şekil 20. Netron'da RidgeClassifierCV modelinin ONNX gösterimi
2.7. Random Forest Classifier
Random Forest Classifier, birden fazla karar ağacı oluşturmaya ve sınıflandırma kalitesini artırmak için sonuçlarını birleştirmeye dayanan bir topluluk makine öğrenimi yöntemidir. Bu yöntem, etkinliği ve farklı verilerle çalışma kabiliyeti nedeniyle son derece popülerdir.
Random Forest Classifier’ın prensipleri:
- Bagging (Bootstrap Aggregating): Random Forest, eğitim verilerinden değiştirme ile birden fazla alt örneklem (yeniden örnekleme) oluşturmayı içeren torbalama yöntemini kullanır. Her bir alt örneklem için ayrı bir karar ağacı oluşturulur.
- Rastgele özellik seçimi: Her bir ağaç oluşturulurken, tüm özellik kümesinden rastgele bir özellik alt kümesi seçilir. Bu, ağaçlar arasında çeşitliliği teşvik eder ve aralarındaki korelasyonları azaltır.
- Oylama: Bir nesneyi sınıflandırırken, her ağaç kendi tahminini sunar ve tüm ağaçlar arasında en çok oyu alan sınıf nihai model tahmini olarak seçilir.
Random Forest Classifier’ın avantajları:
- Yüksek doğruluk: Random Forest tipik olarak birden fazla ağacın sonuçlarının ortalamasını alarak yüksek sınıflandırma doğruluğuna ulaşır.
- Farklı verileri işleme becerisi: Sayısal ve kategorik özelliklerin yanı sıra farklı yapılardaki verilerle de iyi çalışır.
- Aşırı uyum direnci: Random Forest yerleşik düzenlileştirmeye sahiptir, bu da onu aşırı uyuma karşı dirençli hale getirir.
- Özelliğin önemi: Random Forest, özelliklerin önemini değerlendirerek veri bilimcilerin ve özellik mühendislerinin verileri daha iyi anlamasına yardımcı olabilir.
Random Forest Classifier’ın sınırlamaları:
- Hesaplama karmaşıklığı: Bir Random Forest’ı eğitmek, özellikle çok sayıda ağaç ve özellik söz konusu olduğunda zaman alıcı olabilir.
- Yorumlanabilirlik zorlukları: Çok sayıda ağaç ve rastgele özellik seçimi nedeniyle modelin yorumlanması zor olabilir.
- Aykırı değer dayanıklılığı garanti edilmez: Random Forest, veri aykırı değerlerine karşı her zaman dayanıklılık sağlamaz.
Random Forest Classifier, biyotıp, finansal analiz ve metin veri analizi dahil olmak üzere çeşitli alanlarda yaygın olarak kullanılan güçlü bir makine öğrenimi algoritmasıdır. Sınıflandırma ve regresyon görevlerini çözmede başarılıdır ve yüksek genelleme kabiliyetine sahiptir.
2.7.1. Random Forest Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Random Forest Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_RandomForestClassifier.py # The code demonstrates the process of training Random Forest Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023,2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Random Forest Classifier model rf_model = RandomForestClassifier(n_estimators=100, random_state=42) # train the model on the entire dataset rf_model.fit(X, y) # predict classes for the entire dataset y_pred = rf_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Random Forest Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(rf_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "rf_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Random Forest Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 1.00 1.00 1.00 50
Python 2 1.00 1.00 1.00 50
Python
Python accuracy 1.00 150
Python macro avg 1.00 1.00 1.00 150
Python weighted avg 1.00 1.00 1.00 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\rf_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Random Forest Classifier model in ONNX format: 1.0
Random Forest Classifier modeli (ve ONNX versiyonu) Fisher'ın iris sınıflandırma problemini %100 doğrulukla çözmektedir.
2.7.2. Random Forest Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_RandomForestClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "rf_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="RandomForestClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_RandomForestClassifier (EURUSD,H1) model:RandomForestClassifier correct results: 100.00% Iris_RandomForestClassifier (EURUSD,H1) model=RandomForestClassifier all samples accuracy=1.000000 Iris_RandomForestClassifier (EURUSD,H1) model=RandomForestClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %100'dür ve bu da orijinal modelin doğruluğuyla eşleşmektedir.
2.7.3. Random Forest Classifier modelinin ONNX gösterimi
Şekil 21. Netron'da Random Forest Classifier modelinin ONNX gösterimi
2.8. Gradient Boosting Classifier
Gradyan artırma, en güçlü makine öğrenimi yöntemlerinden biridir ve yüksek doğruluğu ve farklı verilerle çalışma yeteneği sayesinde veri analizi, bilgisayarlı görme, doğal dil işleme ve finansal analiz dahil olmak üzere çok çeşitli alanlarda uygulama alanı bulur. Gradient Boosting Classifier, sınıflandırma görevlerini çözmek için karar ağaçlarının bir bileşimini oluşturan bir topluluk makine öğrenimi yöntemidir. Bu yöntem, yüksek doğruluk elde etme kabiliyeti ve aşırı uyuma karşı direnci nedeniyle popülerdir.
Gradient Boosting Classifier’ın prensipleri:
- Karar ağaçları topluluğu: Gradient Boosting Classifier, her ağacın bir önceki ağacın tahminlerini iyileştirmeyi amaçladığı bir karar ağaçları topluluğu oluşturur.
- Gradyan iniş: Gradyan artırma, kayıp fonksiyonunu optimize etmek için gradyan inişi kullanır. Kayıp fonksiyonunun gradyanını hesaplayarak ve tahminleri bu gradyana göre güncelleyerek sınıflandırma hatasını en aza indirir.
- Ağaç ağırlıklandırma: Bileşimdeki her ağacın bir ağırlığı vardır ve sonunda tüm ağaçlardan gelen tahminler ağırlıkları dikkate alınarak birleştirilir.
Gradient Boosting Classifier’ın avantajları:
- Yüksek doğruluk: Gradient Boosting Classifier tipik olarak yüksek sınıflandırma doğruluğu sağlar ve en güçlü makine öğrenimi yöntemlerinden biridir.
- Aşırı uyum direnci: Düzenlileştirme ve gradyan iniş kullanımı sayesinde bu yöntem, özellikle hiperparametreler ayarlanırken aşırı uyuma karşı dirençlidir.
- Farklı veri tipleriyle çalışabilme becerisi: Gradient Boosting Classifier, sayısal ve kategorik özellikler dahil olmak üzere çeşitli veri türlerini işleyebilir.
Gradient Boosting Classifier’ın sınırlamaları:
- Hesaplama karmaşıklığı: Gradient Boosting Classifier’ı eğitmek, özellikle çok sayıda ağaç veya derin ağaçlar söz konusu olduğunda hesaplama açısından yoğun olabilir.
- Yorumlanabilirlik zorlukları: Birden fazla ağacın bileşiminin karmaşıklığı nedeniyle, sonuçları yorumlamak zor olabilir.
- Küçük veri kümeleri için her zaman uygun değildir: Gradyan artırma genellikle etkili çalışma için önemli miktarda veri gerektirir ve küçük veri kümelerinde aşırı uyuma eğilimli olabilir.
Gradient Boosting Classifier, veri analizi yarışmalarında sıklıkla kullanılan ve çeşitli sınıflandırma görevlerini etkili bir şekilde çözen güçlü bir makine öğrenimi yöntemidir. Verilerdeki karmaşık doğrusal olmayan ilişkileri keşfedebilir ve hiperparametreler uygun şekilde ayarlandığında iyi bir genelleme sergiler.
2.8.1. Gradient Boosting Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Gradient Boosting Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_GradientBoostingClassifier.py # The code demonstrates the process of training Gradient Boostring Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.ensemble import GradientBoostingClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Gradient Boosting Classifier model gb_model = GradientBoostingClassifier(n_estimators=100, random_state=42) # train the model on the entire dataset gb_model.fit(X, y) # predict classes for the entire dataset y_pred = gb_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Gradient Boosting Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(gb_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "gb_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Gradient Boosting Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 1.00 1.00 1.00 50
Python 2 1.00 1.00 1.00 50
Python
Python accuracy 1.00 150
Python macro avg 1.00 1.00 1.00 150
Python weighted avg 1.00 1.00 1.00 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\gb_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Gradient Boosting Classifier model in ONNX format: 1.0
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %100'dür ve bu da orijinal modelin doğruluğuyla eşleşmektedir.
2.8.2. Gradient Boosting Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_GradientBoostingClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "gb_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="GradientBoostingClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_GradientBoostingClassifier (EURUSD,H1) model:GradientBoostingClassifier correct results: 100.00% Iris_GradientBoostingClassifier (EURUSD,H1) model=GradientBoostingClassifier all samples accuracy=1.000000 Iris_GradientBoostingClassifier (EURUSD,H1) model=GradientBoostingClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %100'dür ve bu da orijinal modelin doğruluğuyla eşleşmektedir.
2.8.3. Gradient Boosting Classifier modelinin ONNX gösterimi
Şekil 22. Netron'da Gradient Boosting Classifier modelinin ONNX gösterimi
2.9. Adaptive Boosting Classifier
AdaBoost (Adaptive Boosting) Classifier, daha güçlü bir algoritma oluşturmak için birden fazla zayıf (örneğin karar ağaçları) sınıflandırıcının sonuçlarını birleştirerek sınıflandırmayı geliştirmek için kullanılan bir topluluk makine öğrenimi yöntemidir.
AdaBoost Classifier’ın prensipleri:
- Zayıf sınıflandırıcılar topluluğu: AdaBoost, eğitim setindeki her bir örneklemin ağırlıklarını eşit başlangıç değerleri atayarak başlatır.
- Zayıf sınıflandırıcıları eğitme: AdaBoost daha sonra örneklem ağırlıklarını dikkate alarak eğitim seti üzerinde zayıf bir sınıflandırıcıyı (örneğin bir karar ağacı) eğitir. Bu sınıflandırıcı örneklemleri doğru bir şekilde sınıflandırmaya çalışır.
- Ağırlık yeniden dağıtımı: AdaBoost, yanlış sınıflandırılmış örneklemlerin ağırlıklarını artırarak ve doğru sınıflandırılmış örneklerin ağırlıklarını azaltarak örnek ağırlıklarını ayarlar.
- Bileşim oluşturma: AdaBoost, zayıf sınıflandırıcıları eğitme ve ağırlıkları yeniden dağıtma işlemini birçok kez tekrarlar. Bu zayıf sınıflandırıcıların sonuçları daha sonra her sınıflandırıcının doğruluğuna göre katkıda bulunduğu bir bileşimde birleştirilir.
AdaBoost Classifier’ın avantajları:
- Yüksek doğruluk: AdaBoost tipik olarak birkaç zayıf sınıflandırıcıyı birleştirerek yüksek sınıflandırma doğruluğu sağlar.
- Aşırı uyum direnci: AdaBoost yerleşik düzenlileştirmeye sahiptir, bu da onu aşırı uyuma karşı dirençli hale getirir.
- Çeşitli sınıflandırıcılarla çalışabilme becerisi: AdaBoost farklı temel sınıflandırıcılar kullanabilir ve böylece belirli görevlere uyarlanabilir.
AdaBoost Classifier’ın sınırlamaları:
- Aykırı değerlere hassasiyet: AdaBoost, önemli bir ağırlığa sahip olabilecekleri için verilerdeki aykırı değerlere karşı hassas olabilir.
- Karmaşık görevler için her zaman uygun değildir: Bazı karmaşık görevlerde, AdaBoost iyi sonuçlar elde etmek için çok sayıda temel sınıflandırıcı gerektirebilir.
- Temel sınıflandırıcıların kalitesine bağımlılık: AdaBoost, temel sınıflandırıcılar rastgele tahminden daha iyi olduğunda daha iyi performans gösterir.
AdaBoost Classifier, sınıflandırma görevlerini çözmek için pratikte yaygın olarak kullanılan güçlü bir makine öğrenimi algoritmasıdır. Hem ikili hem de çok sınıflı problemler için çok uygundur ve çeşitli temel sınıflandırıcılara uyarlanabilir.
2.9.1. Adaptive Boosting Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Adaptive Boosting Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_AdaBoostClassifier.py # The code demonstrates the process of training AdaBoost Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.ensemble import AdaBoostClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create an AdaBoost Classifier model adaboost_model = AdaBoostClassifier(n_estimators=50, random_state=42) # train the model on the entire dataset adaboost_model.fit(X, y) # predict classes for the entire dataset y_pred = adaboost_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of AdaBoost Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(adaboost_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "adaboost_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of AdaBoost Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.92 0.96 0.94 50
Python 2 0.96 0.92 0.94 50
Python
Python accuracy 0.96 150
Python macro avg 0.96 0.96 0.96 150
Python weighted avg 0.96 0.96 0.96 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\adaboost_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of AdaBoost Classifier model in ONNX format: 0.96
2.9.2. Adaptive Boosting Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_AdaBoostClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "adaboost_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="AdaBoostClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier sample=135 FAILED [class=1, true class=2] features=(6.10,2.60,5.60,1.40] Iris_AdaBoostClassifier (EURUSD,H1) model:AdaBoostClassifier correct results: 96.00% Iris_AdaBoostClassifier (EURUSD,H1) model=AdaBoostClassifier all samples accuracy=0.960000 Iris_AdaBoostClassifier (EURUSD,H1) model=AdaBoostClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %96'dır ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.9.3. Adaptive Boosting Classifier modelinin ONNX gösterimi
Şekil 23. Netron'da Adaptive Boosting Classifier modelinin ONNX gösterimi
2.10. Bootstrap Aggregating Classifier
Bagging (Bootstrap Aggregating) Classifier, eğitim verisinden birden fazla rastgele alt örneklem (yeniden örnekleme) oluşturmaya ve her biri üzerinde ayrı modeller oluşturmaya dayanan bir topluluk makine öğrenimi yöntemidir. Sonuçlar daha sonra modelin genelleme yeteneğini geliştirmek için birleştirilir.
Bagging Classifier’ın prensipleri:
- Alt örneklemler oluşturma: Bagging, eğitim verisinden değiştirme ile birkaç rastgele alt örneklem (yeniden örnekleme) oluşturarak başlar. Bu da aynı örneklemlerin birden fazla alt örneklemde yer alabileceği ve bazı örneklemlerin atlanabileceği anlamına gelir.
- Temel modelleri eğitme: Her bir alt örneklem üzerinde ayrı bir temel model (örneğin bir karar ağacı) eğitilir. Her model diğerlerinden bağımsız olarak eğitilir.
- Sonuçların birleştirilmesi: Tüm temel modeller eğitildikten sonra, tahminlerinin sonuçları nihai tahmini elde etmek için birleştirilir. İkili sınıflandırmada bu, çoğunluk oylaması yoluyla yapılabilir.
Bagging Classifier’ın avantajları:
- Düşük varyans: Bagging, birden fazla temel modelin sonuçlarının ortalamasını alarak modelin varyansını azaltır, bu da daha istikrarlı ve güvenilir tahminlere yol açabilir.
- Aşırı uyum azaltma: Her bir temel model farklı alt örneklemler üzerinde eğitildiğinden, Bagging modelin aşırı uyum eğilimini azaltabilir.
- Çok yönlülük: Bagging, farklı veri türlerine ve görevlere uyarlanmaya olanak tanıyan çeşitli temel modeller kullanabilir.
Bagging Classifier’ın sınırlamaları:
- Yanlılığı iyileştirmez: Bagging varyansı azaltma eğilimindedir ancak modelin yanlılığını çözmez. Temel modeller yanlı olma eğilimindeyse (örneğin, yetersiz uyum), Bagging bu sorunu düzeltmeyecektir.
- Karmaşık görevler için her zaman uygun değildir: Bazı karmaşık görevlerde, Bagging iyi sonuçlar elde etmek için çok sayıda temel model gerektirebilir.
Bagging Classifier, modelin genelleme yeteneğini artırabilen ve aşırı uyumu azaltabilen etkili bir makine öğrenimi yöntemidir. Çeşitli sınıflandırma ve regresyon görevlerini ele almak için genellikle farklı temel modellerle birlikte kullanılır.
2.10.1. Bootstrap Aggregating Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Bootstrap Aggregating Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_BootstrapAggregatingClassifier.py # The code demonstrates the process of training Bagging Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.ensemble import BaggingClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Bagging Classifier model with a Decision Tree base estimator bagging_model = BaggingClassifier(n_estimators=100, random_state=42) # train the model on the entire dataset bagging_model.fit(X, y) # predict classes for the entire dataset y_pred = bagging_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Bagging Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(bagging_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "bagging_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Bagging Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 1.00 1.00 1.00 50
Python 2 1.00 1.00 1.00 50
Python
Python accuracy 1.00 150
Python macro avg 1.00 1.00 1.00 150
Python weighted avg 1.00 1.00 1.00 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\bagging_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Bagging Classifier model in ONNX format: 1.0
Bootstrap Aggregating Classifier modeli (ve ONNX versiyonu) iris veri setini sınıflandırmada %100 doğruluk elde etmiştir.
2.10.2. Bootstrap Aggregating Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_BootstrapAggregatingClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "bagging_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="BootstrapAggregatingClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_BootstrapAggregatingClassifier (EURUSD,H1) model:BootstrapAggregatingClassifier correct results: 100.00% Iris_BootstrapAggregatingClassifier (EURUSD,H1) model=BootstrapAggregatingClassifier all samples accuracy=1.000000 Iris_BootstrapAggregatingClassifier (EURUSD,H1) model=BootstrapAggregatingClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri setindeki doğruluğu %100'dür ve bu da orijinal modelin doğruluğu ile tutarlıdır.
2.10.3. Bootstrap Aggregating Classifier modelinin ONNX gösterimi
Şekil 24. Netron'da Bootstrap Aggregating Classifier modelinin ONNX gösterimi
2.11. K-Nearest Neighbors (K-NN) Classifier
K-Nearest Neighbors (K-NN) Classifier, veri noktaları arasındaki benzerliğe dayalı sınıflandırma ve regresyon görevlerini çözmek için kullanılan bir makine öğrenimi yöntemidir. Çok boyutlu bir özellik uzayında birbirine yakın nesnelerin benzer karakteristiğe sahip olduğu ve bu nedenle benzer sınıf etiketlerine sahip olabileceği ilkesine göre çalışır.
K-NN Classifier’ın prensipleri:
- Yakınlığın belirlenmesi: K-NN Classifier, sınıflandırılacak nesne ile eğitim veri kümesindeki diğer nesneler arasındaki yakınlığı hesaplar. Bu genellikle Öklid mesafesi veya Manhattan mesafesi gibi bir mesafe metriği kullanılarak yapılır.
- Komşu sayısının seçilmesi: K parametresi, bir nesneyi sınıflandırmak için kullanılacak en yakın komşu sayısını belirler. Tipik olarak K, göreve ve verilere göre seçilir.
- Oylama: K-NN, nesnenin sınıfını belirlemek için en yakın K komşu arasında çoğunluk oylamasını kullanır. Örneğin, K komşunun çoğunluğu A sınıfına aitse, nesne de A sınıfı olarak sınıflandırılacaktır.
K-NN Classifier’ın avantajları:
- Basitlik ve sezgisellik: K-NN, anlaşılması ve uygulanması kolay, basit ve sezgisel bir yöntemdir.
- Farklı veri tipleriyle çalışabilme becerisi: K-NN, sayısal, kategorik ve metin verileri dahil olmak üzere çeşitli veri türleri için kullanılabilir.
- Değişen verilere uyarlanabilirlik: K-NN, verilerdeki değişikliklere hızlı bir şekilde adapte olabilir, bu da onu dinamik verilere sahip görevler için uygun hale getirir.
K-NN Classifier’ın sınırlamaları:
- K seçimine duyarlılık: Optimum K değerini seçmek basit olmayan bir görev olabilir. Küçük bir K aşırı uyuma yol açabilirken, büyük bir K yetersiz uyuma yol açabilir.
- Özellik ölçeklendirmesine duyarlılık. K-NN özellik ölçeklendirmesine duyarlıdır, bu nedenle veri normalizasyonu önemli olabilir.
- Hesaplama karmaşıklığı: Büyük veri kümeleri ve çok sayıda özellik için, tüm nesne çiftleri arasındaki mesafeleri hesaplamak hesaplama açısından maliyetli olabilir.
- Yorumlanabilirlik eksikliği: K-NN sonuçlarını yorumlamak, özellikle K büyük olduğunda ve çok fazla veri olduğunda zor olabilir.
K-NN Classifier, tavsiye sistemleri, metin sınıflandırma ve örüntü tanıma gibi nesne yakınlığının önemli olduğu görevlerde yararlı olabilecek bir makine öğrenimi yöntemidir. İlk veri analizi ve hızlı model prototipleme için çok uygundur.
2.11.1. K-Nearest Neighbors (K-NN) Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir K-Nearest Neighbors (K-NN) Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_KNearestNeighborsClassifier.py # The code uses the K-Nearest Neighbors (KNN) Classifier for the Iris dataset, converts the model to ONNX format, saves it, and evaluates its accuracy. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a K-Nearest Neighbors (KNN) Classifier model knn_model = KNeighborsClassifier(n_neighbors=3) # train the model on the entire dataset knn_model.fit(X, y) # predict classes for the entire dataset y_pred = knn_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of KNN Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(knn_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "knn_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of KNN Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.94 0.94 0.94 50
Python 2 0.94 0.94 0.94 50
Python
Python accuracy 0.96 150
Python macro avg 0.96 0.96 0.96 150
Python weighted avg 0.96 0.96 0.96 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\knn_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of KNN Classifier model in ONNX format: 0.96
2.11.2. K-Nearest Neighbors (K-NN) Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_KNearestNeighborsClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "knn_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="KNearestNeighborsClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier sample=73 FAILED [class=2, true class=1] features=(6.30,2.50,4.90,1.50] Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier sample=107 FAILED [class=1, true class=2] features=(4.90,2.50,4.50,1.70] Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier correct results: 96.00% Iris_KNearestNeighborsClassifier (EURUSD,H1) model=KNearestNeighborsClassifier all samples accuracy=0.960000 Iris_KNearestNeighborsClassifier (EURUSD,H1) model:KNearestNeighborsClassifier FAILED [class=2, true class=1] features=(6.30,2.50,4.90,1.50) Iris_KNearestNeighborsClassifier (EURUSD,H1) model=KNearestNeighborsClassifier batch test accuracy=0.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %96'dır ve bu da orijinal modelin doğruluğu ile tutarlıdır.
2.11.3. K-Nearest Neighbors (K-NN) Classifier modelinin ONNX gösterimi
Şekil 25. Netron'da K-Nearest Neighbors Classifier modelinin ONNX gösterimi
2.12. Decision Tree Classifier
Decision Tree Classifier, bir karar ağacının oluşturulmasına dayanan sınıflandırma görevleri için kullanılan bir makine öğrenimi yöntemidir. Bu yöntem, özellikler üzerinde bir dizi koşullu test gerçekleştirerek veri kümesini daha küçük alt gruplara ayırır ve bir nesnenin sınıfını ağaçta izlediği yola göre belirler.
Decision Tree Classifier’ın prensipleri:
- Karar ağacının oluşturulması: Başlangıçta, tüm veriler ağacın kökünde temsil edilir. Ağacın her bir düğümü için veriler, her bir alt gruptaki belirsizliği (örneğin entropi veya Gini endeksi) en aza indirmeyi amaçlayan bir özelliğin değerlerine dayalı olarak iki veya daha fazla alt gruba ayrılır.
- Yinelemeli inşa: Verileri bölme işlemi, ağaç yapraklarına ulaşana kadar yinelemeli olarak gerçekleştirilir. Yapraklar nesnelerin nihai sınıflarını temsil eder.
- Karar verme: Bir nesne ağaca girdiğinde, kökten yapraklardan birine doğru bir yol izler ve burada sınıfı o yapraktaki nesnelerin çoğunluğuna göre belirlenir.
Decision Tree Classifier’ın avantajları:
- Yorumlanabilirlik: Karar ağaçlarının yorumlanması ve görselleştirilmesi kolaydır. Sınıflandırma için kullanılan karar kuralları anlaşılabilirdir.
- Farklı veri türlerini işleme: Decision Tree Classifier hem sayısal hem de kategorik özelliklerle çalışabilir.
- Özelliğin önemi: Karar ağaçları, özelliklerin önemini değerlendirerek veri analistlerinin ve özellik mühendislerinin verileri anlamasına yardımcı olabilir.
Decision Tree Classifier’ın sınırlamaları:
- Aşırı uyum: Büyük ve derin ağaçlar aşırı uyum sağlamaya eğilimli olabilir, bu da onları yeni verilere daha az genelleştirilebilir hale getirir.
- Gürültüye karşı hassasiyet: Karar ağaçları, verilerdeki gürültü ve aykırı değerlere karşı hassas olabilir.
- Açgözlü inşa: Karar ağaçları açgözlü bir algoritma kullanılarak oluşturulur ve bu da optimum olmayan global çözümlere yol açabilir.
- Veri değişikliklerine karşı istikrarsızlık: Verilerdeki küçük değişiklikler ağaç yapısında önemli değişikliklere yol açabilir.
Decision Tree Classifier, özellikle modelin yorumlanabilirliğinin önemli olduğu ve hangi özelliklerin kararı etkilediğini anlamanız gereken durumlarda, sınıflandırma görevleri için yararlı bir makine öğrenimi yöntemidir. Bu yöntem, Random Forest ve Gradient Boosting gibi topluluk yöntemlerinde de kullanılabilir.
2.12.1. Decision Tree Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Decision Tree Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_DecisionTreeClassifier.py # The code uses the Decision Tree Classifier for the Iris dataset, converts the model to ONNX format, saves it, and evaluates its accuracy. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Decision Tree Classifier model decision_tree_model = DecisionTreeClassifier(random_state=42) # train the model on the entire dataset decision_tree_model.fit(X, y) # predict classes for the entire dataset y_pred = decision_tree_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Decision Tree Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(decision_tree_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "decision_tree_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Decision Tree Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 1.00 1.00 1.00 50
Python 2 1.00 1.00 1.00 50
Python
Python accuracy 1.00 150
Python macro avg 1.00 1.00 1.00 150
Python weighted avg 1.00 1.00 1.00 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\decision_tree_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Decision Tree Classifier model in ONNX format: 1.0
Decision Tree Classifier modeli (ve ONNX versiyonu) Fisher'ın iris veri setinin tamamını sınıflandırmada %100 doğruluk göstermiştir.
2.12.2. Decision Tree Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_DecisionTreeClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "decision_tree_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="DecisionTreeClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_DecisionTreeClassifier (EURUSD,H1) model:DecisionTreeClassifier correct results: 100.00% Iris_DecisionTreeClassifier (EURUSD,H1) model=DecisionTreeClassifier all samples accuracy=1.000000 Iris_DecisionTreeClassifier (EURUSD,H1) model=DecisionTreeClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %100'dür ve bu da orijinal modelin doğruluğuyla eşleşmektedir.
2.12.3. Decision Tree Classifier modelinin ONNX gösterimi
Şekil 26. Netron'da Decision Tree Classifier modelinin ONNX gösterimi
LogisticRegression ve LogisticRegressionCV hakkında not:
LogisticRegression ve LogisticRegressionCV, lojistik regresyon kullanarak ikili sınıflandırma için kullanılan iki sınıflandırıcıdır, ancak model parametrelerinin nasıl ayarlandığı konusunda farklılık gösterirler:
LogisticRegression:
- LogisticRegression, iki sınıftan birine ait olma olasılığını modellemek için lojistik fonksiyon kullanan bir sınıflandırıcıdır (ikili sınıflandırma).
- C (ters düzenlileştirme gücü), ceza (düzenlileştirme türü, örneğin L1 veya L2), çözücü (optimizasyon algoritması) vb. gibi özelleştirme için temel parametreler sağlar.
- LogisticRegression kullanırken, genellikle parametre değerlerini ve bunların kombinasyonlarını manuel olarak seçer ve ardından modeli veriler üzerinde eğitirsiniz.
LogisticRegressionCV:
- LogisticRegressionCV, çapraz doğrulama ve C düzenlileştirme parametresinin optimum değerinin seçilmesi için yerleşik destek sağlayan LogisticRegression'ın bir uzantısıdır.
- C'yi manuel olarak seçmek yerine, LogisticRegressionCV'ye keşfedilecek C değerlerinin bir listesini iletebilir ve çapraz doğrulama yöntemini belirtebilirsiniz (örneğin, cv parametresi aracılığıyla).
- LogisticRegressionCV, çapraz doğrulamada en iyi performansı gösteren optimum C değerini otomatik olarak seçer.
- Bu, özellikle çok fazla veriniz varsa veya hangi C değerini seçeceğinizden emin değilseniz, düzenlileştirmeyi otomatik olarak ayarlamanız gerektiğinde kullanışlıdır.
Dolayısıyla, aralarındaki temel fark parametre ayarlamasındaki otomasyon seviyesinde yatmaktadır. LogisticRegression, C değerinin manuel olarak ayarlanmasını gerektirirken LogisticRegressionCV, çapraz doğrulama yoluyla optimum C değerinin otomatik olarak seçilmesine olanak tanır. Bunlar arasındaki tercih, ihtiyaçlarınıza ve model ayarlama sürecindeki otomasyon isteğinize bağlıdır.
2.13. Logistic Regression Classifier
Logistic Regression Classifier, ikili ve çok sınıflı sınıflandırma görevleri için kullanılan bir makine öğrenimi yöntemidir. Adında "regresyon" olmasına rağmen, lojistik regresyon aslında bir nesnenin sınıflardan birine ait olma olasılığını tahmin eder. Bu olasılıklara dayanarak nihai sınıflandırma kararı verilir.
Logistic Regression Classifier’ın prensipleri:
- Olasılık tahmini: Lojistik regresyon, lojistik (sigmoid) fonksiyon kullanarak bir nesnenin belirli bir sınıfa ait olma olasılığını modeller.
- Karar sınırı: Tahmin edilen olasılıklara dayanarak, lojistik regresyon sınıfları ayıran karar sınırını belirler. Olasılık belirli bir eşiği (tipik olarak 0.5) aşarsa, nesne bir sınıfta sınıflandırılır; aksi takdirde, başka bir sınıfta sınıflandırılır.
- Parametre öğrenme: Lojistik regresyon modeli, kayıp fonksiyonunu en aza indirmek için özelliklerle ilişkili ağırlıkları (katsayıları) ayarlayarak bir eğitim veri kümesi üzerinde eğitilir.
Logistic Regression Classifier’ın avantajları:
- Basitlik ve yorumlanabilirlik: Lojistik regresyon, özelliklerin sınıf tahminleri üzerindeki etkisine ilişkin kolayca yorumlanabilir sonuçlara sahip basit bir modeldir.
- Büyük veri kümelerinde verimlilik: Lojistik regresyon, büyük veri kümelerini verimli bir şekilde işleyebilir ve bunlar üzerinde hızlı bir şekilde eğitebilir.
- Topluluk yöntemlerinde kullanım: Lojistik regresyon, istifleme gibi topluluk yöntemlerinde temel sınıflandırıcı olarak kullanılabilir.
Logistic Regression Classifier’ın sınırlamaları:
- Doğrusallık: Lojistik regresyon, özellikler ve olasılıkların logaritması arasında doğrusal bir ilişki olduğunu varsayar ve bu da karmaşık görevler için yetersiz olabilir.
- Çok sınıflı kısıtı: Orijinal haliyle lojistik regresyon ikili sınıflandırma için tasarlanmıştır, ancak çok sınıflı sınıflandırmaya genişletmek için One-vs-All (One-vs-Rest) gibi yöntemler vardır.
- Aykırı değerlere hassasiyet: Lojistik regresyon, verilerdeki aykırı değerlere karşı hassas olabilir.
Lojistik regresyon, özellikle modelin yorumlanabilirliğinin önemli olduğu ve verilerin doğrusal veya doğrusala yakın bir yapı sergilediği durumlarda, sınıflandırma görevleri için pratikte yaygın olarak kullanılan klasik bir makine öğrenimi yöntemidir. İstatistik ve tıbbi veri analizinde, faktörlerin olayların olasılığı üzerindeki etkisini değerlendirmek için de kullanılır.
2.13.1. Logistic Regression Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Logistic Regression Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_LogisticRegressionClassifier.py # The code uses the Logistic Regression Classifier for the Iris dataset, converts the model to ONNX format, saves it, and evaluates its accuracy. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Logistic Regression Classifier model logistic_regression_model = LogisticRegression(max_iter=1000, random_state=42) # train the model on the entire dataset logistic_regression_model.fit(X, y) # predict classes for the entire dataset y_pred = logistic_regression_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Logistic Regression Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(logistic_regression_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "logistic_regression_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Logistic Regression Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.98 0.94 0.96 50
Python 2 0.94 0.98 0.96 50
Python
Python accuracy 0.97 150
Python macro avg 0.97 0.97 0.97 150
Python weighted avg 0.97 0.97 0.97 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\logistic_regression_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Logistic Regression Classifier model in ONNX format: 0.9733333333333334
2.13.2. Logistic Regression Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_LogisticRegressionClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "logistic_regression_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="LogisticRegressionClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+Çıktı:
Iris_LogisticRegressionClassifier (EURUSD,H1) model:LogisticRegressionClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_LogisticRegressionClassifier (EURUSD,H1) model:LogisticRegressionClassifier sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_LogisticRegressionClassifier (EURUSD,H1) model:LogisticRegressionClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_LogisticRegressionClassifier (EURUSD,H1) model:LogisticRegressionClassifier sample=107 FAILED [class=1, true class=2] features=(4.90,2.50,4.50,1.70] Iris_LogisticRegressionClassifier (EURUSD,H1) model:LogisticRegressionClassifier correct results: 97.33% Iris_LogisticRegressionClassifier (EURUSD,H1) model=LogisticRegressionClassifier all samples accuracy=0.973333 Iris_LogisticRegressionClassifier (EURUSD,H1) model=LogisticRegressionClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %97.33'tür ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.13.3. Logistic Regression Classifier modelinin ONNX gösterimi
Şekil 27. Netron'da Logistic Regression Classifier modelinin ONNX gösterimi
2.14. LogisticRegressionCV Classifier
LogisticRegressionCV (çapraz doğrulamalı lojistik regresyon) ikili sınıflandırma için güçlü ve esnek bir yöntemdir. Bu yöntem yalnızca lojistik regresyona dayalı sınıflandırma modelleri oluşturmanıza izin vermekle kalmaz, aynı zamanda en iyi performansı elde etmek için parametreleri otomatik olarak ayarlar.
LogisticRegressionCV’nin çalışma prensipleri:
- Lojistik regresyon: LogisticRegressionCV temel olarak lojistik regresyona dayanır. Lojistik regresyon, bir nesnenin iki sınıftan birine ait olma olasılığını modellemek için kullanılan istatistiksel bir yöntemdir. Bu model, bağımlı değişkenin ikili (iki sınıflı) olduğu veya ikiliye dönüştürülebildiği durumlarda uygulanır.
- Çapraz doğrulama: LogisticRegressionCV'nin en önemli avantajı dahili çapraz doğrulamadır. Bu, C düzenlileştirme parametresi için en uygun değeri manuel olarak seçmek yerine, yöntemin otomatik olarak farklı C değerlerini denediği ve çapraz doğrulamada en iyi performansı göstereni seçtiği anlamına gelir.
- Optimum C'yi seçme: LogisticRegressionCV, modelin performansını farklı C değerlerinde değerlendirmek için bir çapraz doğrulama stratejisi kullanır. C, model düzenlileştirmenin kapsamını kontrol eden düzenlileştirme parametresidir. Küçük bir C değeri güçlü düzenlileştirmeye işaret ederken, büyük bir C değeri zayıf düzenlileştirmeye işaret eder. Çapraz doğrulama, yetersiz uyum ve aşırı uyumu dengelemek için en uygun C değerinin seçilmesine yardımcı olur.
- Düzenlileştirme: LogisticRegressionCV ayrıca L1 (lasso) ve L2 (ridge) düzenlileştirme dahil olmak üzere çeşitli düzenlileştirme türlerini de destekler. Bu düzenlileştirme türleri, modelin genellemesini iyileştirmeye ve aşırı uyumu önlemeye yardımcı olur.
LogisticRegressionCV'nin avantajları:
Otomatik parametre ayarlama: LogisticRegressionCV'nin başlıca avantajlarından biri, çapraz doğrulama kullanarak en uygun C değerini otomatik olarak seçebilmesidir. Bu, manuel model ayarlama ihtiyacını ortadan kaldırır ve verilere ve göreve odaklanmanızı sağlar.
Aşırı uyum dayanıklılığı: LogisticRegressionCV tarafından desteklenen düzenlileştirme, modelin karmaşıklığını kontrol etmeye yardımcı olur ve özellikle sınırlı verilerle aşırı uyum riskini azaltır.
Şeffaflık: Lojistik regresyon yorumlanabilir bir yöntemdir. Her bir özelliğin tahmine katkısını analiz edebilirsiniz, bu da özelliğin önemini anlamak için yararlıdır.
Yüksek performans: Lojistik regresyon, özellikle büyük hacimli verilerle hızlı ve verimli bir şekilde çalışabilir.
LogisticRegressionCV’nin sınırlamaları:
Doğrusal bağımlılıklar: LogisticRegressionCV doğrusal ve doğrusala yakın sınıflandırma problemlerini çözmek için uygundur. Özellikler ve hedef değişken arasındaki ilişki yüksek oranda doğrusal değilse, model iyi performans göstermeyebilir.
Çok sayıda özelliğin işlenmesi: Çok sayıda özellik ile lojistik regresyon, aşırı uyumu önlemek için önemli miktarda veri veya boyut azaltma teknikleri gerektirebilir.
Veri temsili bağımlılığı: Lojistik regresyonun etkinliği, verilerin nasıl temsil edildiğine ve hangi özelliklerin seçildiğine bağlı olabilir.
LogisticRegressionCV, otomatik parametre ayarlama ve aşırı uyum sağlamlığı ile ikili sınıflandırma için güçlü bir araçtır. Özellikle hızlı bir şekilde yorumlanabilir bir sınıflandırma modeli oluşturmanız gerektiğinde kullanışlıdır. Ancak, verilerin doğrusal veya doğrusala yakın bağımlılıklar sergilediği durumlarda en iyi performansı gösterdiğini unutmamak önemlidir.
2.14.1. LogisticRegressionCV Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir LogisticRegressionCV Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_LogisticRegressionCVClassifier.py # The code demonstrates the process of training LogisticRegressionCV model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import LogisticRegressionCV from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a LogisticRegressionCV model logistic_regression_model = LogisticRegressionCV(cv=5, max_iter=1000) # train the model on the entire dataset logistic_regression_model.fit(X, y) # predict classes for the entire dataset y_pred = logistic_regression_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of LogisticRegressionCV model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(logistic_regression_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "logistic_regressioncv_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of LogisticRegressionCV model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.98 0.96 0.97 50
Python 2 0.96 0.98 0.97 50
Python
Python accuracy 0.98 150
Python macro avg 0.98 0.98 0.98 150
Python weighted avg 0.98 0.98 0.98 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\logistic_regression_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of LogisticRegressionCV model in ONNX format: 0.98
2.14.2. LogisticRegressionCV Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_LogisticRegressionCVClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "logistic_regressioncv_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="LogisticRegressionCVClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_LogisticRegressionCVClassifier (EURUSD,H1) model:LogisticRegressionCVClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_LogisticRegressionCVClassifier (EURUSD,H1) model:LogisticRegressionCVClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_LogisticRegressionCVClassifier (EURUSD,H1) model:LogisticRegressionCVClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_LogisticRegressionCVClassifier (EURUSD,H1) model:LogisticRegressionCVClassifier correct results: 98.00% Iris_LogisticRegressionCVClassifier (EURUSD,H1) model=LogisticRegressionCVClassifier all samples accuracy=0.980000 Iris_LogisticRegressionCVClassifier (EURUSD,H1) model=LogisticRegressionCVClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %98'dir ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.14.3. LogisticRegressionCV Classifier modelinin ONNX gösterimi
Şekil 28. Netron'da LogisticRegressionCV Classifier modelinin ONNX gösterimi
2.15. Passive-Aggressive (PA) Classifier
Passive-Aggressive (PA) Classifier, sınıflandırma görevleri için kullanılan bir makine öğrenimi yöntemidir. Bu yöntemin ana fikri, sınıflandırma hatalarını en aza indirmek için eğitim sırasında modelin ağırlıklarını (katsayılarını) uyarlamaktır. Passive-Aggressive Classifier, çevrimiçi öğrenme senaryolarında ve verilerin zaman içinde değiştiği durumlarda faydalı olabilir.
Passive-Aggressive Classifier’ın çalışma prensipleri:
- Ağırlık uyarlaması: Passive-Aggressive Classifier, stokastik gradyan inişte olduğu gibi modelin ağırlıklarını kayıp fonksiyonunu en aza indirme yönünde güncellemek yerine, ağırlıkları mevcut örnek için sınıflandırma hatasını en aza indiren yönde uyarlar.
- Agresifliği sürdürme: Yöntem, modelin ağırlıklarının ne kadar güçlü bir şekilde uyarlanması gerektiğini belirleyen agresiflik (C) adlı bir parametreye sahiptir. Daha büyük C değerleri yöntemi uyarlamada daha agresif hale getirirken, daha küçük değerler daha az agresif hale getirir.
Passive-Aggressive Classifier’ın avantajları:
- Çevrimiçi öğrenme için uygundur: Passive-Aggressive Classifier yeni veriler geldikçe güncellenebilir, bu da onu verilerin bir akış halinde geldiği çevrimiçi öğrenme görevleri için uygun hale getirir.
- Veri değişikliklerine uyarlanabilirlik: Yöntem, modeli yeni koşullara uyarladığı için değişen verilerle iyi performans gösterir.
Passive-Aggressive Classifier’ın sınırlamaları:
- Agresiflik parametresi seçimine duyarlılık: C agresiflik parametresi için en uygun değerin seçilmesi ayarlama gerektirebilir ve veri karakteristiğine bağlıdır.
- Karmaşık görevler için her zaman uygun değildir: Passive-Aggressive Classifier, karmaşık özellik bağımlılıklarının dikkate alınması gereken karmaşık görevlerde yüksek doğruluk sağlayamayabilir.
- Ağırlıkların yorumlanması: Bu yöntem kullanılarak elde edilen model ağırlıkları, lineer veya lojistik regresyon kullanılarak elde edilen ağırlıklara kıyasla daha az yorumlanabilir olabilir.
Passive-Aggressive Classifier, değişen verilerle sınıflandırma görevleri ve modelin yeni koşullara hızlı adaptasyonunun çok önemli olduğu durumlar için uygun bir makine öğrenimi yöntemidir. Metin veri analizi, görüntü sınıflandırma vb. görevler de dahil olmak üzere çeşitli alanlarda uygulamalar bulur.
2.15.1. Passive-Aggressive (PA) Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Passive-Aggressive (PA) Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_PassiveAgressiveClassifier.py # The code uses the Passive-Aggressive (PA) Classifier for the Iris dataset, converts the model to ONNX format, saves it, and evaluates its accuracy. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import PassiveAggressiveClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Passive-Aggressive (PA) Classifier model pa_classifier_model = PassiveAggressiveClassifier(max_iter=1000, random_state=42) # train the model on the entire dataset pa_classifier_model.fit(X, y) # predict classes for the entire dataset y_pred = pa_classifier_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Passive-Aggressive (PA) Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(pa_classifier_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "pa_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Passive-Aggressive (PA) Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.96 0.92 0.94 50
Python 2 0.92 0.96 0.94 50
Python
Python accuracy 0.96 150
Python macro avg 0.96 0.96 0.96 150
Python weighted avg 0.96 0.96 0.96 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\pa_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Passive-Aggressive (PA) Classifier model in ONNX format: 0.96
2.15.2. Passive-Aggressive (PA) Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_PassiveAgressiveClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "pa_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="PassiveAgressiveClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier sample=67 FAILED [class=2, true class=1] features=(5.60,3.00,4.50,1.50] Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier sample=85 FAILED [class=2, true class=1] features=(5.40,3.00,4.50,1.50] Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_PassiveAgressiveClassifier (EURUSD,H1) model:PassiveAgressiveClassifier correct results: 96.00% Iris_PassiveAgressiveClassifier (EURUSD,H1) model=PassiveAgressiveClassifier all samples accuracy=0.960000 Iris_PassiveAgressiveClassifier (EURUSD,H1) model=PassiveAgressiveClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %96'dır ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.15.3. Passive-Aggressive (PA) Classifier modelinin ONNX gösterimi
Şekil 29. Netron'da Passive-Aggressive (PA) Classifier modelinin ONNX gösterimi
2.16. Perceptron Classifier
Perceptron Classifier, doğrusal bir ayırıcı hiperdüzleme dayalı olarak iki sınıfı ayırmak için kullanılan doğrusal bir ikili sınıflandırıcıdır. En basit ve en eski makine öğrenimi yöntemlerinden biridir ve temel ilkesi, eğitim veri kümesi üzerinde sınıflandırma doğruluğunu en üst düzeye çıkarmak için modelin ağırlıklarını (katsayılarını) eğitmektir.
Perceptron Classifier’ın çalışma prensipleri:
- Doğrusal hiperdüzlem: Perceptron, özellik uzayında iki sınıfı ayıran doğrusal bir hiperdüzlem oluşturur. Bu hiperdüzlem, modelin ağırlıkları (katsayıları) tarafından belirlenir.
- Ağırlık eğitimi: Başlangıçta, ağırlıklar rastgele veya sıfır olarak başlatılır. Daha sonra, eğitim veri kümesindeki her nesne için, model mevcut ağırlıklara dayanarak sınıfı tahmin eder ve bir hata durumunda bunları ayarlar. Eğitim, tüm nesneler doğru sınıflandırılana veya maksimum yineleme sayısına ulaşılana kadar devam eder.
Perceptron Classifier’ın avantajları:
- Basitlik: Perceptron çok basit bir algoritmadır, anlaşılması ve uygulanması kolaydır.
- Yüksek eğitim hızı: Perceptron, özellikle büyük veri kümeleri üzerinde hızlı bir şekilde eğitilebilir ve çevrimiçi öğrenme görevlerinde kullanılabilir.
Perceptron Classifier’ın sınırlamaları:
- Doğrusal ayrılabilirlik kısıtı: Perceptron yalnızca verilerin doğrusal olarak ayrılabilir olduğu durumlarda iyi çalışır. Veriler doğrusal olarak ayrılamazsa, Perceptron yüksek doğruluk elde edemeyebilir.
- Başlangıç ağırlıklarına duyarlılık: Ağırlıkların ilk seçimi algoritmanın yakınsamasını etkileyebilir. Kötü başlangıç ağırlığı seçimleri yavaş yakınsamaya veya sınıfları doğru şekilde ayıramayan bir nörona yol açabilir.
- Olasılıkları belirleyememe: Perceptron, belirli görevler için önemli olabilecek sınıf üyeliğine ilişkin olasılık hesaplamaları sağlamaz.
Perceptron Classifier, verilerin doğrusal olarak ayrılabilir olduğu basit durumlarda yararlı olabilecek ikili sınıflandırma için temel bir algoritmadır. Çok katmanlı sinir ağları gibi daha karmaşık yöntemler için de bir temel oluşturabilir. Verilerin karmaşık yapılara sahip olduğu daha karmaşık görevlerde, lojistik regresyon veya destek vektör makineleri (SVM) gibi diğer yöntemlerin daha yüksek sınıflandırma doğruluğu sağlayabileceğini unutmamak önemlidir.
2.16.1. Perceptron Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Perceptron Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_PerceptronClassifier.py # The code demonstrates the process of training Perceptron Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import Perceptron from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Perceptron Classifier model perceptron_model = Perceptron(max_iter=1000, random_state=42) # train the model on the entire dataset perceptron_model.fit(X, y) # predict classes for the entire dataset y_pred = perceptron_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Perceptron Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(perceptron_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "perceptron_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Perceptron Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 0.80 0.89 50
Python 1 0.46 1.00 0.63 50
Python 2 1.00 0.04 0.08 50
Python
Python accuracy 0.61 150
Python macro avg 0.82 0.61 0.53 150
Python weighted avg 0.82 0.61 0.53 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\perceptron_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Perceptron Classifier model in ONNX format: 0.6133333333333333
2.16.2. Perceptron Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_PerceptronClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "perceptron_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="PerceptronClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=2 FAILED [class=1, true class=0] features=(4.90,3.00,1.40,0.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=9 FAILED [class=1, true class=0] features=(4.40,2.90,1.40,0.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=10 FAILED [class=1, true class=0] features=(4.90,3.10,1.50,0.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=13 FAILED [class=1, true class=0] features=(4.80,3.00,1.40,0.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=21 FAILED [class=1, true class=0] features=(5.40,3.40,1.70,0.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=26 FAILED [class=1, true class=0] features=(5.00,3.00,1.60,0.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=31 FAILED [class=1, true class=0] features=(4.80,3.10,1.60,0.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=35 FAILED [class=1, true class=0] features=(4.90,3.10,1.50,0.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=42 FAILED [class=1, true class=0] features=(4.50,2.30,1.30,0.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=46 FAILED [class=1, true class=0] features=(4.80,3.00,1.40,0.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=102 FAILED [class=1, true class=2] features=(5.80,2.70,5.10,1.90] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=103 FAILED [class=1, true class=2] features=(7.10,3.00,5.90,2.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=104 FAILED [class=1, true class=2] features=(6.30,2.90,5.60,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=105 FAILED [class=1, true class=2] features=(6.50,3.00,5.80,2.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=106 FAILED [class=1, true class=2] features=(7.60,3.00,6.60,2.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=107 FAILED [class=1, true class=2] features=(4.90,2.50,4.50,1.70] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=108 FAILED [class=1, true class=2] features=(7.30,2.90,6.30,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=109 FAILED [class=1, true class=2] features=(6.70,2.50,5.80,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=110 FAILED [class=1, true class=2] features=(7.20,3.60,6.10,2.50] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=111 FAILED [class=1, true class=2] features=(6.50,3.20,5.10,2.00] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=112 FAILED [class=1, true class=2] features=(6.40,2.70,5.30,1.90] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=113 FAILED [class=1, true class=2] features=(6.80,3.00,5.50,2.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=114 FAILED [class=1, true class=2] features=(5.70,2.50,5.00,2.00] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=116 FAILED [class=1, true class=2] features=(6.40,3.20,5.30,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=117 FAILED [class=1, true class=2] features=(6.50,3.00,5.50,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=118 FAILED [class=1, true class=2] features=(7.70,3.80,6.70,2.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=119 FAILED [class=1, true class=2] features=(7.70,2.60,6.90,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=121 FAILED [class=1, true class=2] features=(6.90,3.20,5.70,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=122 FAILED [class=1, true class=2] features=(5.60,2.80,4.90,2.00] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=123 FAILED [class=1, true class=2] features=(7.70,2.80,6.70,2.00] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=124 FAILED [class=1, true class=2] features=(6.30,2.70,4.90,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=125 FAILED [class=1, true class=2] features=(6.70,3.30,5.70,2.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=126 FAILED [class=1, true class=2] features=(7.20,3.20,6.00,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=127 FAILED [class=1, true class=2] features=(6.20,2.80,4.80,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=128 FAILED [class=1, true class=2] features=(6.10,3.00,4.90,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=129 FAILED [class=1, true class=2] features=(6.40,2.80,5.60,2.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=131 FAILED [class=1, true class=2] features=(7.40,2.80,6.10,1.90] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=132 FAILED [class=1, true class=2] features=(7.90,3.80,6.40,2.00] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=133 FAILED [class=1, true class=2] features=(6.40,2.80,5.60,2.20] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=135 FAILED [class=1, true class=2] features=(6.10,2.60,5.60,1.40] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=136 FAILED [class=1, true class=2] features=(7.70,3.00,6.10,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=137 FAILED [class=1, true class=2] features=(6.30,3.40,5.60,2.40] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=138 FAILED [class=1, true class=2] features=(6.40,3.10,5.50,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=139 FAILED [class=1, true class=2] features=(6.00,3.00,4.80,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=140 FAILED [class=1, true class=2] features=(6.90,3.10,5.40,2.10] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=141 FAILED [class=1, true class=2] features=(6.70,3.10,5.60,2.40] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=142 FAILED [class=1, true class=2] features=(6.90,3.10,5.10,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=143 FAILED [class=1, true class=2] features=(5.80,2.70,5.10,1.90] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=144 FAILED [class=1, true class=2] features=(6.80,3.20,5.90,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=145 FAILED [class=1, true class=2] features=(6.70,3.30,5.70,2.50] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=146 FAILED [class=1, true class=2] features=(6.70,3.00,5.20,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=147 FAILED [class=1, true class=2] features=(6.30,2.50,5.00,1.90] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=148 FAILED [class=1, true class=2] features=(6.50,3.00,5.20,2.00] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=149 FAILED [class=1, true class=2] features=(6.20,3.40,5.40,2.30] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier sample=150 FAILED [class=1, true class=2] features=(5.90,3.00,5.10,1.80] Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier correct results: 61.33% Iris_PerceptronClassifier (EURUSD,H1) model=PerceptronClassifier all samples accuracy=0.613333 Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier FAILED [class=1, true class=2] features=(6.30,2.70,4.90,1.80) Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier FAILED [class=1, true class=0] features=(4.90,3.10,1.50,0.10) Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier FAILED [class=1, true class=2] features=(5.80,2.70,5.10,1.90) Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier FAILED [class=1, true class=2] features=(7.10,3.00,5.90,2.10) Iris_PerceptronClassifier (EURUSD,H1) model:PerceptronClassifier FAILED [class=1, true class=2] features=(6.30,2.90,5.60,1.80) Iris_PerceptronClassifier (EURUSD,H1) model=PerceptronClassifier batch test accuracy=0.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %61.33'tür ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.16.3. Perceptron Classifier modelinin ONNX gösterimi
Şekil 30. Netron'da Perceptron Classifier modelinin ONNX gösterimi
2.17. Stochastic Gradient Descent Classifier
SGD Classifier (Stochastic Gradient Descent Classifier), sınıflandırma görevleri için kullanılan bir makine öğrenimi yöntemidir. Doğrusal modellerin özel bir durumudur ve stokastik gradyan iniş kullanılarak eğitilen doğrusal bir sınıflandırıcıdır.
SGD Classifier’ın prensipleri:
- Doğrusal hiperdüzlem: SGD Classifier, çok boyutlu özellik uzayında iki sınıfı ayıran doğrusal bir hiperdüzlem oluşturur. Bu hiperdüzlem, modelin ağırlıkları (katsayıları) tarafından belirlenir.
- Stokastik gradyan iniş: Yöntem stokastik gradyan iniş kullanılarak eğitilir; bu da ağırlık güncellemelerinin tüm veri kümesi yerine eğitim veri kümesindeki (veya rastgele seçilen bir alt kümedeki) her nesne üzerinde gerçekleştirildiği anlamına gelir. Bu, SGD Classifier’ı büyük hacimli veriler ve çevrimiçi öğrenme için uygun hale getirir.
- Kayıp fonksiyonu: SGD Classifier, ikili sınıflandırma için lojistik kayıp fonksiyonu veya çok sınıflı sınıflandırma için softmax kayıp fonksiyonu gibi bir kayıp fonksiyonunu optimize eder.
SGD Classifier’ın avantajları:
- Eğitim hızı: SGD Classifier, stokastik gradyan iniş sayesinde özellikle büyük hacimli veriler üzerinde hızlı bir şekilde eğitilir.
- Çevrimiçi öğrenme için uygundur: Bu yöntem, verilerin akış halinde geldiği ve yeni veriler geldikçe modelin güncellenmesi gereken çevrimiçi öğrenme görevleri için çok uygundur.
SGD Classifier’ın sınırlamaları:
- Parametrelere duyarlılık: SGD Classifier, öğrenme oranı ve düzenlileştirme parametresi gibi dikkatli ayarlama gerektiren birçok hiperparametreye sahiptir.
- Ağırlık başlatma: Ağırlıkların ilk seçimi yakınsamayı ve model kalitesini etkileyebilir.
- Yerel minimumlara yakınsama: SGD yönteminin stokastik yapısı nedeniyle, kayıp fonksiyonunun yerel minimumlarına yakınsayabilir ve bu da model kalitesini etkileyebilir.
SGD Classifier, özellikle hızlı işleme gerektiren büyük hacimli verilerle uğraşırken ikili ve çok sınıflı sınıflandırma görevleri için kullanılabilen çok yönlü bir makine öğrenimi yöntemidir. Yüksek sınıflandırma doğruluğu elde etmek için hiperparametrelerini uygun şekilde ayarlamak ve yakınsamayı izlemek önemlidir.
2.17.1. Stochastic Gradient Descent Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir SGD Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_SGDClassifier.py # The code demonstrates the process of training Stochastic Gradient Descent Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.linear_model import SGDClassifier from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create an SGD Classifier model sgd_model = SGDClassifier(max_iter=1000, random_state=42) # train the model on the entire dataset sgd_model.fit(X, y) # predict classes for the entire dataset y_pred = sgd_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of SGD Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(sgd_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "sgd_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of SGD Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 0.96 1.00 0.98 50
Python 1 0.88 0.92 0.90 50
Python 2 0.96 0.88 0.92 50
Python
Python accuracy 0.93 150
Python macro avg 0.93 0.93 0.93 150
Python weighted avg 0.93 0.93 0.93 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\perceptron_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of SGD Classifier model in ONNX format: 0.9333333333333333
2.17.2. Stochastic Gradient Descent Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_SGDClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "sgd_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="SGDClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=65 FAILED [class=0, true class=1] features=(5.60,2.90,3.60,1.30] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=86 FAILED [class=0, true class=1] features=(6.00,3.40,4.50,1.60] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=124 FAILED [class=1, true class=2] features=(6.30,2.70,4.90,1.80] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=127 FAILED [class=1, true class=2] features=(6.20,2.80,4.80,1.80] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier sample=135 FAILED [class=1, true class=2] features=(6.10,2.60,5.60,1.40] Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier correct results: 93.33% Iris_SGDClassifier (EURUSD,H1) model=SGDClassifier all samples accuracy=0.933333 Iris_SGDClassifier (EURUSD,H1) model:SGDClassifier FAILED [class=1, true class=2] features=(6.30,2.70,4.90,1.80) Iris_SGDClassifier (EURUSD,H1) model=SGDClassifier batch test accuracy=0.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %93.33'tür ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.17.3. Stochastic Gradient Descent Classifier modelinin ONNX gösterimi
Şekil 31. Netron'da Stochastic Gradient Descent Classifier modelinin ONNX gösterimi
2.18. Gaussian Naive Bayes (GNB) Classifier
Gaussian Naive Bayes (GNB) Classifier, sınıflandırma görevleri için kullanılan Bayes olasılık modeline dayalı bir makine öğrenimi yöntemidir. Saf Bayes sınıflandırıcıları ailesinin bir parçasıdır ve tüm özelliklerin bağımsız olduğunu ve normal bir dağılıma sahip olduğunu varsayar.
Gaussian Naive Bayes Classifier’ın prensipleri:
- Bayes yaklaşımı: GNB, bir nesnenin her bir sınıfa ait olma olasılığını hesaplamak için Bayes teoremini kullanan Bayes sınıflandırma yaklaşımına dayanmaktadır.
- Saf yaklaşım: GNB'deki temel varsayım, tüm özelliklerin bağımsız olduğu ve normal (Gauss) bir dağılım izlediğidir. Bu varsayım saf olarak kabul edilir çünkü gerçek dünya verilerinde özellikler genellikle birbirleriyle ilişkilidir.
- Parametre hesaplaması: GNB modeli, her bir sınıftaki her bir özellik için dağılımın parametrelerini (ortalama ve standart sapma) hesaplayarak eğitim veri kümesi üzerinde eğitilir.
Gaussian Naive Bayes Classifier’ın avantajları:
- Basitlik ve eğitim hızı: GNB çok basit bir algoritmadır ve büyük veri kümelerinde bile hızlı bir şekilde eğitilir.
- Küçük ve orta ölçekli veriler için etkililik: GNB, özellikle normal özellik dağılımları varsayımı geçerli olduğunda, az veya orta sayıda özelliğe sahip sınıflandırma görevleri için etkili olabilir.
Gaussian Naive Bayes Classifier’ın sınırlamaları:
- Saf yaklaşım: Özellik bağımsızlığı ve normal dağılım varsayımı, gerçek dünya verileri için aşırı basit ve yanlış olabilir, bu da sınıflandırma doğruluğunun azalmasına neden olur.
- Aykırı değerlere hassasiyet: GNB, normal dağılımın parametrelerini önemli ölçüde çarpıtabileceğinden verilerdeki aykırı değerlere karşı hassas olabilir.
- Özellik bağımlılıklarının yakalanamaması: Bağımsızlık varsayımı nedeniyle, GNB özellikler arasındaki bağımlılıkları hesaba katmaz.
Gaussian Naive Bayes Classifier, özellikle normal özellik dağılımları varsayımı yaklaşık olarak karşılandığında, basit sınıflandırma görevleri için iyi bir seçimdir. Bununla birlikte, özelliklerin birbiriyle ilişkili olduğu veya normal bir dağılım izlemediği daha karmaşık görevlerde, destek vektör makineleri (SVM) veya gradyan artırma gibi diğer yöntemler daha doğru sonuçlar sağlayabilir.
2.18.1. Gaussian Naive Bayes (GNB) Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Gaussian Naive Bayes (GNB) Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_GaussianNaiveBayesClassifier.py # The code demonstrates the process of training Gaussian Naive Bayes Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.naive_bayes import GaussianNB from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Gaussian Naive Bayes (GNB) Classifier model gnb_model = GaussianNB() # train the model on the entire dataset gnb_model.fit(X, y) # predict classes for the entire dataset y_pred = gnb_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Gaussian Naive Bayes (GNB) Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(gnb_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "gnb_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Gaussian Naive Bayes (GNB) Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.94 0.94 0.94 50
Python 2 0.94 0.94 0.94 50
Python
Python accuracy 0.96 150
Python macro avg 0.96 0.96 0.96 150
Python weighted avg 0.96 0.96 0.96 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\gnb_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Gaussian Naive Bayes (GNB) Classifier model in ONNX format: 0.96
2.18.2. Gaussian Naive Bayes (GNB) Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_GaussianNaiveBayesClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "gnb_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="GaussianNaiveBayesClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier sample=53 FAILED [class=2, true class=1] features=(6.90,3.10,4.90,1.50] Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier sample=107 FAILED [class=1, true class=2] features=(4.90,2.50,4.50,1.70] Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier sample=120 FAILED [class=1, true class=2] features=(6.00,2.20,5.00,1.50] Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model:GaussianNaiveBayesClassifier correct results: 96.00% Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model=GaussianNaiveBayesClassifier all samples accuracy=0.960000 Iris_GaussianNaiveBayesClassifier (EURUSD,H1) model=GaussianNaiveBayesClassifier batch test accuracy=1.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %96'dır ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.18.3. Gaussian Naive Bayes (GNB) Classifier modelinin ONNX gösterimi
Şekil 32. Netron'da Gaussian Naive Bayes (GNB) Classifier modelinin ONNX gösterimi
2.19. Multinomial Naive Bayes (MNB) Classifier
Multinomial Naive Bayes (MNB) Classifier, Bayes olasılık modeline dayalı bir makine öğrenme yöntemidir ve özellikle metin işlemede sınıflandırma görevleri için kullanılır. Saf Bayes sınıflandırıcılarının varyantlarından biridir ve özelliklerin metindeki kelime sayısı gibi sayıları temsil ettiğini varsayar.
Multinomial Naive Bayes Classifier’ın prensipleri:
- Bayes yaklaşımı: MNB ayrıca, bir nesnenin her sınıfa ait olma olasılığını hesaplamak için Bayes teoremini kullanarak sınıflandırmaya yönelik Bayes yaklaşımını takip eder.
- Çok terimli dağılım varsayımı: MNB'deki temel varsayım, özelliklerin metindeki kelime sayısı gibi sayıları temsil ettiği ve çok terimli bir dağılım izlediğidir. Bu varsayım genellikle metinsel veriler için geçerlidir.
- Parametre hesaplaması: MNB modeli, her bir sınıftaki her bir özellik için dağılımın parametreleri hesaplanarak eğitim veri kümesi üzerinde eğitilir.
Multinomial Naive Bayes Classifier’ın avantajları:
- Metin işlemede etkililik: MNB, özellik sayıları varsayımı sayesinde metin sınıflandırması veya spam filtreleme gibi metinsel verilerin analiziyle ilgili görevlerde iyi performans gösterir.
- Basitlik ve eğitim hızı: Diğer saf Bayes sınıflandırıcıları gibi, MNB de büyük hacimli metin verilerinde bile hızlı bir şekilde eğitilen basit bir algoritmadır.
Multinomial Naive Bayes Classifier’ın sınırlamaları:
- Saf yaklaşım: Özelliklerin çok terimli dağılımı varsayımı, özellikle özellikler karmaşık yapılara sahip olduğunda, gerçek dünya verileri için aşırı basit ve yanlış olabilir.
- Kelime sıralamasını hesaba katamama: MNB, belirli metin analizi görevlerinde önemli olabilen metindeki kelimelerin sırasını dikkate almaz.
- Nadir kelimelere duyarlılık: MNB nadir kelimelere karşı hassas olabilir ve yetersiz sayıda olması sınıflandırma doğruluğunu azaltabilir.
Multinomial Naive Bayes Classifier, özellikle özellikler metindeki kelime sayısı gibi sayılarla ilgili olduğunda, metin analizi görevleri için kullanışlı bir yöntemdir. Metin sınıflandırma, belge kategorizasyonu ve diğer metin analizleri için doğal dil işlemede (NLP) yaygın olarak kullanılmaktadır.
2.19.1. Multinomial Naive Bayes (MNB) Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Multinomial Naive Bayes (MNB) Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_MultinomialNaiveBayesClassifier.py # The code demonstrates the process of training Multinomial Naive Bayes (MNB) Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Multinomial Naive Bayes (MNB) Classifier model mnb_model = MultinomialNB() # train the model on the entire dataset mnb_model.fit(X, y) # predict classes for the entire dataset y_pred = mnb_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Multinomial Naive Bayes (MNB) Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(mnb_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "mnb_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Multinomial Naive Bayes (MNB) Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 1.00 1.00 1.00 50
Python 1 0.94 0.92 0.93 50
Python 2 0.92 0.94 0.93 50
Python
Python accuracy 0.95 150
Python macro avg 0.95 0.95 0.95 150
Python weighted avg 0.95 0.95 0.95 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\mnb_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Multinomial Naive Bayes (MNB) Classifier model in ONNX format: 0.9533333333333334
2.19.2. Multinomial Naive Bayes (MNB) Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_MultinomialNaiveBayesClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "mnb_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="MultinomialNaiveBayesClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=69 FAILED [class=2, true class=1] features=(6.20,2.20,4.50,1.50] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=73 FAILED [class=2, true class=1] features=(6.30,2.50,4.90,1.50] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=130 FAILED [class=1, true class=2] features=(7.20,3.00,5.80,1.60] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=132 FAILED [class=1, true class=2] features=(7.90,3.80,6.40,2.00] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier sample=134 FAILED [class=1, true class=2] features=(6.30,2.80,5.10,1.50] Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier correct results: 95.33% Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model=MultinomialNaiveBayesClassifier all samples accuracy=0.953333 Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model:MultinomialNaiveBayesClassifier FAILED [class=2, true class=1] features=(6.30,2.50,4.90,1.50) Iris_MultinomialNaiveBayesClassifier (EURUSD,H1) model=MultinomialNaiveBayesClassifier batch test accuracy=0.000000
Dışa aktarılan ONNX modelinin tam iris veri kümesi üzerindeki doğruluğu %95.33'tür ve bu da orijinal modelin doğruluğuna karşılık gelmektedir.
2.19.3. Multinomial Naive Bayes (MNB) Classifier modelinin ONNX gösterimi
Şekil 33. Netron'da Multinomial Naive Bayes (MNB) Classifier modelinin ONNX gösterimi
2.20. Complement Naive Bayes (CNB) Classifier
Complement Naive Bayes (CNB) Classifier, bir sınıfın diğerinden önemli ölçüde daha yaygın olabileceği dengesiz verilerle çalışmak üzere özel olarak tasarlanmış bir saf Bayes sınıflandırıcı çeşididir. Bu sınıflandırıcı, sınıf dengesizliğini ele almak için klasik saf Bayes yöntemini uyarlar.
Complement Naive Bayes Classifier’ın prensipleri:
- Bayes yaklaşımı: Diğer Bayes sınıflandırıcıları gibi CNB de sınıflandırmada Bayes yaklaşımını izler ve bir nesnenin her bir sınıfa ait olma olasılığını hesaplamak için Bayes teoremini kullanır.
- Sınıf dengesizliğinin çözülmesi: CNB'nin birincil amacı sınıf dengesizliğini düzeltmektir. CNB, standart saf Bayes yönteminin yaptığı gibi sınıftaki özelliklerin olasılığını dikkate almak yerine, sınıf dışındaki özelliklerin olasılığını dikkate almaya çalışır. Bu, özellikle bir sınıfın diğerine göre önemli ölçüde daha az temsil edildiği durumlarda faydalıdır.
- Parametre hesaplaması: CNB modeli, sınıf dışındaki her özellik için dağılımın parametreleri hesaplanarak eğitim veri kümesi üzerinde eğitilir.
Complement Naive Bayes Classifier’ın avantajları:
- Dengesiz veriler için uygunluk: CNB, sınıfların farklı sıklığa sahip olduğu dengesiz verilerle sınıflandırma görevlerinde iyi performans gösterir.
- Basitlik ve eğitim hızı: Diğer saf Bayes sınıflandırıcıları gibi CNB de büyük hacimli veriler üzerinde bile hızlı bir şekilde eğitilen basit bir algoritmadır.
Complement Naive Bayes Classifier’ın sınırlamaları:
- Düzenlileştirme parametresi seçimine duyarlılık: Diğer Bayes yöntemlerinde olduğu gibi, düzenlileştirme parametresi için doğru değerin seçilmesi ayarlama ve değerlendirme gerektirebilir.
- Saf yaklaşım: Diğer saf Bayes sınıflandırıcıları gibi CNB de özellik bağımsızlığı varsayımını yapar ve bu varsayım bazı görevler için aşırı basit olabilir.
Complement Naive Bayes Classifier, özellikle bir sınıfın diğerinden önemli ölçüde daha az temsil edildiği durumlarda, dengesiz verilere sahip sınıflandırma görevleri için iyi bir seçimdir. Görüş analizi veya spam filtreleme gibi kelimelerin sınıflar arasında büyük ölçüde dengesiz olabileceği metin sınıflandırma görevlerinde özellikle yararlı olabilir.
2.20.1. Complement Naive Bayes (CNB) Classifier modelini oluşturmak için kod
Bu kod, iris veri kümesi üzerinde bir Complement Naive Bayes (CNB) Classifier modelinin eğitilmesi, ONNX formatına aktarılması ve ONNX modeli kullanılarak sınıflandırma yapılması sürecini göstermektedir. Ayrıca hem orijinal modelin hem de ONNX modelinin doğruluğunu değerlendirir.
# Iris_CNBClassifier.py # The code demonstrates the process of training Complement Naive Bayes (CNB) Classifier model on the Iris dataset, exporting it to ONNX format, and making predictions using the ONNX model. # It also evaluates the accuracy of both the original model and the ONNX model. # Copyright 2023, MetaQuotes Ltd. # https://www.mql5.com # import necessary libraries from sklearn import datasets from sklearn.naive_bayes import ComplementNB from sklearn.metrics import accuracy_score, classification_report from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType import onnxruntime as ort import numpy as np from sys import argv # define the path for saving the model data_path = argv[0] last_index = data_path.rfind("\\") + 1 data_path = data_path[0:last_index] # load the Iris dataset iris = datasets.load_iris() X = iris.data y = iris.target # create a Complement Naive Bayes (CNB) Classifier model cnb_model = ComplementNB() # train the model on the entire dataset cnb_model.fit(X, y) # predict classes for the entire dataset y_pred = cnb_model.predict(X) # evaluate the model's accuracy accuracy = accuracy_score(y, y_pred) print("Accuracy of Complement Naive Bayes (CNB) Classifier model:", accuracy) # display the classification report print("\nClassification Report:\n", classification_report(y, y_pred)) # define the input data type initial_type = [('float_input', FloatTensorType([None, X.shape[1]]))] # export the model to ONNX format with float data type onnx_model = convert_sklearn(cnb_model, initial_types=initial_type, target_opset=12) # save the model to a file onnx_filename = data_path + "cnb_classifier_iris.onnx" with open(onnx_filename, "wb") as f: f.write(onnx_model.SerializeToString()) # print model path print(f"Model saved to {onnx_filename}") # load the ONNX model and make predictions onnx_session = ort.InferenceSession(onnx_filename) input_name = onnx_session.get_inputs()[0].name output_name = onnx_session.get_outputs()[0].name # display information about input tensors in ONNX print("\nInformation about input tensors in ONNX:") for i, input_tensor in enumerate(onnx_session.get_inputs()): print(f"{i + 1}. Name: {input_tensor.name}, Data Type: {input_tensor.type}, Shape: {input_tensor.shape}") # display information about output tensors in ONNX print("\nInformation about output tensors in ONNX:") for i, output_tensor in enumerate(onnx_session.get_outputs()): print(f"{i + 1}. Name: {output_tensor.name}, Data Type: {output_tensor.type}, Shape: {output_tensor.shape}") # convert data to floating-point format (float32) X_float32 = X.astype(np.float32) # predict classes for the entire dataset using ONNX y_pred_onnx = onnx_session.run([output_name], {input_name: X_float32})[0] # evaluate the accuracy of the ONNX model accuracy_onnx = accuracy_score(y, y_pred_onnx) print("\nAccuracy of Complement Naive Bayes (CNB) Classifier model in ONNX format:", accuracy_onnx)
Çıktı:
Python
Python Classification Report:
Python precision recall f1-score support
Python
Python 0 0.96 1.00 0.98 50
Python 1 0.00 0.00 0.00 50
Python 2 0.51 1.00 0.68 50
Python
Python accuracy 0.67 150
Python macro avg 0.49 0.67 0.55 150
Python weighted avg 0.49 0.67 0.55 150
Python
Python Model saved to C:\Users\user\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Scripts\cnb_classifier_iris.onnx
Python
Python Information about input tensors in ONNX:
Python 1. Name: float_input, Data Type: tensor(float), Shape: [None, 4]
Python
Python Information about output tensors in ONNX:
Python 1. Name: output_label, Data Type: tensor(int64), Shape: [None]
Python 2. Name: output_probability, Data Type: seq(map(int64,tensor(float))), Shape: []
Python
Python Accuracy of Complement Naive Bayes (CNB) Classifier model in ONNX format: 0.6666666666666666
2.20.2. Complement Naive Bayes (CNB) Classifier modeliyle çalışmak için MQL5 kodu
//+------------------------------------------------------------------+ //| Iris_CNBClassifier.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" #include "iris.mqh" #resource "cnb_classifier_iris.onnx" as const uchar ExtModel[]; //+------------------------------------------------------------------+ //| Test IRIS dataset samples | //+------------------------------------------------------------------+ bool TestSamples(long model,float &input_data[][4], int &model_classes_id[]) { //--- check number of input samples ulong batch_size=input_data.Range(0); if(batch_size==0) return(false); //--- prepare output array ArrayResize(model_classes_id,(int)batch_size); //--- float output_data[]; //--- struct Map { ulong key[]; float value[]; } output_data_map[]; //--- check consistency bool res=ArrayResize(output_data,(int)batch_size)==batch_size; //--- if(res) { //--- set input shape ulong input_shape[]= {batch_size,input_data.Range(1)}; OnnxSetInputShape(model,0,input_shape); //--- set output shapeы ulong output_shape1[]= {batch_size}; ulong output_shape2[]= {batch_size}; OnnxSetOutputShape(model,0,output_shape1); OnnxSetOutputShape(model,1,output_shape2); //--- run the model res=OnnxRun(model,0,input_data,output_data,output_data_map); //--- postprocessing if(res) { //--- postprocessing of sequence map data //--- find class with maximum probability ulong output_keys[]; float output_values[]; //--- for(uint n=0; n<output_data_map.Size(); n++) { int model_class_id=-1; int max_idx=-1; float max_value=-1; //--- copy to arrays ArrayCopy(output_keys,output_data_map[n].key); ArrayCopy(output_values,output_data_map[n].value); //ArrayPrint(output_keys); //ArrayPrint(output_values); //--- find the key with maximum probability for(int k=0; k<ArraySize(output_values); k++) { if(k==0) { max_idx=0; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } else { if(output_values[k]>max_value) { max_idx=k; max_value=output_values[max_idx]; model_class_id=(int)output_keys[max_idx]; } } } //--- store the result to the output array model_classes_id[n]=model_class_id; //Print("model_class_id=",model_class_id); } } } //--- return(res); } //+------------------------------------------------------------------+ //| Test all samples from IRIS dataset (150) | //| Here we test all samples with batch=1, sample by sample | //+------------------------------------------------------------------+ bool TestAllIrisDataset(const long model,const string model_name,double &model_accuracy) { sIRISsample iris_samples[]; //--- load dataset from file PrepareIrisDataset(iris_samples); //--- test int total_samples=ArraySize(iris_samples); if(total_samples==0) { Print("iris dataset not prepared"); return(false); } //--- show dataset for(int k=0; k<total_samples; k++) { //PrintFormat("%d (%.2f,%.2f,%.2f,%.2f) class %d (%s)",iris_samples[k].sample_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3],iris_samples[k].class_id,iris_samples[k].class_name); } //--- array for output classes int model_output_classes_id[]; //--- check all Iris dataset samples int correct_results=0; for(int k=0; k<total_samples; k++) { //--- input array float iris_sample_input_data[1][4]; //--- prepare input data from kth iris sample dataset iris_sample_input_data[0][0]=(float)iris_samples[k].features[0]; iris_sample_input_data[0][1]=(float)iris_samples[k].features[1]; iris_sample_input_data[0][2]=(float)iris_samples[k].features[2]; iris_sample_input_data[0][3]=(float)iris_samples[k].features[3]; //--- run model bool res=TestSamples(model,iris_sample_input_data,model_output_classes_id); //--- check result if(res) { if(model_output_classes_id[0]==iris_samples[k].class_id) { correct_results++; } else { PrintFormat("model:%s sample=%d FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f]",model_name,iris_samples[k].sample_id,model_output_classes_id[0],iris_samples[k].class_id,iris_samples[k].features[0],iris_samples[k].features[1],iris_samples[k].features[2],iris_samples[k].features[3]); } } } model_accuracy=1.0*correct_results/total_samples; //--- PrintFormat("model:%s correct results: %.2f%%",model_name,100*model_accuracy); //--- return(true); } //+------------------------------------------------------------------+ //| Here we test batch execution of the model | //+------------------------------------------------------------------+ bool TestBatchExecution(const long model,const string model_name,double &model_accuracy) { model_accuracy=0; //--- array for output classes int model_output_classes_id[]; int correct_results=0; int total_results=0; bool res=false; //--- run batch with 3 samples float input_data_batch3[3][4]= { {5.1f,3.5f,1.4f,0.2f}, // iris dataset sample id=1, Iris-setosa {6.3f,2.5f,4.9f,1.5f}, // iris dataset sample id=73, Iris-versicolor {6.3f,2.7f,4.9f,1.8f} // iris dataset sample id=124, Iris-virginica }; int correct_classes_batch3[3]= {0,1,2}; //--- run model res=TestSamples(model,input_data_batch3,model_output_classes_id); if(res) { //--- check result for(int j=0; j<ArraySize(model_output_classes_id); j++) { //--- check result if(model_output_classes_id[j]==correct_classes_batch3[j]) correct_results++; else { PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch3[j],input_data_batch3[j][0],input_data_batch3[j][1],input_data_batch3[j][2],input_data_batch3[j][3]); } total_results++; } } else return(false); //--- run batch with 10 samples float input_data_batch10[10][4]= { {5.5f,3.5f,1.3f,0.2f}, // iris dataset sample id=37 (Iris-setosa) {4.9f,3.1f,1.5f,0.1f}, // iris dataset sample id=38 (Iris-setosa) {4.4f,3.0f,1.3f,0.2f}, // iris dataset sample id=39 (Iris-setosa) {5.0f,3.3f,1.4f,0.2f}, // iris dataset sample id=50 (Iris-setosa) {7.0f,3.2f,4.7f,1.4f}, // iris dataset sample id=51 (Iris-versicolor) {6.4f,3.2f,4.5f,1.5f}, // iris dataset sample id=52 (Iris-versicolor) {6.3f,3.3f,6.0f,2.5f}, // iris dataset sample id=101 (Iris-virginica) {5.8f,2.7f,5.1f,1.9f}, // iris dataset sample id=102 (Iris-virginica) {7.1f,3.0f,5.9f,2.1f}, // iris dataset sample id=103 (Iris-virginica) {6.3f,2.9f,5.6f,1.8f} // iris dataset sample id=104 (Iris-virginica) }; //--- correct classes for all 10 samples in the batch int correct_classes_batch10[10]= {0,0,0,0,1,1,2,2,2,2}; //--- run model res=TestSamples(model,input_data_batch10,model_output_classes_id); //--- check result if(res) { for(int j=0; j<ArraySize(model_output_classes_id); j++) { if(model_output_classes_id[j]==correct_classes_batch10[j]) correct_results++; else { double f1=input_data_batch10[j][0]; double f2=input_data_batch10[j][1]; double f3=input_data_batch10[j][2]; double f4=input_data_batch10[j][3]; PrintFormat("model:%s FAILED [class=%d, true class=%d] features=(%.2f,%.2f,%.2f,%.2f)",model_name,model_output_classes_id[j],correct_classes_batch10[j],input_data_batch10[j][0],input_data_batch10[j][1],input_data_batch10[j][2],input_data_batch10[j][3]); } total_results++; } } else return(false); //--- calculate accuracy model_accuracy=correct_results/total_results; //--- return(res); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart(void) { string model_name="CNBClassifier"; //--- long model=OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(model==INVALID_HANDLE) { PrintFormat("model_name=%s OnnxCreate error %d for",model_name,GetLastError()); } else { //--- test all dataset double model_accuracy=0; //-- test sample by sample execution for all Iris dataset if(TestAllIrisDataset(model,model_name,model_accuracy)) PrintFormat("model=%s all samples accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- test batch execution for several samples if(TestBatchExecution(model,model_name,model_accuracy)) PrintFormat("model=%s batch test accuracy=%f",model_name,model_accuracy); else PrintFormat("error in testing model=%s ",model_name); //--- release model OnnxRelease(model); } return(0); } //+------------------------------------------------------------------+
Çıktı:
Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=51 FAILED [class=2, true class=1] features=(7.00,3.20,4.70,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=52 FAILED [class=2, true class=1] features=(6.40,3.20,4.50,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=53 FAILED [class=2, true class=1] features=(6.90,3.10,4.90,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=54 FAILED [class=2, true class=1] features=(5.50,2.30,4.00,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=55 FAILED [class=2, true class=1] features=(6.50,2.80,4.60,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=56 FAILED [class=2, true class=1] features=(5.70,2.80,4.50,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=57 FAILED [class=2, true class=1] features=(6.30,3.30,4.70,1.60] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=58 FAILED [class=2, true class=1] features=(4.90,2.40,3.30,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=59 FAILED [class=2, true class=1] features=(6.60,2.90,4.60,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=60 FAILED [class=2, true class=1] features=(5.20,2.70,3.90,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=61 FAILED [class=2, true class=1] features=(5.00,2.00,3.50,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=62 FAILED [class=2, true class=1] features=(5.90,3.00,4.20,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=63 FAILED [class=2, true class=1] features=(6.00,2.20,4.00,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=64 FAILED [class=2, true class=1] features=(6.10,2.90,4.70,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=65 FAILED [class=2, true class=1] features=(5.60,2.90,3.60,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=66 FAILED [class=2, true class=1] features=(6.70,3.10,4.40,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=67 FAILED [class=2, true class=1] features=(5.60,3.00,4.50,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=68 FAILED [class=2, true class=1] features=(5.80,2.70,4.10,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=69 FAILED [class=2, true class=1] features=(6.20,2.20,4.50,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=70 FAILED [class=2, true class=1] features=(5.60,2.50,3.90,1.10] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=71 FAILED [class=2, true class=1] features=(5.90,3.20,4.80,1.80] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=72 FAILED [class=2, true class=1] features=(6.10,2.80,4.00,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=73 FAILED [class=2, true class=1] features=(6.30,2.50,4.90,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=74 FAILED [class=2, true class=1] features=(6.10,2.80,4.70,1.20] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=75 FAILED [class=2, true class=1] features=(6.40,2.90,4.30,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=76 FAILED [class=2, true class=1] features=(6.60,3.00,4.40,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=77 FAILED [class=2, true class=1] features=(6.80,2.80,4.80,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=78 FAILED [class=2, true class=1] features=(6.70,3.00,5.00,1.70] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=79 FAILED [class=2, true class=1] features=(6.00,2.90,4.50,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=80 FAILED [class=0, true class=1] features=(5.70,2.60,3.50,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=81 FAILED [class=2, true class=1] features=(5.50,2.40,3.80,1.10] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=82 FAILED [class=2, true class=1] features=(5.50,2.40,3.70,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=83 FAILED [class=2, true class=1] features=(5.80,2.70,3.90,1.20] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=84 FAILED [class=2, true class=1] features=(6.00,2.70,5.10,1.60] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=85 FAILED [class=2, true class=1] features=(5.40,3.00,4.50,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=86 FAILED [class=2, true class=1] features=(6.00,3.40,4.50,1.60] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=87 FAILED [class=2, true class=1] features=(6.70,3.10,4.70,1.50] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=88 FAILED [class=2, true class=1] features=(6.30,2.30,4.40,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=89 FAILED [class=2, true class=1] features=(5.60,3.00,4.10,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=90 FAILED [class=2, true class=1] features=(5.50,2.50,4.00,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=91 FAILED [class=2, true class=1] features=(5.50,2.60,4.40,1.20] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=92 FAILED [class=2, true class=1] features=(6.10,3.00,4.60,1.40] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=93 FAILED [class=2, true class=1] features=(5.80,2.60,4.00,1.20] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=94 FAILED [class=2, true class=1] features=(5.00,2.30,3.30,1.00] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=95 FAILED [class=2, true class=1] features=(5.60,2.70,4.20,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=96 FAILED [class=2, true class=1] features=(5.70,3.00,4.20,1.20] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=97 FAILED [class=2, true class=1] features=(5.70,2.90,4.20,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=98 FAILED [class=2, true class=1] features=(6.20,2.90,4.30,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=99 FAILED [class=0, true class=1] features=(5.10,2.50,3.00,1.10] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier sample=100 FAILED [class=2, true class=1] features=(5.70,2.80,4.10,1.30] Iris_CNBClassifier (EURUSD,H1) model:CNBClassifier correct results: 66.67% Iris_CNBClassifier (EURUSD,H1) model=CNBClassifier all samples accuracy=0.666667