Hi @abmayfield ,
This was something that I've been wanting to script up for a while and was really fun, and your post gave the fire to get it going, thanks! I've been wanting to have a way to tune the NN platform for a while as it is very sensitive to the initial conditions, and it's rather slow to do it manually.
So, I adapted some scripts that I have made for other model platforms to automate their tuning processes, for example, the boosted tree, bootstrap forest, and XGBoost platforms. The scripts are meant to be saved into your data table and run with the green hot button.
Hopefully you know some about scripting and will know where to adapt these scripts to your specific situations/data structure/column names, etc. I have entered in some comments to try and help explain what I'm doing in each larger group. I'm attaching two scripts -- one for continuous Y's and one for Nominal/Ordinal Y's. I did have to include a test to see if the output Y is nominal or ordinal because the Number Col Box() value changes depending on this. I used the Big Class Families.jmp data table in the sample data as a test data set. I'm also including two output data tables I generate using either the numerical NN tuning or nominal/ordinal NN tuning. I did nominal on :sex using :age, :weight:, :height, and then I changed :age from Ordinal to Continuous and modeled age with :weight and :sex for the continuous NN tuning. The fits and stats are horrible, but it's intended only for the purpose of seeing if the JSL works or not. I also added a :Validation column to the data table by stratifying on :age, just to check that it all worked correctly.
I'm sure someone else could script it up more elegantly to test the Y() input column to be modeling type Continuous, Nominal, or Ordinal and then have the appropriate Number Col Box() value inserted to extract the data appropriately using only a single JSL code.
You will need to edit the Y() and X() inputs to the dt << Nerual() section as well as the part where you get the name of the report window, as it's named after the variable you're modeling.
The NN tuning tables could be treating like a space filling DOE in principle where the lower and upper settings are whatever you want to set it to, except for some of them, like N_Layers can only be 1 or 2 because JMP only allows 1 or 2 layers. Penalty_Method is only the options that are valid in the NN platform, and the Transform Covariate and Robust Fit only take on values of 0 or 1 (off or on). I'm including the NN tuning table as well.
If you have any questions, let me know.
Here's my code for the Nominal/Ordinal modeling type:
Names Default To Here( 1 );
dt = Data Table( "Big Class Families" );//enter the name of the current data table
dt_parms = Data Table( "NN Tuning" );//enter name of parameter data table for tuning the NN
dt_results = dt_parms << Subset( All rows, Selected Columns Only( 0 ) );//this copies the tuning table with all the different rows in it
//these commands create columns to record the fit results
dt_results << New Column( "Generalized R² Training" );
dt_results << New Column( "Generalized R² Validation" );
dt_results << New Column( "Entropy R² Training" );
dt_results << New Column( "Entropy R² Validation" );
dt_results << New Column( "RMSE Training" );
dt_results << New Column( "RMSE Validation" );
dt_results << New Column( "Mean Abs Dev Training" );
dt_results << New Column( "Mean Abs Dev Validation" );
dt_results << New Column( "Misclassification Rate Training" );
dt_results << New Column( "Misclassification Rate Validation" );
dt_results << New Column( "-LogLiklihood Training" );
dt_results << New Column( "-LogLiklihood Validation" );
dt_results << New Column( "Sum Freq Training" );
dt_results << New Column( "Sum Freq Validation" );
//This part just creates a separate modelling progress, delete if you don't want it.
i = 1;
imax = N Row( dt_parms );
dlgStatus = New Window( "Overall Modeling Progress",
V List Box(
Text Box( " Overall Modeling Progress ", <<Set Font Size( 12 ), <<Justify Text( "center" ), <<Set width( 200 ) ),
dlg_gb = Graph Box( FrameSize( 200, 15 ), X Scale( 0, 100 ), Y Scale( 0, 1 ) ),
tb = Text Box(
"Current step " || Char( i ) || " of " || Char( imax ),
<<Set Font Size( 12 ),
<<Justify Text( "center" ),
<<Set width( 200 )
)
)
);
dlg_gb[Axis Box( 2 )] << Delete;
dlg_gb[Axis Box( 1 )] << Delete;
//This big for loop goes through your tuning table putting each value into the fit to generate a new NN model and save the statistics
For( i = 1, i <= imax, i++,
prog = (i / imax) * 100;//take out if you don't want the update window
dlgStatus[FrameBox( 1 )] << Add Graphics Script( {Fill Color( "purple" ), Rect( 0, 1, prog, 0, 1 )} );//take out if you don't want the update window
tb << set text( "Current step " || Char( i ) || " of " || Char( imax ) );//take out if you don't want the update window
Nlayer = dt_parms:N_Layers[i];
If( dt_results:N_Layers[i] == 1,
dt_results:N_TanH_2[i] = 0;
dt_results:N_Linear_2[i] = 0;
dt_results:N_Gauss_2[i] = 0;
);//can't have a second layer if you have one and are boosting
If( dt_results:N_Layers[i] == 2,
dt_results:N_Boosts[i] = 0;
dt_results:Learn_Rate[i] = 0.1;
);//can't boost if you have two layers
NTH1 = dt_results:N_TanH_1[i];
NTH2 = dt_results:N_TanH_2[i];
NL1 = dt_results:N_Linear_1[i];
NL2 = dt_results:N_Linear_2[i];
NG1 = dt_results:N_Gauss_1[i];
NG2 = dt_results:N_Gauss_2[i];
Nboosts = dt_results:N_Boosts[i];
LR = dt_results:Learn_Rate[i];
TCov = dt_results:T_Cov[i];
RFit = dt_results:Robust_Fit[i];
PMethod = dt_results:Penalty_Method[i];
Ntours = dt_results:N_Tours[i];
str = Eval Insert(
"report = (dt << Neural(
Y( :sex ),
X(
:height,
:age,
:weight
),
Validation ( :Validation ),
Informative Missing(0),
Transform Covariates(^TCov^),
Fit(
NTanH(^NTH1^),
NLinear(^NL1^),
NGaussian(^NG1^),
NTanH2(^NTH2^),
NLinear2(^NL2^),
NGaussian2(^NG2^),
Transform Covariates(^TCov^),
Penalty Method(\!"PMethod\!"),
Number of Tours(^Ntours^),
N Boost(^Nboosts^),
Learning Rate(^LR^)
)),
Go,
invisible
) << Report;"
);
Eval( Parse( str ) );
w = Window( dt << GetName || " - " || "Neural of sex" );//here, you'll want to change the characters after "age" to whatever your response is
//just a simple way to test if the Y variable is Nominal or Ordinal by testing the name of the report window
If( !Is Missing( Regex( w << Get Window Title, "age" ) ) == 1,
ncol_box = 14
);
If( !Is Missing( Regex( w << Get Window Title, "sex" ) ) == 1,
ncol_box = 6
);
T_stats = w[Outline Box( 3 ), Number Col Box( 1 )] << Get;//You might need to adjust the Outline Box () and Number Col Box() values depending on your tree structure
V_stats = w[Outline Box( 3 ), Number Col Box( ncol_box )] << Get;//You might need to adjust the Outline Box () and Number Col Box() values depending on your tree structure
report << Close Window;
//training results
dt_results:Generalized R² Training[i] = T_stats[1];
dt_results:Entropy R² Training[i] = T_stats[2];
dt_results:RMSE Training[i] = T_stats[3];
dt_results:Mean Abs Dev Training[i] = T_stats[4];
dt_results:Misclassification Rate Training[i] = T_stats[5];
dt_results:Name( "-LogLiklihood Training" )[i] = T_stats[6];
dt_results:Sum Freq Training[i] = T_stats[7];
//validation results
dt_results:Generalized R² Validation[i] = V_stats[1];
dt_results:Entropy R² Validation[i] = V_stats[2];
dt_results:RMSE Validation[i] = V_stats[3];
dt_results:Mean Abs Dev Validation[i] = V_stats[4];
dt_results:Misclassification Rate Validation[i] = V_stats[5];
dt_results:Name( "-LogLiklihood Validation" )[i] = V_stats[6];
dt_results:Sum Freq Validation[i] = V_stats[7];
);
dlgStatus << closewindow();
One thing that is strange that I don't understand is that I get this warning about the log window I create when I run it for the NN platform, but I've never gotten it from my other platforms. I can't follow where that warning comes from, but it still runs correctly. Maybe someone can fix that part of my code?
Unexpected ",". Perhaps there is a missing ")".
Trying to parse operand for "<<" operator.
Line 23 Column 10: ))►,
As a last note: be careful about the settings as it can take a VERY long time to run the modeling if you have huge numbers of boosts or tours or transfer functions. Just be cautious not to go overboard.
Hope this helps!,
DS