Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Bonjour,
J'écris un script pour créer des données normales multivariées avec un nombre spécifié de lignes, des vecteurs d'écart moyen/type et une structure de corrélation à partir d'un ensemble d'échantillons de données. Je souhaite profiter du simulateur de la plate-forme Profiler pour générer la table de données en procédant comme suit :
- Calculer la moyenne de l'échantillon et l'écart type pour chaque variable.
- Générer une matrice de corrélation à partir de données d'échantillon.
- Simulez des données multivariées à l'aide des statistiques récapitulatives de (1) et (2).
Actuellement, mon script génère la table de données simulée avec les moyennes et les écarts-types appropriés pour chaque variable, mais je n'arrive pas à maintenir correctement la structure de corrélation entre les variables. Je crois que la cause de mon problème est la façon dont je spécifie le [ NxN corrélations] avec Corrélations X en utilisant une variable au lieu de spécifier explicitement la matrice de corrélation (par exemple [1 0,3 0, 0,3 1 0, 0 0 1]), mais mes compétences en dépannage ne m'ont laissé aucune solution. Script actuel et résultats attendus par rapport aux résultats réels fournis ci-dessous, toute suggestion sur la manière de réaliser ces étapes est la bienvenue :
JSL :
names default to here(1);
Try( Close( Data Table(dt) ) );
If( Is Empty( dt ),
Try( dt = Open(), Throw( "No data found" ) )
);
ncol = NCol(dt);
//Dialog Window.
Dlg = New Window("New Window",
<< Modal,
BorderBox(left(3), top(2),
V List Box(
TextBox("Simulate multivariate data"),
HListBox(
VListBox(
PanelBox("Select variables",
colListData = ColListBox(all,nLines,(min(ncol,10)))
),
),
PanelBox("Cast Selected Variables",
LineupBox(NCol(2), Spacing(3),
ButtonBox("Variables", colListY << Append(colListData << Get Selected)),
colListY = ColListBox(nLines(6), "numeric"))
),
//specifications - not in use.
PanelBox("Enter Specifications",
Spacer Box(Size(10, 1)),
HListBox(
VListBox(
Spacer Box(Size(5, 10)),
lsl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl4 = Number Edit Box(, 3)
),
SpacerBox(Size(10,10)),
VListBox(
Spacer Box(Size(5, 10)),
usl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl4 = Number Edit Box(, 3)
)
),
),
PanelBox("Action",
LineupBox(NCol(1),
// OK button
Button Box("OK",
lsl_mat = J(4,1, .);
lsl_mat[1] = Eval(lsl1 << Get);
lsl_mat[2] = Eval(lsl2 << Get);
lsl_mat[3] = Eval(lsl3 << Get);
lsl_mat[4] = Eval(lsl4 << Get);
usl_mat = J(4,1, .);
usl_mat[1] = Eval(usl1 << Get);
usl_mat[2] = Eval(usl2 << Get);
usl_mat[3] = Eval(usl3 << Get);
usl_mat[4] = Eval(usl4 << Get);
// Store summary statistics
tpListY = colListY << Get Items;
tpMean = J(4, 1, 0);
tpSD = J(4, 1, 0);
for (i=1, i <= nitems(tpListY), i++,
one_col = tpListY[i];
Meani = Col Mean(Column(dt, one_col));
SDi = Col Std Dev(Column(dt, one_col));
tpMean[i] = Meani;
tpSD[i] = SDi;
);
Dlg << CloseWindow
),
// Cancel button
Button Box("Cancel", Dlg << CloseWindow),
Spacer Box(Size(10,10)),
// Remove button
Button Box("Remove", collistY << RemoveSelected)
)
),
)
)
)
);
//correlation matrix
corr = multivariate(
Y(Eval List(tpListY)),
estimation method("Row-wise"),
matrix format("Square"),
scatterplot matrix(0)
);
corr.run = corr << run;
corr.rep = corr.run << report;
corr.mat = corr.rep["Correlations"][matrix box(1)] << get(1);
//only used to launch profiler
prof.x = J(2,4 ,1);
prof.tbl = as table(prof.x, << column names(tpListY), << invisible);
prof.tbl << new column("Y",
Formula( :TP1 + :TP2 + :TP3 + :TP4)
);
prof.tbl = current data table();
random reset(1234);
//specify multivariate data from summary statistics
sim.design = Profiler(
Y(:Y),
Invisible
);
sim.design << Simulator(
1,
Factors(
TP1 << multivariate( tpMean[1], tpSD[1]),
TP2 << multivariate( tpMean[2], tpSD[2]),
TP3 << multivariate( tpMean[3], tpSD[3]),
TP4 << multivariate( tpMean[4], tpSD[4]),
),
X Correlations(
1,
tpListY,
corr.mat
),
N Runs(10000)
);
//Make data table
report( sim.design )["Simulate to Table"][button box( 1 )] << click( 1 );
sim.dt = data table( 1 );
sim.dt << set name( "Simulated multivariate data" );
sim.dt << delete columns({"Y","Obj"});Résultats attendus par rapport aux résultats réels :
expectedvsactualexpectedvsactualattendu vs réel
Automatisation et scriptExploration et visualisation des donnéesRe : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @angello ,
Très beau! J'aime bien sûr le code plus court et plus élégant (je ne suis pas si doué pour ça, cependant). Par curiosité, avez-vous vérifié si les résultats du travail avec la moyenne et les écarts-types et la matrice de corrélation donnent les (approximativement) mêmes données simulées que le travail avec uniquement la moyenne et la matrice de covariance ?
Désolé, cette autre approche n'a pas fonctionné, mais heureux que vous ayez trouvé une bonne solution qui soit portable pour d'autres données avec lesquelles vous travaillez. Je teste une modélisation sur les données simulées pour voir comment elle se compare aux modèles construits sur les données réelles. Je peux voir où cela pourrait être très utile lorsque l'ensemble de données réelles est relativement petit et que les données simulées peuvent vous donner une chance de construire au moins un modèle pas si terrible qui peut être déployé tôt puis mis à jour à mesure que davantage de données arrivent . Autrement dit, plutôt que d'attendre pendant des mois qu'un ensemble de données suffisamment volumineux soit généré. Parfois, il est utile d'avoir un modèle en place, même s'il n'est pas « parfait ».
Merci pour la discussion et les points d'apprentissage!
Bonne chance!,
DS
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @SDF1 ,
Je n'aurais jamais pensé à cette approche, bien faite. En ce qui concerne la fenêtre de dialogue, je pense que vous avez raison, il faudra y regarder de plus près. Il s'est avéré que c'était moins un casse-tête d'éviter la plate-forme Profiler tous ensemble, alors que c'était une bonne idée, cela n'a pas marché pour moi. Voici le même résultat mais avec moins d'agitation (similaire aux étapes que je prends pour implémenter dans R) et seulement le vecteur moyen et la matrice de covariance nécessaires comme entrées.
//tpListY is variables.<BR /><BR />cov = multivariate(
Y(eval list(tpListY)),
estimation method("Row-wise"),
matrix format("Lower Triangular"),
scatterplot matrix(1)
);
cov << covariance matrix(1);
cov.run = cov << run;
cov.rep = cov.run << report;
cov.mat = cov.rep["Covariance Matrix"][matrix box(1)] << get(1);
random reset(1234);
//generate X = (X1, . . . , Xn) where X ∼ MNn(µ, Σ) using the Cholesky decomposition of Σ
//to find (nxn) matrix, C, such that C*C` = Σ.
//let Z = (Z1, . . . , Zn)` where the Zi’s are IID N(µ, 1) for i = 1, . . . , n.
//mean.M is mean vector.
sim.n = 1e4;
dummy.mat = j(1,sim.n,1);
mean.mat = mean.M*dummy.mat;
n.means = n row(mean.M);
sim.C = cholesky(cov.mat);
sim.Z = j(n.means, sim.n, random normal());
sim.X = sim.C*sim.Z;
sim.X2 = sim.X + mean.mat;
sim.Xt = transpose(sim.X2);
as table(sim.Xt, << column names(tpListY));
Je préfère utiliser moins de code pour faire le même travail, donc c'était plus attrayant que la route Profiler. Espérons que cela facilite la mise en œuvre ailleurs.
Merci encore,
ange
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @angello ,
Je pense que j'ai pu élaborer un script évolutif sur N colonnes. je donne @SP une quantité ÉNORME de crédit pour l'aide à la généralisation de la partie corrélation du Profiler. Ce fil est ici .
Il existe deux scripts, une version autonome comme celle que vous avez implémentée, mais sans les variables supplémentaires que vous aviez dans votre message d'origine, ainsi qu'un script qui peut s'exécuter à partir d'une table de données elle-même. Le autonome est ci-dessous et celui à exécuter à partir de la table de données se trouve dans la table de données Gendt.jmp. Cela fonctionne à la fois avec votre table de données à 4 colonnes et l'autre table de données que j'ai créée avec 11 colonnes. J'ai essayé de généraliser également le script autonome pour les tables de données avec d'autres types de colonnes.
Names Default To Here( 1 );
// Expression to clear all current settings
clearRoles = Expr( ColListY << RemoveAll );
// Expression to store the current settings in global variables
recallRoles = Expr(
::ycolRecall = ColListY << GetItems
);
//get data table
Try( Close( Data Table( dt ) ) );
If( Is Empty( dt ),
Try( dt = Open(), Throw( "No data found" ) )
);
//Find the number of columns in the data table
ncol = N Col( dt );
ColList = dt << Get Column Names( Numeric, Continuous );
//Dialog Window.
Dlg = New Window( "New Window",
<<RETURN result=""></RETURN>
De plus, je pense que l'erreur Button Box que vous recevez est liée à l'appel <
J'espère que cela aide, c'était vraiment cool et j'ai beaucoup appris. Je sais que je vais certainement pouvoir l'utiliser pour mon travail que je fais !
Merci!,
DS
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @angello ,
C'est exactement ce qui m'est venu à l'esprit quand j'ai réalisé ce que vous vouliez faire avec la structure de corrélation. Je voudrais m'inspirer de votre idée et la modifier en fonction de certains des problèmes spécifiques auxquels je suis confronté. J'ai posté dans un autre fil sur la généralisation à N entrées. Je pense que je suis assez proche, mais pas tout à fait là. J'ai des difficultés à le mettre à l'échelle lors de l'appel de X Correlations() et de la définition des valeurs de moyenne et de développement standard pour les facteurs.
Vous trouverez ci-joint une table de données et un script de maquette sur lesquels je travaille, tous basés sur votre script d'origine. Peut-être que vous pouvez trouver les erreurs que je fais? J'aimerais voir cela fonctionner pour un nombre arbitraire de colonnes, ce serait très utile pour les données historiques, comme vous le soulignez.
Merci!,
DS
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @SDF1 ,
Je simule fréquemment des jeux de données multivariés à des fins de modélisation (réglage du modèle entre eux), généralement basés sur certains paramètres historiques. Ce script n'était qu'une solution simple pour servir ces données fictives. Je n'ai pas de cas d'utilisation spécifique pour le moment, mais j'ai l'intention de mettre à l'échelle ce script à n dimensions et de l'utiliser potentiellement comme un outil fonctionnel module Je peux les intégrer dans des scripts plus élaborés qui utilisent des techniques à grand échantillon. Compte tenu des contraintes liées à l'envoi de vecteurs moyenne/sd et de la matrice de corrélation à la plate-forme Profiler, je recourrai probablement à l'écriture explicite des opérations linéaires afin de mettre à l'échelle la simulation à n dimensions.
Salutations,
ange
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @angello ,
Excellente solution, et j'aurais aimé me souvenir de le faire de cette façon. J'ai dû faire quelque chose de similaire lors de l'écriture d'un script pour automatiser certains réglages de modèle. Le EvalInsert() et les caractères d'échappement pour les guillemets et ^^ pour insérer des valeurs ont été très utiles. Je ne l'utilise pas souvent et j'ai oublié cette façon particulière de faire les choses.
Par curiosité, pourquoi avez-vous besoin de générer des données simulées comme celle-ci avec la structure de corrélation spécifiée. Je suis très intéressé, car cela m'a donné quelques idées sur la façon d'intégrer cela dans certaines choses sur lesquelles je travaille.
Merci!,
DS
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @SDF1 ,
Merci pour l'aide au dépannage, très appréciée. J'ai joué avec des fonctions similaires comme Eval, Eval Expr( Expr(x) ) , et Evalinsert et trouvé une solution en forçant la ou les variables de colonne et de matrice à évaluer avant de les envoyer à Profiler (qui Corrélations X semble accepter). J'ai appliqué la même solution ci-dessus pour rendre mon profileur flexible pour différents noms de colonnes. Maintenant, ma structure de corrélation est maintenue dans les données simulées.
new.design = evalinsert(
"\[sim.design << Simulator(
1,
Factors(
Name( "^col1^" ) << multivariate( tpMean[1], tpSD[1]),
Name( "^col2^" ) << multivariate( tpMean[2], tpSD[2]),
Name( "^col3^" ) << multivariate( tpMean[3], tpSD[3]),
Name( "^col4^" ) << multivariate( tpMean[4], tpSD[4]),
),
X Correlations(
1,
^tpListY^,
^corr.mat^
),
N Runs(10000)) ]\");
eval(parse(new.design));
Merci encore,
EA
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @angello ,
Merci pour le tableau de données. Je peux recréer votre problème comme vous le mentionnez. Une chose que je remarque est que lorsque vous exécutez le simulateur, il ne crée pas l'histogramme à côté du profileur, contrairement à l'exemple de bande de roulement dans l'index d'aide sur les corrélations X.
Je pense qu'il se passe deux choses :
1. appeler tpListY
2. appeler corr.mat
Je ne sais pas pourquoi, mais je pense que vous devez "épeler" explicitement la liste des corrélations X dans votre code et cela inclut la matrice de corrélation. Ainsi, au lieu d'appeler tpListY, vous devez la remplacer par {TP1, TP2 , TP3, TP4}. De même, vous devez mettre la matrice de corrélation réelle 4x4 (ou NxN) entre les crochets [].
Je pensais que faire quelque chose comme Parse(tpListY[1]) fonctionnerait, mais je n'arrive pas à le faire fonctionner, même avec un Eval() enroulé autour de lui. Je ne peux le faire fonctionner automatiquement que si je mets le code JSL comme {TP1, TP2, TP3, TP4}. Notez que lorsque vous insérez la matrice de corrélation NxN, elle utilise en fait le triangle inférieur gauche de la matrice pour remplir le tableau.
J'ai aussi pensé qu'appeler les éléments du corr.mat pourrait fonctionner, comme dans corr.mat[1], etc., mais cela ne fonctionne pas non plus. Si j'essaie cela, j'obtiens une erreur de jeton de matrice non valide, et je ne sais pas vraiment pourquoi, car les éléments de corr.mat sont des nombres.
Le code ci-dessous (j'ai modifié votre fonction pour la modifier un peu) fonctionne pour fournir la sortie attendue, mais cela n'aide pas votre désir de passer d'un système 4x4 à un système NxN.
names default to here(1);
Try( Close( Data Table(dt) ) );
If( Is Empty( dt ),
Try( dt = Open(), Throw( "No data found" ) )
);
ncol = NCol(dt);
//Dialog Window.
Dlg = New Window("New Window",
<< Modal,
BorderBox(left(3), top(2),
V List Box(
TextBox("Simulate multivariate data"),
HListBox(
VListBox(
PanelBox("Select variables",
colListData = ColListBox(all,nLines,(min(ncol,10)))
),
),
PanelBox("Cast Selected Variables",
LineupBox(NCol(2), Spacing(3),
ButtonBox("Variables", colListY << Append(colListData << Get Selected)),
colListY = ColListBox(nLines(6), "numeric"))
),
//specifications - not in use.
PanelBox("Enter Specifications",
Spacer Box(Size(10, 1)),
HListBox(
VListBox(
Spacer Box(Size(5, 10)),
lsl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
lsl4 = Number Edit Box(, 3)
),
SpacerBox(Size(10,10)),
VListBox(
Spacer Box(Size(5, 10)),
usl1 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl2 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl3 = Number Edit Box(, 3),
Spacer Box(Size(5, 10)),
usl4 = Number Edit Box(, 3)
)
),
),
PanelBox("Action",
LineupBox(NCol(1),
// OK button
Button Box("OK",
lsl_mat = J(4,1, .);
lsl_mat[1] = Eval(lsl1 << Get);
lsl_mat[2] = Eval(lsl2 << Get);
lsl_mat[3] = Eval(lsl3 << Get);
lsl_mat[4] = Eval(lsl4 << Get);
usl_mat = J(4,1, .);
usl_mat[1] = Eval(usl1 << Get);
usl_mat[2] = Eval(usl2 << Get);
usl_mat[3] = Eval(usl3 << Get);
usl_mat[4] = Eval(usl4 << Get);
// Store summary statistics
tpListY = colListY << Get Items;
tpMean = J(4, 1, 0);
tpSD = J(4, 1, 0);
for (i=1, i <= nitems(tpListY), i++,
one_col = tpListY[i];
Meani = Col Mean(Column(dt, one_col));
SDi = Col Std Dev(Column(dt, one_col));
tpMean[i] = Meani;
tpSD[i] = SDi;
);
Dlg << CloseWindow
),
// Cancel button
Button Box("Cancel", Dlg << CloseWindow),
Spacer Box(Size(10,10)),
// Remove button
Button Box("Remove", collistY << RemoveSelected)
)
),
)
)
)
);
//correlation matrix
corr = multivariate(
Y(Eval List(tpListY)),
estimation method("Row-wise"),
matrix format("Square"),
scatterplot matrix(0)
);
corr.run = corr << run;
corr.rep = corr.run << report;
corr.mat = corr.rep["Correlations"][matrix box(1)] << get(1);
//only used to launch profiler
prof.x = J(200,4 ,1);
prof.tbl = as table(prof.x, << column names(tpListY), << invisible);
prof.tbl << new column("Y",
Formula( :TP1+:TP2^2-:TP3+:TP4*Random Normal(0,2))
);
prof.tbl = current data table();
random reset(1234);
//specify multivariate data from summary statistics
sim.design = Profiler( Y( :Y ), Invisible );
sim.design << Simulator(
1,
Factors(
TP1 << multivariate( tpMean[1], tpSD[1] ), TP2 << multivariate( tpMean[2], tpSD[2] ),
TP3 << multivariate( tpMean[3], tpSD[3] ), TP4 << multivariate( tpMean[4], tpSD[4] ),
),
Responses( Y << No Noise ),
Automatic Histogram Update( 1 ),
X Correlations( 1, {TP1, TP2, TP3, TP4},
[1 0.6401843997 0.670478399654806 0.6405126152, 0.6401843997 1 0.9443055859 0.8815992957, 0.6704783997 0.9443055859 1 0.9355872238, 0.6405126152 0.8815992957 0.9355872238 1]
),
N Runs( 10000 ),
Simulate
);
//Make data table
report( sim.design )["Simulate to Table"][button box( 1 )] << click( 1 );
sim.dt = data table( 1 );
sim.dt << set name( "Simulated multivariate data" );
sim.dt << delete columns({"Y","Obj"});Il doit y avoir un moyen de le faire, puisque vous pouvez appeler les éléments de tpMean et tpSD pour remplir le bruit multivarié des facteurs. Je pense que quelqu'un avec plus d'expérience dans JSL pourrait être nécessaire pour commenter cela.
Enfin, je pense que vous avez raison à propos de l'une des boîtes à boutons, mais je ne pouvais pas l'identifier exactement non plus - j'étais plus concentré sur la résolution des problèmes tpListY et corr.mat ! 
Je suis vraiment intéressé par ce que vous découvrez.
Bonne chance,
DS
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @SDF1 ,
Je n'ai pas fait preuve de diligence raisonnable avant de publier - voici un échantillon de 10 lignes à partir des exemples de données (4 X; TP1-TP4). Le script actuel est limité à 4 variables, mais j'espère pouvoir l'adapter à N variables à l'avenir. Cet exemple de table de données recréera mon problème. Je pense que l'erreur de nom non résolue provient de la boîte de dialogue (peut-être des boutons Annuler/Supprimer), mais je n'ai pas trouvé la cause première.
Merci,
EA
Re : Comment spécifier une matrice de corrélation dans Profiler pour la simulation ?Salut @angello ,
C'est une question intéressante, et j'aimerais essayer d'aider si je peux, mais je ne suis pas en mesure de reproduire votre problème. Lorsque j'essaie d'exécuter votre script, il me demande d'ouvrir une table de données à partir du répertoire de données d'exemple. Un problème ici est que je ne sais pas avec quelle table de données vous travaillez et que je n'aurai pas le même problème. Pouvez-vous fournir le tableau de données avec lequel vous travaillez ?
Si je sélectionne une table de données à partir des exemples de données - par exemple, le fichier example.jmp du processus gaussien 2D, la fenêtre de dialogue suivante demande de convertir les colonnes en rôles, mais lorsque je clique sur OK, j'obtiens l'erreur qu'il y a un non résolu name Nom en trop ou évaluation de 'Button', Button(-1) /*###*/. Ensuite, une autre erreur apparaît à la ligne 124 de votre code où elle n'aime pas la commande d'envoi sim.design << Simulator() .
Apparemment, vous avez une table de données où cela fonctionne. Pouvez-vous le partager? Ou donnez plus de détails sur la table que vous utilisez pour générer la sortie que vous avez montrée dans votre message ?
Merci!,
DS