使用 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 整合...