JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Salut la communauté JMP,
La taille de mes ensembles de données augmente et les scripts de base que j'ai créés il y a quelque temps (voir ci-dessous) ne suivent pas du point de vue de la vitesse.
J'apprécierais beaucoup d'entendre des idées sur la façon d'optimiser ce type de script pour une meilleure vitesse. Par exemple, je soupçonne que des opérations comme "Concaténer" sont relativement lentes, et il peut être judicieux de travailler avec des matrices pour ce type d'opération.
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;
Tous les commentaires sont les bienvenus.
Meilleur,
TS
Automatisation et scriptRe : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Salut jti,
Rendre le modèle d'ajustement invisible a réduit de 8 secondes supplémentaires (de 61 à 53 secondes) et remplacer "Pour chaque ligne" par des affectations directes réduit de 5 secondes supplémentaires (de 53 à 48 secondes).
Brillant!
Meilleur,
TS
Re : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Ceux-ci pourraient donner des augmentations de vitesse supplémentaires (probablement assez faibles):
Vous pouvez très probablement ajouter un modèle invisible pour s'adapter
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
);
De plus, si vous créez des colonnes avec des formules et que vous les supprimez immédiatement, vous pouvez utiliser << Définir chaque valeur au lieu de Formule et Supprimer la formule
dtoutl << New Column("METAB_ID", Character, Nominal, << Set Each Value(Substitute(:MET_ID, "LOG10 FC ", "")));
Vous pourrez peut-être remplacer For Each Row par << Set Each Value également (pas sûr de celui-ci, pas sûr non plus si cela aura une augmentation de vitesse):
Column(dtoutp, "LABEL") << Set Each Value(annot_pv[Sequence( 1, N Items (annot_pv), 1, 1 )]);
Vous pouvez également essayer de garder les tables de données privées (au moins invisibles) jusqu'à ce que vous en ayez besoin. Vous pouvez rendre les tables privées visibles avec << New Data View (je ne le savais pas avant aujourd'hui).
Fermez les tables de données/rapports/fenêtres dès que vous n'en avez plus besoin.
Re : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Salut la communauté JMP,
Trouvez ci-dessous la version annotée du script le plus amélioré pour exécuter et capturer le résultat d'un grand nombre d'analyses Fit Model.
Les deux étapes les plus essentielles pour améliorer le temps d'exécution sont :
- Utilisation de matrices au lieu de tableaux de données pour agréger les résultats de l'analyse
- Remplacement au lieu d'insertion des données de sortie d'analyse dans des matrices maîtresses créées avant la boucle 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"));
Meilleur,
TS
Re : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Cool! Je pense que la communauté aimerait voir ce que vous avez fait pour y arriver, ou peut-être résumer l'importance des différents changements.
@DonMcCormack
Re : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Salut @Craige_Hales ,
Merci pour la suggestion. Grâce à la méthode que vous avez recommandée, j'ai amélioré la vitesse de 33 % supplémentaires.
Il y a encore quelques ajustements que je dois perfectionner, mais j'ai commencé avec un temps d'exécution total d'environ 450 secondes, jusqu'à 91 secondes avec mes modifications initiales, et jusqu'à 61 secondes maintenant.
Meilleur
TS
Re : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?5X sonne bien !
Il peut également y avoir une option invisible pour la plate-forme qui pourrait aider.
(Essayez le profileur JSL, la suggestion suivante peut être loin de la base. Cela ne sert à rien de faire quelque chose de plus rapide qui utilise < 1% du temps...)
Si cela ne suffit toujours pas, les deux dernières instructions de la boucle peuvent être le prochain endroit où chercher. Je pense que votre JSL réaffecte les tableaux 2000 fois à des tailles progressivement plus grandes. Si vous pouvez pré-allouer les tableaux (en utilisant la fonction J(nr,nc,initvalue)) et les stocker avec quelque chose comme mtx_lsm[a::b,0] = temp_mtx_lsm[0,0] vous gagnerez du temps .
Edit : il s'agit potentiellement d'un problème N^2 car non seulement il réaffecte, mais il copie également les données ; passer d'une série de 1000 à une série de 2000 copiera 4X (et non 2X) la quantité de données.
Re : JMP > JSL > Accélération de script pour plusieurs appels pour ajuster le modèle (N > 2000) ?Salut la communauté JMP,
J'ai expérimenté des matrices comme réceptacles pour agréger de longues collections de tableaux de sortie d'analyse, et jusqu'à présent, j'ai accéléré mon temps d'exécution d'environ 5 fois (voir ci-dessous). Le seul inconvénient mineur est que j'ai dû reconstruire les annotations pour les tables de sortie capturées car (évidemment) les matrices ne contiennent pas de texte.
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;