Maschinelles Lernen mit XGBoostZweck
Hier ist ein Versuch meiner ersten mit App-Builder erstellten Anwendung, die die Verbindung zwischen JMP und Python nutzt, um einen komplexen Algorithmus für maschinelles Lernen zu verarbeiten.
Der Zweck dieser App besteht darin, eine in JSL geschriebene grafische Benutzeroberfläche zu starten und diese Schnittstelle mit der API für maschinelles Lernen „XGBoost“ zu verbinden.
Wie benutzt man
Ich habe die Möglichkeit implementiert, an drei Arten von Validierungsschemata zu arbeiten: Holdout / Kreuzvalidierung / Rastersuche. Sowohl Regressionen als auch Klassifizierungen wurden auf der Grundlage weniger Ziele und klassischer Metriken entwickelt.
Am Ende des Trainings wird ein Bericht mit Metrikwerten sowohl für den Trainings-/Validierungssatz als auch für den Mittelwert/die Standardentwicklung zur Kreuzvalidierung bereitgestellt. Im Falle eines Rastersuchtrainings wird der Bericht mit den besten Hyperparameter-Ergebnissen geliefert und wir können uns für die Verwendung eines frühen Stopps entscheiden. Es ist auch möglich, das Python-Modell zu exportieren, um neue Daten vorherzusagen, ohne das Modell erneut zu trainieren (dies sollte jedoch in einer Python-Umgebung erfolgen).
Sie sollten dann prüfen, ob JMP diesen Link mit Python verarbeiten kann, bevor Sie die App verwenden ...




Für die neue Version 2024:
Mit den Upgrades der Python-Bibliotheken waren viele Updates notwendig, daher habe ich die Gelegenheit genutzt, um Funktionen hinzuzufügen, die mir im praktischen Einsatz gefehlt haben, und einige Fehler zu beheben ...
- Ich erzwinge jetzt, dass Spaltennamen ein bestimmtes Muster haben, um Konflikte zwischen Python/JMP zu vermeiden (ich lösche alle Sonderzeichen, Satzzeichen und Leerzeichen), und ich nutze die neue Möglichkeit, die JMP 16 eingeführt hat, um das Dezimalformat mit Punkten zu vermeiden, um es zu vermeiden bestimmte Abstürze, die ich zuvor hatte.
- Ich überprüfe jetzt auch, ob die Antworten das richtige Format für Klassifizierungsprobleme haben (es muss numerisch sein und bei 0 beginnen, da die Änderungen an xgboost vermutlich mit Numpy-Änderungen verknüpft sind) und ich korrigiere das Klassenproblem bei binären Antworten Dies konnte in einigen Fällen bei der ersten Version des Add-Ins auftreten.
- Es wurde ein Kontrollkästchen hinzugefügt, mit dem Sie die generierten Trainings- und Testdatensätze behalten können, sodass Sie sie als CSV exportieren und auf derselben Basis arbeiten können, wenn Sie dieses Add-In mit klassischem Python (und damit anderen ML-Algorithmen für noch mehr Spaß) mischen möchten ^^ ).

- Hinzufügung des Hyperparameters „Gamma“ (auch bekannt als „min_split_loss“, d. h. eine Überprüfung des Grads der Baumregulierung durch Angabe der minimalen Reduzierung der Verlustfunktion, die erforderlich ist, um die zusätzliche Aufteilung eines Knotens zu rechtfertigen).

- Ich zeige die Hyperparameter des Modells jetzt nach der Anpassung systematisch in der gleichen Reihenfolge wie das Add-In an, um die Verknüpfung dieser Hyperparameter mit der Leistung des Modells zu erleichtern und auch das Zurückkopieren in das Add-In zu erleichtern (wenn Sie von der Rastersuche ausgehen). zum Beispiel zur Kreuzvalidierung).

- Ich rufe jetzt die Liste der vom trainierten Modell verwendeten Funktionen ab, normalisiert durch F-Score, und zeige diejenigen an, deren Normalisierung größer als 0,20 ist. Anschließend zeige ich sie in den Protokollen in einem Format an, das direkt kopiert und in JMP eingefügt werden kann (und daher leichter zu einer anderen Analyse hinzuzufügen). Diese Liste ist nach absteigendem F-Score-Wert sortiert.

- Installation einer Matplotlib-Ausgabe, sodass die Funktionsbedeutung des Modells jetzt direkt angezeigt werden kann, ohne dass ein Export und anschließender Import in eine Ide-Python-Umgebung erforderlich ist (dies war in meiner ersten Version vorgesehen, aber JMP15 stürzte anscheinend systematisch ab, sobald Matplotlib importiert wurde). Das Problem wurde in JMP 17 gelöst, ich habe es aber in JMP 16 nicht getestet.) Passt sich das Diagramm an die Anzahl der angezeigten Funktionen an (Schriftgröße und Rand).
Beispiel für einen klassischen Datensatz („Boston-Hauspreise“: https://www.kaggle.com/competitions/home-data-for-ml-course/data 

Systemkonfiguration
Add-in entwickelt und getestet mit der folgenden Systemkonfiguration:
JMP 17
Python 3.11 oder 3.12 mit Numpy, Pandas, Pathlib, Multiprocess, Scikit-Learn, xgboost
Getestet mit klassischen Datensätzen (Titanic, Boston Houses,...)

Prädiktive Modellierung und Data MiningBetreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Ok, Franck
Danke für deine Antwort.
Wie bereits erwähnt, war ich einfach neugierig. Jetzt ist es klar.
Rgds.Felice
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Hallo Felice und vielen Dank für dein Feedback!
Ich erinnere mich nicht genau, was das Problem war, aber ich hatte ein Problem bei der Verarbeitung nicht numerischer Daten während der Python-Übertragung.
Und weil es keinen Fehlerbericht gibt, sobald JMP Python-Code ausführt, ist es mir nicht gelungen, die Grundursache zu identifizieren und zu beheben. Der Python-Skriptcode für kategorial war in Ordnung, der JMP-Code auch, aber der JMP-Code und dann der Python-Code führten zum Absturz des Skripts ...
Eines Tages werde ich versuchen, darauf zurückzublicken!
Sie müssen nur die Werte umkodieren, zum Beispiel: ja = 1 und nein = 2 oder setosa = 1, versicolor = 2, virginica =3,... Es ist etwas umständlich, aber es ging darum, diesen Fehler zu umgehen
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Ciao Franck. Deine Add-Ins sind wirklich gut gemacht.
Nur eine Kuriosität. Warum muss der Antwortvariablentyp numerisch sein, wenn ich die Klassifizierungsaufgabe auswähle? Ich hatte eine kategoriale Variable erwartet (schlecht vs. gut, Basislinie vs. Experiment, Katze vs. Hund usw. usw.).
Rgds.Felice
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Kein Problem, Franck. Es ist ein toller Beitrag, danke fürs Teilen.
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Danke schön!
Ja, ich hoffe auch, dass die Python-Unterstützung mit der Zeit verbessert wird.
Was die Schnittstelle angeht, tut mir leid, dass ich dieses Add-In fast ausschließlich in meiner Freizeit erstellt habe, aber da die JMP-Lizenz von meinem Unternehmen bezahlt wird, bin ich der Meinung, dass die Veröffentlichung des Quellcodes von meinem Arbeitgeber validiert werden muss, der möchte, dass dieser Quellcode privat bleibt.
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Das ist toll! Danke fürs Teilen*
Was Python in Windows betrifft, funktioniert Anaconda mit Python 3.6 sofort mit JMP 15, Sie müssen jedoch alle Pakete aktualisieren, da es sich um ein 2 Jahre altes Paket handelt. Ich hoffe, dass JMP seine Python-Unterstützung in den nächsten Versionen verbessert.
(*Hinweis) Die von Ihnen erstellte Schnittstelle kann für andere Python-APIs verwendet werden. Haben Sie den Quellcode auch veröffentlicht?
Grüße.
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Hallo Ruth
Es tut mir sehr leid, ich habe keine Ahnung, was passiert: Ich vermutete ein Problem mit der Art und Weise, wie Mac OS Verzeichnisse anders behandelt als Windows, aber der Absturz liegt im Python-Teil und nicht davor. Außerdem kommt es zu dem Absturz, obwohl Sie die Dateiexportoption nicht verwendet haben
Möglicherweise hängt es, wie Sie erwähnt haben, mit einem Paketproblem zusammen. Ich werde versuchen, meine Pakete so schnell wie möglich zu aktualisieren, um zu überprüfen, ob dieselben Pakete unter Windows 10 noch in Ordnung sind oder nicht.
Vielen Dank, dass Sie mein Add-In ausprobiert haben! 
Franck
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Vielen Dank, dass Sie sich mein Problem angesehen haben. @Franck_R .Meine Python-Installation funktioniert mit JMP für anderen Code (einschließlich des von Ihnen vorgeschlagenen Testcodes), aber möglicherweise liegt immer noch ein Problem mit einem Paket oder einer anderen fehlenden Komponente vor, die für Ihr Add-In benötigt wird und die ich noch nicht entdeckt habe. Ich bin im Moment völlig ratlos. Wenn ich Gelegenheit dazu habe, werde ich versuchen, dies auf einem Windows-Rechner einzurichten, um es noch einmal zu versuchen.
Nochmals vielen Dank, dass Sie dies in der Community veröffentlicht haben – es ist eine sehr nützliche Anwendung!
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Derselbe Datensatz ohne Probleme auf meinem Computer:

Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Hallo,
Ja, das Problem liegt tatsächlich im Python-Teil. Tut mir leid ...
Es ist seltsam, weil der Python-Code überhaupt nicht ausgeführt wurde: Der Code ist vor dem „try“-Befehl abgestürzt! Ich füge diese Art von Absturz nie hinzu ...
Es ist jedoch schwierig, Ihr Protokoll zu debuggen, da JMP keine der Python-Fehlermeldungen schreibt. Es gibt lediglich den Python-Code ohne Erklärungen aus. Wenn wir Python mit JMP verwenden und Python auf ein Problem stößt, gibt es keinen expliziten Fehlercode: Aus diesem Grund musste ich den gesamten Python-Code außerhalb von JMP entwickeln und diesen Code dann in JMP integrieren ...
Dieser Datensatz wird auf meinem Computer gut verarbeitet, aber ich arbeite unter Windows 10 und mit Python 3.7
Das erste, was überprüft werden muss, ist, dass JMP 15.1 mit Python 3.8 umgehen kann. Ich bin mir wirklich nicht sicher, ob das der Fall ist (es gab beispielsweise einige Schwierigkeiten mit Python 3.7, siehe). https://community.jmp.com/t5/Discussions/JMP-14-Python-abilities-working-Im-confused/td-p/184515
Versuchen Sie, den Beispielcode im Skriptindex auszuführen:
Namen standardmäßig hier( 1 );
Python Init();
Python-Senden(
„\[
str = 'Der schnelle Braunfuchs springt über den faulen Hund';
a = 200;
]\"
);
getStr = Python Get( str );
getNum = Python Get( a );
Show( getStr, getNum );
Python-Term();
Gibt es dann einen fehlenden Wert in Ihrem Datensatz? (Ich überprüfe den Datensatz nicht auf fehlende Werte und er kann deshalb abstürzen, wenn es sich um einen überarbeiteten Boston-Datensatz mit einigen fehlenden Werten handelt.)
Ich bin mir auch nicht sicher, ob mein Code mit Mac OS zurechtkommt, weil ich das nicht überprüfen kann und die Python-Integration möglicherweise etwas anders sein kann als die Windows-Integration ...
Betreff: Maschinelles Lernen mit XGBoost in einem JMP-Add-In (JMP-App + Python)Vielen Dank, dass Sie dies zur Verfügung gestellt haben! Ich versuche, es mit den Boston Housing-Daten auszuführen, leicht angepasst, um eine entsprechende Validierungsspalte und eine numerische ID-Spalte sowie die Variable „chas“ als numerischen Indikator einzuschließen. (Siehe Screenshot unten.) Ich verwende JMP Pro 15.1 unter MacOS 10.15.3 mit Python 3.8.2 und Numpy 1.18.2, Pandas 1.0.3, Scikit-Learn 0.23.1 und XGBoost 1.1.0. Ich kopiere das Protokoll unten. Offensichtlich funktioniert etwas eine Weile, aber dann stürzt Python ab. Am Ende erhalte ich die Warnung „Send erwartet ein skriptfähiges Objekt beim Zugriff oder bei der Auswertung von ‚Send‘.“ Ich kann mir vorstellen, dass dieser Fehler auftritt, weil Python abgestürzt ist und das zu sendende Objekt nicht erstellt hat.
Irgendwelche Ideen, was schief laufen könnte? Ich bin kein Scripting-Experte, aber zusätzlich zu dieser Schwäche verstehe ich einige der französischen Ausgaben im Protokoll nicht 
Danke!
Ruth
"*** DEBUG Report: Start"
"******* Fonction update OK"
"**** Valeurs initialisées"
2
"**** OK avant lancement algo"
"***** La table de travail est:"
DataTable("Boston Housing.jmp")
/Library/Frameworks/Python.framework/Versions/3.8/lib/python38.zip
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/lib-dynload
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/aeosa
/**********/
# Partie import des biblios Python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
from xgboost import XGBRegressor
from joblib import dump, load
from pathlib import Path
# Optionnel
#from xgboost import plot_tree
# On affiche pas les warnings python
import warnings
warnings.simplefilter("ignore")
try:
# On créé des DataFrame avec les Data Table JMP
data_frame_train = pd.DataFrame(dt_train)
data_frame_valid = pd.DataFrame(dt_valid)
data_frame_test = pd.DataFrame(dt_test)
# On récupère l'index du DF avec Id pour le réutiliser dans la génération du dataframe de la réponse
Id_train = data_frame_train[colId]
Id_valid = data_frame_valid[colId]
Id_test = data_frame_test[colId]
# On fixe l'index du DF avec Id
data_frame_train.set_index(colId)
data_frame_valid.set_index(colId)
data_frame_test.set_index(colId)
# On conserve la table train non modifiée
data_frame_train_initial = pd.DataFrame(dt_train)
# On fixe l'index du DF avec Id
data_frame_train_initial.set_index(colId)
# On fixe le y
y_train = data_frame_train[colY]
y_valid = data_frame_valid[colY]
y_test = data_frame_test[colY]
# On fixe les facteurs: ce sont ici les colonnes récupérées de la liste des colonnes de JMP donc les features contenus dans liste_colonne
X_train = data_frame_train[liste_colonne]
X_valid = data_frame_valid[liste_colonne]
X_test = data_frame_test[liste_colonne]
# MODELISATION
# On définit le modèle comme étant un régresseur XGBoost
# my_model = XGBRegressor(n_estimators=100, learning_rate=0.05, random_state=0)
#param_dist = {'n_estimators':2,'learning_rate'=0.05,'random_state'=0 }
# ATTENTION: le transfert de variable est piégeux car un integer est converti en decimal
# Or dans cette list de paramètre XGBoost ne tolère pas tout le temps des décimals, il faut donc convertir en Integer avec int()
# Conversion des paramètres:
Int_Nb_Iterations = int(Nb_Iterations)
Int_Max_Depth = int (Max_Depth)
Int_Min_Child = int (Min_Child)
# Assignation des paramètres
max_depth = Int_Max_Depth
min_child_weight = Int_Min_Child
subsample = Sub_Sample
colsample_bytree = Col_Sample
objective = Objective
num_estimators = Int_Nb_Iterations
learning_rate = Learning_Rate
my_model = XGBRegressor(max_depth=max_depth,min_child_weight=min_child_weight,subsample=subsample,colsample_bytree=colsample_bytree,objective=objective,n_estimators=num_estimators,learning_rate=learning_rate)
# On fitte le modèle
my_model.fit(X_train, y_train)
# On récupère les prédictions sur le set de la table train partie validation
predictions_sur_train_XGBoost = my_model.predict(X_train)
predictions_sur_validation_XGBoost = my_model.predict(X_valid)
# Calculate Score
#score_train = mean_absolute_error(predictions_sur_train_XGBoost, y_train)
#score_valid = mean_absolute_error(predictions_sur_validation_XGBoost, y_valid)
if Type_Score == 'MAE': score_train = mean_absolute_error(predictions_sur_train_XGBoost, y_train); score_valid = mean_absolute_error(predictions_sur_validation_XGBoost, y_valid)
elif Type_Score == 'RMSE': score_train = mean_squared_error(predictions_sur_train_XGBoost, y_train) ; score_valid = mean_squared_error(predictions_sur_validation_XGBoost, y_valid)
else: print("toto")
# Export prévisions sur table train et validate
output_train_XGBoost = pd.DataFrame({colY: predictions_sur_train_XGBoost,colId : Id_train})
output_validation_XGBoost = pd.DataFrame({colY: predictions_sur_validation_XGBoost, colId : Id_valid })
# On concatene les dataframe train et valid afin de réentrainer le modèle sur l'ensemble des données pour prédire le y_test
X_full = pd.concat([X_train, X_valid])
y_full = pd.concat([y_train, y_valid])
# On réentraine le modèle sur train + validate et on l'exporte sur test
my_model.fit(X_full, y_full)
predictions_sur_test_XGBoost = my_model.predict(X_test)
output_test_XGBoost = pd.DataFrame({colY: predictions_sur_test_XGBoost,colId : Id_test})
# ------------------------- Essais de sortie graphique: plantage car JMP 15.1 n'est pas fonctionnel
# fit = alg.fit(dtrain[ft_cols].values, dtrain['y'].values)
# ft_weights = pd.DataFrame(fit.feature_importances_, columns=['weights'], index=ft_cols)
# model = xgb.train(params, d_train, 1000, watchlist)
# fig, ax = plt.subplots(figsize=(12,18))
# xgb.plot_importance(model, max_num_features=50, height=0.8, ax=ax)
# plt.show()
# ft_weights = my_model.feature_importances_
#import matplotlib.pylab as plt
#from matplotlib import pyplot
#from xgboost import plot_importance
#plot_importance(model, max_num_features=10) # top 10 most important features
#plt.show()
# -------------------------
if int(File_Save_Check) == 1:
data_folder = Path(File_Save_Directory)
file_to_save = data_folder / File_Save_Name
dump(my_model, file_to_save)
except:
print("python has crashed check your parameters")
/**********/
Send Expects Scriptable Object in access or evaluation of 'Send'


Betreff: Maschinelles Lernen mit XGBoostHallo
Ich habe das Add-In hinsichtlich der Kompatibilität mit neuen Python-Versionen + neuen Funktionen + Fehlerkorrekturen aktualisiert
Betreff: Maschinelles Lernen mit XGBoostIch kann den Grund kommentieren, warum Sie mit Matplotlib abstürzten. Sowohl die Hauptfenster-Ereignisschleife von JMP als auch die Hauptfenster-Ereignisschleife von matplotlib kollidieren. Da die gemeinsam genutzte Python-Bibliothek in den Prozessraum von JMP geladen wird, verfügt JMP bereits über ein Hauptfenster. Matplotlib, das mit üblichen Methoden aufgerufen wird, geht davon aus, dass es die Hauptfensterschleife hat. Es hängt ganz vom gewählten Matplolib-Backend ab. Nach 14 haben wir das Maptplotlib-Backend auf das nicht interaktive AGG-Backend umgestellt und es ist vollständig nutzbar, indem wir Matplotlib einfach anweisen, die Abbildung zu speichern, anstatt sie anzuzeigen. Das andere Problem, das Ihnen vielleicht aufgefallen ist, ist, dass JMP nicht in allen Fällen abstürzte, sondern stattdessen beendet wurde. Das zuletzt geschlossene Matplotib-Fenster rief einen C-Level-Exit() auf, der außerhalb der Kontrolle von JMP lag. JMP 18.0 ist etwas nachsichtiger, wenn es Matplotlib unter Windows zulässt, ohne es zum AGG-Backend zu zwingen, aber auf dem Mac stürzt das standardmäßige Cocoa-Backend tatsächlich immer noch ab, ich habe einen offenen Fehlerbericht mit Matplotlib-Entwicklern. Auf dem Mac hatte ich mit einem PySide- oder PyQt-Backend einige Erfolge, aber das ist immer noch ein Glücksfall. Der beste Weg, Matplotlib aufzurufen, besteht darin, die Figur als Bild zu speichern.
Betreff: Maschinelles Lernen mit XGBoostHallo Paul,
Vielen Dank für die Nachbereitung und Erklärungen! Ich freue mich zu sehen, dass die Integration mit Python in JMP 18 fortgesetzt wird ...