使用 XGBoost 进行机器学习目的
这是我使用 app-builder 构建的第一个应用程序的尝试,使用 JMP 和 Python 之间的连接来处理复杂的机器学习算法。
该应用程序的目的是启动一个用 jsl 编写的图形用户界面,并将该界面与“XGBoost”机器学习 API 连接。
如何使用
我已经实现了使用 3 种类型的验证方案的可能性:保留/交叉验证/网格搜索。回归和分类都是基于很少的目标和经典指标而开发的。
训练结束时,会提供一份报告,其中包含训练/验证集或用于交叉验证的平均值/标准开发的指标值。在网格搜索训练的情况下,报告会提供最佳的超参数结果,我们可以选择使用早期停止。也可以导出 python 模型来预测新数据,而无需再次训练模型(但应该在 python 环境中完成)
然后,您应该在使用该应用程序之前检查 JMP 是否可以使用 Python 处理该链接...




对于 2024 年新版本:
随着python库的升级,需要进行很多更新,所以我借此机会添加了我在实际使用中缺少的功能并修复了相当多的错误......
- 我现在强制列名称具有某种模式,以避免 python/JMP 之间的任何冲突(我清除所有特殊字符、标点符号、空格),并且我利用 JMP 16 引入的新可能性来强制使用带点的十进制格式,以避免我以前遇到过的某些崩溃。
- 我现在还在检查分类问题的响应格式是否正确(它必须是数字,并且从 0 开始,因为对 xgboost 进行的更改,可能与 numpy 更改相关),并且我正在纠正二进制响应的类问题在某些情况下,该插件的第一个版本可能会发生这种情况。
- 添加了一个复选框,允许您保留生成的训练和测试数据集,以便您可以将它们导出为 csv,并在您想要将此插件与经典 python 混合使用时在相同的基础上工作(因此其他 ML 算法会更有趣 ^^ )。

- 添加“Gamma”超参数(又名“min_split_loss”,即通过指定证明节点额外分裂所需的损失函数的最小减少量来检查树正则化程度)。

- 现在,我在拟合后以与插件相同的顺序系统地显示模型的超参数,以便更轻松地将这些超参数与模型的性能相关联,也更容易将它们复制回插件(当您从网格搜索进入时)例如,交叉验证)。

- 我现在检索训练模型使用的特征列表,并通过 F-Score 进行标准化,并显示标准化大于 0.20 的特征,然后以可直接复制并粘贴到 JMP 中的格式将其显示在日志中(以及因此更容易添加到另一个分析中)。此列表按 F-Score 值递减排序。


系统配置
使用以下系统配置开发和测试插件:
JMP 17
Python 3.11 或 3.12 与 numpy、pandas、pathlib、多进程、scikit-learn、xgboost
使用经典数据集(泰坦尼克号、波士顿房屋等)进行测试

预测建模和数据挖掘回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)好的弗兰克
感谢您的回复。
正如我已经知道的那样,我只是想知道。 现在很清楚了。
参考值。菲利斯
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)您好,菲利斯,感谢您的反馈!
我不记得问题是什么,但我在 python 传输过程中处理非数字数据时遇到了问题。
由于 JMP 执行 python 代码时缺乏错误报告,我未能成功找出根本原因并解决它。 分类的 python 脚本代码没问题,JMP 代码也是如此,但是 JMP 代码然后 python 代码使脚本崩溃......
总有一天我会试着回顾一下!
您只需重新编码这些值,例如:yes = 1 且 no = 2 或 setosa = 1、versicolor = 2、virginica =3,... 虽然有点麻烦,但这是为了解决这个错误
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)你好弗兰克。 你的插件做得非常好。
只是出于好奇。 为什么当我选择分类任务时,响应变量类型要求为数字? 我期待一个分类变量(坏与好,基线与实验,猫与狗等)
参考值。菲利斯
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)没问题弗兰克。 这是一个巨大的贡献,感谢分享。
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)谢谢你!
是的,我也希望 Python 支持随着时间的推移而得到改善。
对于界面,抱歉,我几乎完全在空闲时间制作了这个插件,但由于 JMP 的许可证由我的公司支付,我认为源代码的发布必须由我的雇主验证,他希望该源代码保持私有。
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)这很棒! 感谢分享*
关于 Windows 中的 Python,使用 Python 3.6 的 Anaconda 可以与 JMP 15 一起开箱即用,但您需要更新所有包,因为它是一个 2 年前的包。 我希望 JMP 在下一版本中改进对 Python 的支持。
(*note) 您构建的接口可用于其他 python API。 你也发布了源代码吗?
问候。
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)嗨露丝
非常抱歉,我不知道发生了什么:我怀疑 Mac OS 处理目录的方式与 Windows 不同,但崩溃位于 python 部分,而不是在此之前。 此外,当您没有使用文件导出选项时,就会发生崩溃
正如您提到的,这可能与软件包问题有关。 我会尽快尝试升级我的软件包,以检查 Windows 10 上的相同软件包是否仍然正常。
感谢您尝试我的插件! 
弗兰克
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)感谢您查看我的问题, @弗兰克_R 。我的 Python 安装正在与 JMP 一起使用其他代码(包括您建议的测试代码),但您的加载项所需的包或其他缺少组件可能仍然存在问题,但我尚未发现。 我现在完全被难住了。 当我有机会时,我会尝试在 Windows 计算机上进行设置,以便再试一次。
再次感谢您将其发布到社区 - 这是一个非常有用的应用程序!
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)相同的数据集在我的计算机上没有问题:

回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)你好,
是的,问题确实出在 python 部分,对此感到抱歉......
这很奇怪,因为 python 代码根本没有被执行:代码在“try”命令之前就崩溃了! 我从不添加那种崩溃......
但是调试日志很棘手,因为 JMP 不会写入任何 python 的错误消息...它只是抛出 python 代码而没有解释... 当我们将 python 与 JMP 一起使用时,python 遇到问题,没有明确的错误代码:我必须在 JMP 之外开发所有 python 代码,然后将该代码集成到 JMP 中,因为......
这个数据集在我的电脑上处理得很好,但我在 Windows 10 和 python 3.7 上工作
首先要检查的是 JMP 15.1 是否可以处理 python 3.8 我真的不确定情况是否如此(例如 python 3.7 存在一些困难,请参阅https://community.jmp.com/t5/Discussions/JMP-14-Python-bility-working-Im-confused/td-p/184515
尝试执行脚本索引中的示例代码:
名称默认为此处( 1 );
Python 初始化();
Python 提交(
“\[
str = '敏捷的棕色狐狸跳过了懒狗';
a = 200;
]\"
);
getStr = Python Get( str );
getNum = Python Get( a );
显示( getStr, getNum );
Python 术语();
那么,您的数据集中是否存在缺失值? (我不检查数据集中是否有缺失值,如果它是带有一些缺失值的重新设计的波士顿数据集,它可能会崩溃)
我也不确定我的代码是否可以处理 Mac OS,因为我无法检查这一点,而且 python 集成可能与 Windows 有点不同......
回复:在 JMP 插件中使用 XGBoost 进行机器学习(JMP 应用程序 + python)感谢您提供此功能! 我尝试在波士顿住房数据上运行它,稍微调整以包括适当的验证列和数字 ID 列,并使用“chas”变量作为数字指示器。 (参见下面的屏幕截图。)我在 MacOS 10.15.3 上运行 JMP Pro 15.1,使用 Python 3.8.2 和 numpy 1.18.2、pandas 1.0.3、scikit-learn 0.23.1 和 XGBoost 1.1.0。 我正在复制下面的日志。 显然有些东西工作了一段时间,但随后 Python 崩溃了。 最后,我收到警告“在访问或评估‘发送’时,发送需要可编写脚本的对象。” 我想这个错误发生是因为Python崩溃并且没有创建要发送的对象。
关于可能出什么问题的任何想法吗? 我不是脚本专家,但除了这个弱点之外,我不理解日志中的一些法语输出;)
谢谢!
露丝
"*** 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'


回复:使用 XGBoost 进行机器学习你好
我已经更新了该插件,使其与新的 python 版本兼容 + 新功能 + 错误修正
回复:使用 XGBoost 进行机器学习我可以评论一下你使用 matplotlib 崩溃的原因。 JMP 的主窗口事件循环和 matplotlib 的主窗口事件循环发生冲突。由于Python共享库被加载到JMP的进程空间中,JMP已经有了一个主窗口。通过通常方法调用的 Matplotlib 认为它具有主窗口循环。这完全取决于选择的 matplolib 后端。 14 年后,我们强制将 maptplotlib 后端设置为非交互式“AGG”后端,只需告诉 matplotlib 保存图形而不是显示它即可完全使用它。您可能看到的另一个问题是 JMP 并非在所有情况下都崩溃,而是退出。最后关闭的 matplotib 窗口是在 JMP 控制之外调用 C 级 exit()。 JMP 18.0 稍微宽松一点,如果它允许在 Windows 上使用 matplotlib,而不将其强制到 AGG 后端,但在 Mac 上,默认的 Cocoa 后端确实仍然会崩溃,我与 matplotlib 开发人员有一个开放的错误报告。在 Mac 上,我在 PySide 或 PyQt 后端方面取得了一些成功,但仍然时好时坏。调用 matplotlib 的最佳方法是将图形保存为图像。
回复:使用 XGBoost 进行机器学习嗨保罗,
感谢您的关注和解释!很高兴看到 JMP 18 中继续与 python 集成...