Aprendizaje automático con XGBoostObjetivo
Aquí hay un intento de mi primera aplicación creada con app-builder usando la conexión entre JMP y Python para manejar un algoritmo complejo de aprendizaje automático.
El propósito de esta aplicación es iniciar una interfaz gráfica de usuario escrita en jsl y conectar esa interfaz con la API de aprendizaje automático "XGBoost".
Cómo utilizar
He implementado la posibilidad de trabajar en 3 tipos de esquema de validación: reserva / validación cruzada / búsqueda en cuadrícula. Tanto las regresiones como las clasificaciones se han desarrollado sobre pocos objetivos y métricas clásicas.
Al final de la capacitación, se proporciona un informe con el valor de las métricas tanto en el conjunto de entrenamiento/validación como en el desarrollo medio/estándar para la validación cruzada. En el caso de un entrenamiento de búsqueda en cuadrícula, el informe se proporciona con los mejores resultados de hiperparámetros y podemos optar por utilizar la detención anticipada. También es posible exportar el modelo de Python para predecir nuevos datos sin volver a entrenar el modelo (pero debe hacerse en un entorno de Python).
Luego debes verificar que JMP pueda manejar ese enlace con Python antes de usar la aplicación...




Para la versión Nueva 2024:
Se necesitaron muchas actualizaciones con las actualizaciones de las bibliotecas de Python, así que aproveché la oportunidad para agregar características que me faltaban en el uso práctico y corregir algunos errores...
- Ahora fuerzo que los nombres de las columnas tengan un patrón determinado para evitar cualquier conflicto entre python/JMP (borro todos los caracteres especiales, puntuación, espacios) y aprovecho la nueva posibilidad introducida por JMP 16 para forzar el formato decimal con puntos para evitar ciertos accidentes que tuve anteriormente.
- Ahora también estoy verificando que las respuestas estén en el formato correcto para problemas de clasificación (debe ser numérico y comenzar en 0 desde los cambios realizados en xgboost, presumiblemente vinculados a cambios numpy) y estoy corrigiendo el problema de clase en respuestas binarias. eso podría ocurrir en algunos casos con la primera versión del complemento.
- Se agregó una casilla de verificación para permitirle conservar los conjuntos de datos de prueba y entrenamiento generados para que pueda exportarlos como csv y trabajar de la misma manera cuando desee combinar este complemento con Python clásico (y, por lo tanto, otros algoritmos de aprendizaje automático para divertirse aún más ^^ ).

- Adición del hiperparámetro 'Gamma' (también conocido como 'min_split_loss', es decir, una verificación del grado de regularización del árbol, especificando la reducción mínima en la función de pérdida requerida para justificar la división adicional de un nodo).

- Ahora muestro sistemáticamente los hiperparámetros del modelo después del ajuste, en el mismo orden que el complemento, para que sea más fácil asociar estos hiperparámetros con el rendimiento del modelo y también para que sea más fácil copiarlos nuevamente en el complemento (cuando pasas de la búsqueda en cuadrícula para validación cruzada, por ejemplo).

- Ahora recupero la lista de características utilizadas por el modelo entrenado, normalizadas por F-Score, y muestro aquellas cuya normalización es mayor que 0,20, luego las muestro en los registros en un formato que se puede copiar y pegar directamente en JMP (y por lo tanto, es más fácil agregarlo a otro análisis). Esta lista está ordenada por valor F-Score decreciente.

- Instalación de una salida de matplotlib para que la importancia de las características del modelo ahora se pueda mostrar directamente sin tener que exportar y luego importar a un ide python (esto estaba previsto en mi versión inicial, pero JMP15 fallaba sistemáticamente tan pronto como se importaba matplotlib, esto parece (resuelto en JMP 17 pero no lo he probado en JMP 16), el gráfico se adapta al número de características mostradas (tamaño de fuente y margen).
Ejemplo de un conjunto de datos clásico ("precios de la vivienda en Boston": https://www.kaggle.com/competitions/home-data-for-ml-course/data 

Configuración del sistema
Complemento desarrollado y probado utilizando la siguiente configuración del sistema:
JMP 17
Python 3.11 o 3.12 con numpy, pandas, pathlib, multiproceso, scikit-learn, xgboost
Probado utilizando un conjunto de datos clásico (titanic, casas de boston,...)

Modelado predictivo y minería de datosRe: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)ok franck
gracias por su respuesta.
Como ya sead, solo tenía curiosidad por saberlo. Ahora esta claro.
reg.feliz
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)Hola Felice y gracias por tus comentarios!
No recuerdo exactamente cuál era el problema, pero tuve un problema para procesar datos no numéricos durante la transferencia de python.
Y debido a la falta de un informe de error tan pronto como JMP ejecuta el código Python, no logré identificar la causa raíz y resolverla. El código de secuencia de comandos de Python para categorial estaba bien, el código JMP también, pero el código JMP y luego el código de Python estaban bloqueando la secuencia de comandos...
¡Algún día tendré que intentar mirar hacia atrás!
Solo hay que recodificar los valores por ejemplo: si = 1 y no = 2 o setosa = 1, versicolor = 2, virginica = 3,... Es un poco engorroso, pero fue para evitar este error.
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)Chao Franck. Tus complementos están muy bien hechos.
Solo una curiosidad. ¿Por qué cuando elijo la tarea de clasificación se requiere que el tipo de variable de respuesta sea numérico? Esperaba una variable categórica (malo frente a bueno, línea de base frente a experimento, gato frente a perro, etc., etc.)
reg.feliz
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)Franck no hay problema. Es un gran aporte, gracias por compartir.
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)¡Gracias!
Sí, también espero que la compatibilidad con Python mejore con el tiempo.
Para la interfaz, lo siento, hice este complemento casi en su totalidad en mi tiempo libre, pero con la licencia de JMP pagada por mi empresa, considero que la publicación del código fuente debe ser validada por mi empleador que desea que este código fuente permanezca privado.
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)¡Esto es genial! Gracias por compartirlo
Con respecto a Python en Windows, Anaconda con Python 3.6 funciona de manera inmediata con JMP 15, pero debe actualizar todos los paquetes, ya que es un paquete de 2 años de antigüedad. Espero que JMP mejore su compatibilidad con Python en las próximas versiones.
(*nota) La interfaz que ha creado se puede usar para otras API de Python. ¿Has publicado el código fuente también?
Saludos.
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)hola rut
Lo siento mucho, no tengo idea de lo que está sucediendo: sospeché que había algún problema con la forma en que Mac OS maneja el directorio de manera diferente a Windows, pero el bloqueo se encuentra en la parte de python y no antes de eso. Además, el bloqueo ocurre cuando no usó la opción de exportación de archivos
Tal vez esté relacionado con un problema de paquete como mencionas. Intentaré actualizar mis paquetes lo antes posible para verificar si los mismos paquetes en Windows 10 todavía están bien o no.
¡Gracias por probar mi complemento! 
franco
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)Gracias por mirar mi problema, @Franck_R .Mi instalación de Python funciona con JMP para otro código (incluido el código de prueba que sugirió), pero aún puede haber un problema con un paquete o algún otro componente faltante necesario para su complemento que aún no he descubierto. Estoy totalmente perplejo por ahora. Cuando tenga la oportunidad, intentaré configurar esto en una máquina con Windows para intentarlo de nuevo.
Gracias de nuevo por publicar esto en la comunidad: ¡es una aplicación muy útil!
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)El mismo conjunto de datos sin problemas en mi computadora:

Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)Hola,
Sí, el problema está en la parte de python, lo siento por eso...
Es extraño porque el código python no se ha ejecutado en absoluto: ¡el código se bloqueó antes del comando "intentar"! Nunca agrego ese tipo de accidente....
Pero es complicado depurar su registro porque JMP no escribe ninguno de los mensajes de error de python... simplemente arroja el código de python sin explicaciones... Cuando usamos python con JMP y python encuentra un problema, no hay un código de error explícito: tuve que desarrollar todo el código de python fuera de JMP y luego integrar ese código en JMP por eso...
Este conjunto de datos se maneja bien en mi computadora, pero trabajo en Windows 10 y con Python 3.7
Lo primero que debe verificar es que JMP 15.1 puede manejar python 3.8. Realmente no estoy seguro de que sea el caso (hubo algunas dificultades con python 3.7, por ejemplo, vea https://community.jmp.com/t5/Discussions/JMP-14-Python-abilities-working-Im-confused/td-p/184515
intente ejecutar el código de ejemplo en el índice de secuencias de comandos:
Nombres predeterminados hasta aquí ( 1 );
Inicialización de Python();
Enviar Python (
"\[
str = 'El veloz zorro marrón salta sobre el perro perezoso';
a = 200;
]\"
);
getStr = Python Obtener (cadena);
getNum = Python Obtener (a);
Mostrar( obtenerCadena, obtenerNum );
Término de Python ();
Entonces, ¿falta algún valor en su conjunto de datos? (No verifico el valor faltante en el conjunto de datos y puede fallar debido a eso si es un conjunto de datos de Boston reelaborado con algunos valores faltantes)
Tampoco estoy seguro de que mi código pueda manejar Mac OS porque no tengo forma de verificarlo y la integración de python puede ser quizás un poco diferente a la de Windows ...
Re: Aprendizaje automático con XGBoost en un complemento JMP (aplicación JMP + python)¡Gracias por hacer esto disponible! Estoy intentando ejecutarlo en los datos de Vivienda de Boston, ajustado ligeramente para incluir una columna de validación adecuada y una columna de identificación numérica y con la variable "chas" como indicador numérico. (Vea la captura de pantalla a continuación). Estoy ejecutando JMP Pro 15.1 en MacOS 10.15.3 con Python 3.8.2 y numpy 1.18.2, pandas 1.0.3, scikit-learn 0.23.1 y XGBoost 1.1.0. Estoy copiando el registro a continuación. Obviamente, algo funciona durante un tiempo, pero luego Python falla. Al final, recibo la advertencia de que "Enviar espera un objeto programable en acceso o evaluación de 'Enviar'". Me imagino que este error ocurre porque Python se bloqueó y no creó el objeto para enviar.
¿Alguna idea sobre lo que podría estar yendo mal? No soy un experto en secuencias de comandos, pero además de esta debilidad, no comprendo algunos de los resultados en francés en el registro;)
¡Gracias!
Piedad
"*** 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'


Re: Aprendizaje automático con XGBoostHola
He actualizado el complemento con compatibilidad con nuevas versiones de Python + nuevas funciones + correcciones de errores
Re: Aprendizaje automático con XGBoostPuedo comentar el motivo por el que tuviste fallos con matplotlib. Tanto el bucle de eventos de la ventana principal de JMP como el bucle de eventos de la ventana principal de matplotlib chocan. Dado que la biblioteca compartida de Python está cargada en el espacio de proceso de JMP, JMP ya tiene una ventana principal. Matplotlib llamado por métodos habituales cree que tiene el bucle de la ventana principal. Depende completamente del backend matplolib elegido. Después de 14, forzamos el backend de maptplotlib al backend no interactivo 'AGG' y es completamente utilizable simplemente diciéndole a matplotlib que guarde la figura en lugar de mostrarla. El otro problema que quizás hayas visto es que JMP no fallaba en todos los casos, sino que se salía. La última ventana cerrada de matplotib estaba llamando a una salida de nivel C () fuera del control de JMP. JMP 18.0 es un poco más indulgente, si permite matplotlib en Windows sin forzarlo al backend AGG, pero en Mac el backend Cocoa predeterminado todavía falla, tengo un informe de error abierto con los desarrolladores de matplotlib. En Mac he tenido cierto éxito con un backend PySide o PyQt, pero aún así es impredecible. La mejor manera de llamar a matplotlib es guardar la figura como una imagen.
Re: Aprendizaje automático con XGBoostHola Pablo,
¡Gracias por el seguimiento y las explicaciones! Me alegra ver que la integración con Python continúa en JMP 18...