JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?Ciao comunità JMP,
La dimensione dei miei set di dati sta aumentando e gli script di base che ho creato qualche tempo fa (vedi sotto) non tengono il passo dal punto di vista della velocità.
Apprezzerei molto conoscere idee su come ottimizzare questo tipo di script per una migliore velocità. Ad esempio, sospetto che operazioni come "Concatena" siano relativamente lente e potrebbe avere senso lavorare con le matrici per questo tipo di operazione.
Names Default to Here (1);
dt = Current Data Table ();
CList = dt << Get Column Names (string);
dtoutl = New Table ("LSM OUTPUT", "invisible");
dtoutp = New Table ("PVal OUTPUT", "invisible");
For (i = 1, i<= 2000, i++,
fm = dt << Fit Model(
Y( Column (i) ),
Effects( :VISIT, :TREATMENT, :VISIT * :TREATMENT, Column (i+2000) ),
Personality( "Standard Least Squares" ),
Emphasis( "Minimal Report" ),
Run(
Column (i) << {Summary of Fit( 1 ), Analysis of Variance( 1 ),
Parameter Estimates( 1 ), Scaled Estimates( 0 ),
Plot Actual by Predicted( 0 ), Plot Regression( 0 ),
Plot Residual by Predicted( 0 ), Plot Studentized Residuals( 0 ),
Plot Effect Leverage( 0 ), Plot Residual by Normal Quantiles( 0 ),
Box Cox Y Transformation( 0 ), {:VISIT * :TRT01A <<
{LSMeans Contrast( [0 0 1 -1 0 0, 0 0 0 0 1 -1] )}}}
)
);
fmr = report (fm);
table_list = fmr << xpath ("//OutlineBox [text() = 'VISIT*TREATMENT']//TableBox");
temp_lsm = table_list [1];
temp_pval = table_list [2];
temp_tbl_lsm = temp_lsm << Make into Data Table (invisible (1));
temp_tbl_pval = temp_pval << Make into Data Table (invisible (1));
temp_tbl_lsm << New column ("ID", character, nominal, << set each value (CList [i]));
temp_tbl_pval << New column ("ID", character, nominal, << set each value (CList [i]));
fmr << close window;
dtoutl << Concatenate (Data table (temp_tbl_lsm), "Append to First Table");
Wait (0);
dtoutp << Concatenate (Data table (temp_tbl_pval), "Append to First Table");
Close (temp_tbl_lsm, NoSave);
Close (temp_tbl_pval, NoSave);
);
dtoutl << Bring Window to Front;
dtoutp << Bring Window to Front;
Tutti i feedback sono i benvenuti.
Migliore,
ST
Automazione e scriptingOggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?ciao jti,
Rendendo invisibile il modello Fit si sono rasati altri 8 secondi (da 61 secondi a 53 secondi) e la sostituzione di "For Each Row" con assegnazioni dirette si riduce di altri 5 secondi (da 53 secondi a 48 secondi).
Brillante!
Migliore,
ST
Oggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?Questi potrebbero dare ulteriori (molto probabilmente abbastanza piccoli) aumenti di velocità:
Molto probabilmente puoi aggiungere invisibile per adattare il modello
fm = dt << Fit Model(
Y( Column (i) ),
Effects( :VISIT, :TRT01A, :VISIT * :TRT01A, Column (i-1933) ),
Personality( "Standard Least Squares" ),
Emphasis( "Minimal Report" ),
Run(
Column (i) << {Summary of Fit( 1 ), Analysis of Variance( 1 ),
Parameter Estimates( 1 ), Scaled Estimates( 0 ),
Plot Actual by Predicted( 0 ), Plot Regression( 0 ),
Plot Residual by Predicted( 0 ), Plot Studentized Residuals( 0 ),
Plot Effect Leverage( 0 ), Plot Residual by Normal Quantiles( 0 ),
Box Cox Y Transformation( 0 ), {:VISIT * :TRT01A <<
{LSMeans Contrast( [0 0 1 -1 0 0, 0 0 0 0 1 -1] )}}}
),
invisible
);
Inoltre, se stai creando colonne con formule e poi le rimuovi immediatamente, puoi usare << Imposta ogni valore invece di Formula ed Elimina formula
dtoutl << New Column("METAB_ID", Character, Nominal, << Set Each Value(Substitute(:MET_ID, "LOG10 FC ", "")));
Potresti essere in grado di sostituire For Each Row con << Set Each Value also (non sono sicuro di questo, inoltre non sono sicuro se questo aumenterà la velocità):
Column(dtoutp, "LABEL") << Set Each Value(annot_pv[Sequence( 1, N Items (annot_pv), 1, 1 )]);
Puoi anche provare a mantenere i datatable privati (almeno invisibili) fino a quando non ne avrai bisogno. Puoi rendere visibili le tabelle private con < (non lo sapevo prima di oggi).
Chiudi datatables / report / finestre immediatamente dopo che non ne hai più bisogno.
Oggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?Ciao comunità JMP,
Trova di seguito la versione annotata dello script più migliorato per eseguire e acquisire l'output di un gran numero di analisi del modello di adattamento.
I due passaggi più essenziali per migliorare il tempo di esecuzione sono:
- Utilizzo di matrici invece di tabelle di dati per aggregare l'output dell'analisi
- Sostituzione anziché inserimento dei dati di output dell'analisi nelle matrici master create prima del ciclo principale.
Names Default to Here (1);
st = Today();
dt = Current Data Table ();
lc_path = dt << GetPath;
// START: CAPTURING OUTPUT ANNOTATION TO REBUILD ANNOTATION //
dts = dt << Summary( Group( :VISIT, :TRT01A ), Freq( "None" ), Weight( "None" ), invisible );
annot_lsm = {};
met_l = {};
annot_pv = {};
CList = dt << Get Column Names (string);
For (j = 1, j <= N Rows (dts), j++,
insert into (annot_lsm, dts:VISIT [j] || ", " || dts:TRT01A [j]);
);
annot_pv = annot_lsm;
annot_pv = Concat To(annot_pv, {"Estimate","Std Error", "t Ratio", "Prob>|t|", "SS", "Lower 95%", "Upper 95%"});
Close (dts, NoSave);
// END: CAPTURING OUTPUT ANNOTATION TO REBUILD ANNOTATION //
// START: CREATING EMPTY NASTER MATRICES TO HOLD TTHE OUTPUT OF THE FIT MODEL//
nro_l = 1933*6;
nco_l = 4;
nro_p = 1933 * 13;
nco_p = 2;
mtx_lsm = J(nro_l, nco_l);
mtx_pval = J(nro_p, nco_p);
// END: CREATING EMPTY MASTER MATRICES TO HOLD TTHE OUTPUT OF THE FIT MODEL//
//START MAIN LOOP//
For (i = 3921, i<= 5853, i++, //5853
//START LINEAR MODEL WITH CUSTGOMIZED CONTRASTS //
fm = dt << Fit Model(
Y( Column (i) ),
Effects( :VISIT, :TRT01A, :VISIT * :TRT01A, Column (i-1933) ),
Personality( "Standard Least Squares" ),
Emphasis( "Minimal Report" ),
Run(
Column (i) << {Summary of Fit( 1 ), Analysis of Variance( 1 ),
Parameter Estimates( 1 ), Scaled Estimates( 0 ),
Plot Actual by Predicted( 0 ), Plot Regression( 0 ),
Plot Residual by Predicted( 0 ), Plot Studentized Residuals( 0 ),
Plot Effect Leverage( 0 ), Plot Residual by Normal Quantiles( 0 ),
Box Cox Y Transformation( 0 ), {:VISIT * :TRT01A <<
{LSMeans Contrast( [0 0 1 -1 0 0, 0 0 0 0 1 -1] )}}}
)
);
//END LINEAR MODEL WITH CUSTGOMIZED CONTRASTS //
//START CAPTURE ANALYSIS OUTPUTS FOR EACH RUN//
fmr = report (fm);
insert into (met_l, CList [i]); //COLLATING THE NAME OF THE COLUMN FOR EACH RUN//
table_list = fmr << xpath ("//OutlineBox [text() = 'VISIT*TRT01A']//TableBox");
temp_lsm = table_list [1]; //POINTER TO LSMEAN + STDERR TABLE//
temp_pval = table_list [2]; // POINTER TO CONTRAST TABLE //
temp_mtx_lsm = temp_lsm << Get as Matrix; // EXTRACT LSMEAN + STDERR OUTPUT AS A MATRIX //
temp_mtx_pval = temp_pval << Get as Matrix; // EXTRACT CONTRAST OUTPUT AS A MATRIX //
locr1_l = ((i-3921)*6) + 1; //GENERATE THE TOP ROW BLOCK FOR INSERTION OF LSMEAN + STDERR IN TO THE MASTER MATRIX //
locr2_l = ((i-3921)*6) + 6; //GENERATE THE BOTTOM ROW BLOCK FOR INSERTION OF LSMEAN + STDERR IN TO THE MASTER MATRIX //
mtx_lsm [locr1_l::locr2_l, 0] = temp_mtx_lsm [0,0]; //REPLACE PLACEHOLDER VALUES IN MASTER MATRIX WITH LOCAL LSMEAN + STDERR OUTPUT DATA FROM EACH RUN //
locr1_p = ((i-3921)*13) + 1; //GENERATE THE TOP ROW BLOCK FOR INSERTION OF CONTRAST IN TO THE MASTER MATRIX //
locr2_p = ((i-3921)*13) + 13; //GENERATE THE BOTTOM ROW BLOCK FOR INSERTION OF CONTRAST IN TO THE MASTER MATRIX //
mtx_pval [locr1_p::locr2_p, 0] = temp_mtx_pval [0,0]; //REPLACE PLACEHOLDER VALUES IN MASTER MATRIX WITH LOCAL CONTRAST OUTPUT DATA FROM EACH RUN //
fmr << close window;
);
// START CONVERT MASTER MATRICES INTO TABLES//
dtoutl = as Table (mtx_lsm);
dtoutp = as Table (mtx_pval);
// END CONVERT MASTER MATRICES INTO TABLES//
//START REBUILD ANNOTATIONS AND REFORMAT FOR LSMEAN + STDERR TABLE//
dtoutl << new column ("COMP", Character, Nominal);
dtoutl << new column ("MET_ID", Character, Nominal);
dtoutl:Col1 << set name ("LSMEAN");
dtoutl:Col2 << set name ("STDERR");
dtoutl:Col3 << set name ("UPPER CI");
dtoutl:Col4 << set name ("LOWER CI");
dtoutl << Begin Data Update;
For Each Row( dtoutl, :COMP = annot_lsm[Sequence( 1, N Items (annot_lsm), 1, 1 )] );
For each row( dtoutl, :MET_ID = met_l[Sequence (1,N Items (met_l), 1, 6)] );
dtoutl << End Data Update;
dtoutl << New Column ("METAB_ID", Character, Nominal, Formula (Substitute (:MET_ID, "LOG10 FC ", ""))) ;
dtoutl << New Column ("VISIT", Character, Nominal, Formula (Word (1,:COMP, ",")));
dtoutl << New Column ("ARM", Character, Ordinal, Formula (Word (-1, :COMP, ",")));
dtoutl:METAB_ID << Delete Formula;
dtoutl:ARM << Delete Formula;
dtoutl:VISIT << Delete Formula;
//END REBUILD ANNOTATIONS AND REFORMAT FOR LSMEAN + STDERR TABLE//
//START REBUILD ANNOTATIONS AND REFORMAT FOR CONTRAST TABLE//
dtoutp << new column ("LABEL", Character, Nominal);
dtoutp << new column ("MET_ID", Character, Nominal);
dtoutp << Begin Data Update;
For Each Row( dtoutp, :LABEL = annot_pv[Sequence( 1, N Items (annot_pv), 1, 1 )] );
For each row( dtoutp, :MET_ID = met_l[Sequence (1,N items (met_l), 1, 13)] );
dtoutp << End Data Update;
CNAME1 = Column (dtoutp, 3) [3];
CNAME2 = Column (dtoutp, 3) [5];
dtoutp << Select Where (:LABEL == "Prob>|t|");
dtoutp_s = dtoutp << subset (Selected Rows, Output Table Name ("P VAL"));
Close (dtoutp, NoSave);
dtoutp_s << New Column ("METAB_ID", Character, Nominal, Formula (Substitute (:MET_ID, "LOG10 FC ", "")));
dtoutp_s:Col1 << Set Name (CNAME1);
dtoutp_s:Col2 << Set Name (CNAME2);
dtoutp_s_s = dtoutp_s << Stack (Columns (as name(CNAME1), as name (CNAME2)), Output Table Name ("STACK P VAL"));
Close (dtoutp_s, NoSave);
dtoutp_s_s << New Column ("VISIT", Character, Nominal, Formula (Word (1,:Label, ",")));
dtoutp_s_s << New Column ("xARM", Character, Ordinal, Formula (Word (-1, :Label, ",")));
dtoutp_s_s:Data << Set name ("NOM P VAL");
dtoutl << Update(
With( dtoutp_s_s ),
Match Columns( :METAB_ID = :METAB_ID, :VISIT = :VISIT ),
Add Columns from Update Table( :NOM P VAL ),
Replace Columns in Main Table( None )
);
Close (dtoutp_s_s, NoSave);
//END REBUILD ANNOTATIONS AND REFORMAT FOR CONTRAST TABLE//
dtoutl << Save (substitute (lc_path, dt << get name||".jmp", "LINMOD_OUT_")||char(today())); //
et = Today ();
show (Date Difference (st, et, "second"));
Migliore,
ST
Oggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?Freddo! Penso che la comunità vorrebbe vedere cosa hai fatto per arrivarci, o forse riassumere quanto siano stati importanti i diversi cambiamenti.
@DonMcCormack
Oggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?CIAO @Craige_Hales ,
Grazie per il suggerimento. Grazie al metodo che mi hai consigliato, ho migliorato la velocità di un altro 33%.
Ci sono ancora alcune modifiche che devo perfezionare, ma ho iniziato con un tempo di esecuzione totale di circa 450 secondi, sceso a 91 secondi con le mie modifiche iniziali e fino a 61 secondi ora.
Migliore
ST
Oggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?5X suona alla grande!
Potrebbe anche esserci un'opzione invisibile per la piattaforma che potrebbe aiutare.
(Prova il profiler JSL, il prossimo suggerimento potrebbe essere fuori base. Non ha senso creare qualcosa di più veloce che usi <1% del tempo...)
Se ancora non è sufficiente, le ultime due istruzioni nel ciclo potrebbero essere il punto successivo in cui cercare. Penso che il tuo JSL stia riallocando gli array 2000 volte a dimensioni progressivamente maggiori. Se puoi pre-allocare gli array (usando la funzione J(nr,nc,initvalue)) e memorizzarli con qualcosa come mtx_lsm[a::b,0] = temp_mtx_lsm[0,0] risparmierai un po' di tempo .
Modifica: questo è potenzialmente un problema N ^ 2 perché non solo rialloca, ma copia anche i dati; passare da una corsa di 1000 a una corsa di 2000 copierà 4 volte (non 2 volte) la quantità di dati.
Oggetto: JMP > JSL > Accelerazione script per più chiamate per adattare il modello (N > 2000)?Ciao comunità JMP,
Ho sperimentato le matrici come contenitori per l'aggregazione di lunghe raccolte di tabelle di output dell'analisi e finora ho accelerato il mio tempo di esecuzione di ~ 5 volte (vedi sotto). L'unico piccolo inconveniente è che ho dovuto ricostruire le annotazioni per le tabelle di output acquisite perché (ovviamente) le matrici non contengono testo.
Names Default to Here (1);
st = Today();
dt = Current Data Table ();
dts = dt << Summary( Group( :VISIT, :TRT01A ), Freq( "None" ), Weight( "None" ), invisible );
annot_lsm = {};
met_l = {};
annot_pv = {};
CList = dt << Get Column Names (string);
For (j = 1, j <= N Rows (dts), j++,
insert into (annot_lsm, dts:VISIT [j] || ", " || dts:TRT01A [j]);
);
annot_pv = annot_lsm;
annot_pv = Concat To(annot_pv, {"Estimate","Std Error", "t Ratio", "Prob>|t|", "SS", "Lower 95%", "Upper 95%"});
Close (dts, NoSave);
mtx_lsm = [];
mtx_pval = [];
For (i = 1, i<= 2000, i++, //2000
fm = dt << Fit Model(
Y( Column (i) ),
Effects( :VISIT, :TRT01A, :VISIT * :TRT01A, Column (i+2000) ),
Personality( "Standard Least Squares" ),
Emphasis( "Minimal Report" ),
Run(
Column (i) << {Summary of Fit( 1 ), Analysis of Variance( 1 ),
Parameter Estimates( 1 ), Scaled Estimates( 0 ),
Plot Actual by Predicted( 0 ), Plot Regression( 0 ),
Plot Residual by Predicted( 0 ), Plot Studentized Residuals( 0 ),
Plot Effect Leverage( 0 ), Plot Residual by Normal Quantiles( 0 ),
Box Cox Y Transformation( 0 ), {:VISIT * :TRT01A <<
{LSMeans Contrast( [0 0 1 -1 0 0, 0 0 0 0 1 -1] )}}}
)
);
fmr = report (fm);
insert into (met_l, CList [i]);
table_list = fmr << xpath ("//OutlineBox [text() = 'VISIT*TRT01A']//TableBox");
temp_lsm = table_list [1];
temp_pval = table_list [2];
temp_mtx_lsm = temp_lsm << Get as Matrix;
temp_mtx_pval = temp_pval << Get as Matrix;
fmr << close window;
mtx_lsm = mtx_lsm |/ temp_mtx_lsm;
mtx_pval = mtx_pval |/ temp_mtx_pval ;
);
dtoutl = as Table (mtx_lsm);
dtoutp = as Table (mtx_pval);
dtoutl << new column ("COMP", Character, Nominal);
dtoutl << new column ("MET_ID", Character, Nominal);
dtoutl:Col1 << set name ("LSMEAN");
dtoutl:Col2 << set name ("STDERR");
dtoutl:Col3 << set name ("UPPER CI");
dtoutl:Col4 << set name ("LOWER CI");
dtoutl << Begin Data Update;
For Each Row( dtoutl, :COMP = annot_lsm[Sequence( 1, N Items (annot_lsm), 1, 1 )] );
For each row( dtoutl, :MET_ID = met_l[Sequence (1,N Items (met_l), 1, 6)] );
dtoutl << End Data Update;
dtoutp << new column ("LABEL", Character, Nominal);
dtoutp << new column ("MET_ID", Character, Nominal);
dtoutp << Begin Data Update;
For Each Row( dtoutp, :LABEL = annot_pv[Sequence( 1, N Items (annot_pv), 1, 1 )] );
For each row( dtoutp, :MET_ID = met_l[Sequence (1,N items (met_l), 1, 13)] );
dtoutp << End Data Update;