みなさんこんにちは
Datatable を作成する JSL スクリプトがあり、JSL スクリプト内に Python コード ブロックがあります。このコード ブロックに DataTable を渡して、トレーニング済みの機械学習モデルを使用して DataTable で予測を行いたいと考えています。Python コード ブロックの前は、DataTable にアクセスでき、JMP で開くこともできます。ただし、Python コード ブロックの後で、"Show(preds_df)" を使用して DataTable に基づいてニューラル ネットワーク モデルによって行われた予測にアクセスしようとすると、"名前が解決されていません: 'preds_df' のアクセスまたは評価で preds_df が発生しました" というエラーが発生します。私は JMP Pro 17 を使用しています。以下はレビュー用のコード ブロックです。
<
Clear Log();
Clear Symbols();
Names Default To Here( 1 );
// Define the list of options for the dropdown
SITE = {"SITE_1", "SITE_2"};
MODELS = {"NN_MODEL", "RNN_MODEL"};
PythonConnection = Python Connect();
conn = PythonConnection << Is Connected;
PythonConnection << Send( dt);
close(dt);
PythonConnection << Send(MODELS);
PythonConnection << Execute("
import pandas as pd
from sklearn.preprocessing import StandardScaler
import torch
import pickle
import numpy as np
// Model Selection
if 'NN_MODEL' in MODELS:
model = 'NN_MODEL'
else:
model = 'RNN_MODEL'
# Extract categorical and numerical features from data
categorical_features = ['NAME', 'COUNTRY', 'SCHOOL']
numerical_features = ['AGE', 'SIZE', 'HEIGHT', 'WEIGHT']
# One-Hot encoding for categorical features in place
process_df = pd.get_dummies(dt, columns=categorical_features, drop_first=True)
# Normalize numerical features
scaler = StandardScaler()
new_df[numerical_features] = scaler.fit_transform(process_df[numerical_features])
# Exclude bin columns from the model input
B_cols = ['B1', 'B8', 'B9', 'B10']
B_columns = [col for col in B_cols if col in process_df.columns]
input_df = process_df.drop(B_columns, axis=1)
labels = process_df[B_cols]
ids = process_df[B_cols].index
# Load the trained model based on user selection
if model == 'NN_MODEL':
model_path = '.\\nn_model.pth'
model = torch.load(model_path)
model.eval()
# Convert DataFrame to tensor
in_tensor = torch.tensor(input_df.values, dtype=torch.float32)
# Predict using the model
with torch.no_grad():
nn_preds = model(in_tensor)
nn_preds = torch.round(nn_preds).to(torch.int).numpy()
nn_preds = np.clip(nn_preds, a_min=0, a_max=None)
preds_df = pd.DataFrame(nn_preds.numpy(), index=ids, columns=labels)
else:
model_path = '.\\rnn_model.pkl'
with open(model_path, 'rb') as file:
model = pickle.load(file)
rnn_preds = model.predict(input_df)
rnn_preds = np.clip(rnn_preds, a_min=0, a_max=None)
preds_df = pd.DataFrame(rnn_preds, index=ids, columns=labels)
"
);
Show(preds_df)
>
簡単に見ると、preds_df は単なる pandas データフレームであり、JMP テーブルではないため、JMP からアクセスすることはできません。
JSL スクリプトの最後にこれを試してください:
dt = Python Get( preds_df );
dt << New Data View;
また、JMP 18 は Python スクリプトをネイティブに実行できるため、JSL スクリプトに埋め込む必要はありません。
データフレームを JMP データテーブルに変換して、Python ブロックの外部で視覚化する方法はありますか。
「Send は、Send のアクセスまたは評価でスクリプト可能オブジェクトを期待します。"dt" << /*###*/New Data View/*###*/」というメッセージを受け取りました。
できます。JMP17 が直接実行できるかどうかは覚えていませんが、たとえば .csv ファイルを使用して、pandas データフレームから .csv を作成し、そのパスを JMP に渡して開くことができます。
まず、<< Execute ( ) の構文が間違っています。スクリプト インデックスの例を参照してください。Execute の最初のパラメーターは入力の JSL リストで、その後に出力変数の JSL リスト、スクリプト、オプションの echo(1 または 0) パラメーターが続きます。
スクリプトは、空白と行末が保持されるように、JSLの「生の」文字列マーカー「\[script here ]\」で区切る必要があります。構文エラーが発生しないことに驚いていますが、19でも同様にエラーが発生していないのがわかります... 調査中です。私の場合、show preds_dfは単に次のように出力しました。
dt = .;
欠落しています。これは当然次のことを意味します。
dt << 新しいデータビュー
dt ( 欠落 ) はスクリプト化できないため、エラーが発生します。
以下のコードは問題を再現します。
conn = Python Connect();
conn << Get Version();
conn << Execute( "
import pandas as pd
import numpy as np
pandas_df = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
print(pandas_df)
]\", echo(1) );
dt = Python Get(pandas_df);
show(dt);
dt << New Data View;
このコードは期待通りに動作します
conn = Python Connect();
conn << Get Version();
conn << Execute( {},{},"\[
import pandas as pd
import numpy as np
pandas_df = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
print(pandas_df)
]\", echo(1) );
dt = Python Get(pandas_df);
show(dt);
dt << New Data View;
注目すべき点がいくつかあります。JMP 17 は、JMP 18 以降でインストールされた組み込み Python ではなく、ユーザーの環境から Python を利用した最後のバージョンです。JMP 14-17 では、Python Send (dt);は、データ テーブルを一時的な CSV ファイルに保存し、次に pandas にその CSV ファイルをデータフレームに読み込ませることで、Python 環境に pandas データフレームを作成しました。Python Get( df); は、pandas にデータフレームを CSV ファイルに書き込ませ、JMP に CSV ファイルをインポートさせることで、同様に動作しました。つまり、JMP データ テーブルと pandas データフレームの 2 つのデータのコピーがあることになります。
これはJMP 18で組み込みPython 3.11.xと組み込みジャンプの導入により変更されました。 jmp.DataTable クラスを提供するインポート パッケージ。これにより、Python からアクセス可能な JMP データ テーブルへのメモリ内ライブ参照が導入されます。JMP 18+ の Python Send( dt ); は、pandas データグラムではなく jmp.DataTable オブジェクトを作成するようになりました。dt2 = Python Get( dt ) は、変数に割り当てるデータ テーブル参照を取得するだけです。dfdt = Python Get( data_frame ); は、引き続き古いメカニズムを使用して、データフレームを CSV ファイル経由でデータ テーブルとして変換および読み込みます。JMP 18 では、スクリプト ディレクトリに、元の dt->csv->df および df->csv->dt 変換を行う方法を示す Python サンプル スクリプトがあります。JMP 19 は Portable Dataframe Protocol をサポートしているため、メモリ内で dt->df または df->dt を実行するのはワンライナーです。 dt2pandas.jsl、dt2pands.py、dt2pandas2dt.py という名前のサンプル
JMP 17の場合:
Names Default to here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
// I have multiple Python's on system so I choose 3.10 where I have
// matplotlib, pandas, numpy, ... installed
Python Init(Use Python Version("3.10"));
Python Send(dt);
close(dt);
dtdf = Python Get("dt");
Show(dtdf);
dtdf << New Data View;
これは私のマシンでは問題なく動作します。これを実行できない場合は、ログを調べてエラーが表示されているかどうかを確認してください。必要に応じて、環境に合わせて Python Init() を変更します。
JMP19
conn = Python Connect();
conn << Get Version();
conn << Execute( {},{},"\[
import jmp
import pandas as pd
import numpy as np
pandas_df = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
print( pandas_df )
# JMP 19 create a data table direcly from a dataframe
dt = jmp.from_dataframe(pandas_df)
print( dt )
]\", echo(1) );
show(dt);
// dt << New Data View; // already on screen
JMP 18以降では、JSLラッパーを必要とせず、エディターからPythonスクリプトを実行するだけで、さらに多くのことが可能になります。