如何在Profiler中指定相关矩阵进行仿真?你好,
我正在编写一个脚本,用于根据一组样本数据创建具有指定行数、均值/标准差向量和相关结构的多元正态数据。 我想利用Profiler平台中的模拟器通过以下步骤生成数据表:
- 计算每个变量的样本均值和标准差。
- 从样本数据生成相关矩阵。
- 使用 (1) 和 (2) 中的汇总统计来模拟多变量数据。
目前,我的脚本为每个变量生成具有适当平均值和标准差的模拟数据表,但我无法正确维护变量之间的相关结构。 我相信我的问题的原因是我如何指定 [ N×N相关性] 与X 相关性使用变量而不是显式指定相关矩阵(例如 [1 0.3 0, 0.3 1 0, 0 0 1]),但我的故障排除技巧让我没有解决方案。 下面提供了当前脚本以及预期与实际输出,欢迎就如何实现这些步骤提出任何建议:
杰士林:
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"});预期输出与实际输出:
expectedvsactualexpectedvsactual预期与实际
自动化和脚本编写数据探索和可视化回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@eangello ,
很不错! 我当然喜欢更短、更优雅的代码(尽管我不太擅长)。 出于好奇,您是否检查过使用均值和标准差以及相关矩阵的结果是否与仅使用均值和协方差矩阵提供了(大约)相同的模拟数据?
抱歉,这种其他方法没有成功,但很高兴您找到了一个很好的解决方案,可以移植到您正在使用的其他数据。 我正在对模拟数据进行一些建模测试,看看它与基于实际数据构建的模型有何不同。 我可以看到,当真实数据集相对较小并且模拟数据可以让您有机会至少构建一个不那么糟糕的模型时,这会非常有帮助,该模型可以尽早部署,然后随着更多数据的进入而更新。 也就是说,不必等待数月才能生成足够大的数据集。 有时,建立一个适当的模型是有价值的,即使它并不“完美”。
感谢大家的讨论和学习要点!
祝你好运!,
DS
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@SDF1 ,
我从来没有想到过这种方法,做得很好。 至于对话框窗口,我认为你是对的,我必须仔细看看。 事实证明,完全避开 Profiler 平台并不那么令人头疼,虽然这是一个好主意,但对我来说并不成功。 这是相同的结果,但没有那么麻烦(类似于我在 R 中实现的步骤),并且只需要均值向量和协方差矩阵作为输入。
//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));
我更喜欢使用更少的代码来完成相同的工作,因此这比 Profiler 路线更有吸引力。 希望这能让它在其他地方更容易实施。
再次感谢,
埃安杰洛
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@eangello ,
我想我已经能够编写一个可扩展到 N 列的脚本。 我给@多发性硬化症在概括分析器的相关部分方面提供了大量的帮助。 该线程是这里。
有两个脚本,一个是与您实现的脚本类似的独立版本,但没有原始帖子中的额外变量,另一个是可以从数据表本身运行的脚本。 独立版本如下,从数据表运行的版本位于 Gendt.jmp 数据表中。 它适用于您的 4 列数据表和我制作的 11 列数据表。 我还尝试将数据表的独立脚本概括为其他列类型。
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>
另外,我认为您收到的按钮框错误与对话窗口的 <
我希望这会有所帮助,这真的很酷,我从中学到了很多东西。 我知道我一定能够在我所做的工作中使用它!
谢谢!,
DS
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@eangello ,
当我意识到你想要对相关结构做什么时,这正是我的想法。 我想借用你的想法并根据我面临的一些具体问题进行修改。 我在另一个线程中发布了关于泛化到 N 个输入的内容。 我想我已经很接近了,但还没有完全实现。 在调用 X Correlations() 并设置因子的平均值和标准差值时,我很难扩展它。
附件是我正在工作的模型数据表和脚本,全部基于您的原始脚本。 也许你能发现我犯的错误? 我很高兴看到它适用于任意数量的列,正如您所指出的,这对历史数据非常有帮助。
谢谢!,
DS
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@SDF1 ,
我经常出于建模目的(其中的模型调整)模拟多变量数据集,通常基于一些历史参数。 该脚本只是一个提供模拟数据的简单解决方案。 我现在没有具体的用例,但我打算将此脚本扩展到 n 维,并可能将其用作函数模块我可以将其纳入使用大样本技术的更广泛的脚本中。 考虑到向 Profiler 平台发送均值/标准差向量和相关矩阵的限制,我可能会显式编写线性运算,以便将模拟扩展到 n 维。
问候,
埃安杰洛
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@eangello ,
很好的解决方案,我希望我记得这样做。 在编写脚本来自动化某些模型调整时,我必须做类似的事情。 用于插入值的 EvalInsert() 和引号的转义字符以及 ^^ 非常有用。 我只是不经常使用它并且忘记了那种特殊的做事方式。
出于好奇,为什么需要生成具有指定关联结构的模拟数据。 我很感兴趣,因为它给了我一些关于如何将其融入到我正在做的事情中的想法。
谢谢!,
DS
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@SDF1 ,
感谢您帮助解决问题,非常感谢。 我玩过类似的功能,比如求值,求值 Expr( Expr(x) ) ,和评估插入并找到了一个解决方案,通过在发送到 Profiler 之前强制对列和矩阵变量进行评估(其中X 相关性看来可以接受)。 我应用了上面相同的解决方案,使我的探查器能够灵活地适应不同的列名称。 现在我的相关结构保留在模拟数据中。
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));
再次感谢,
EA
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@eangello ,
感谢您提供数据表。 我可以按照您提到的方式重现您的问题。 我注意到的一件事是,当您运行模拟器时,它不会在分析器旁边创建直方图,这与 X Correlations 帮助索引中的轮胎花纹示例不同。
我认为有两件事正在发生:
1. 调用tpListY
2.调用corr.mat
我不确定为什么,但我认为您需要在代码中明确“拼写”出 X 相关性列表,其中包括相关矩阵。因此,您需要将其替换为 {TP1, TP2,而不是调用 tpListY ,TP3,TP4}。 同样,您需要将实际的 4x4(或 NxN)相关矩阵放在方括号 [] 之间。
我认为做类似 Parse(tpListY[1]) 的事情会起作用,但我无法让它工作,即使有一个 Eval() 包裹在它周围。 只有将 JSL 代码输入为 {TP1, TP2, TP3, TP4} 才能让它自动工作。 请注意,当您输入 NxN 相关矩阵时,它实际上使用矩阵的左下三角形来填充表格。
我还认为调用 corr.mat 的元素可能会起作用,如 corr.mat[1] 等,但这也不起作用。 如果我尝试这样做,我会收到无效的矩阵标记错误,并且不太确定原因,因为 corr.mat 的元素是数字。
下面的代码(我修改了您的函数以对其进行了一些更改)可以提供预期的输出,但它无助于您从 4x4 系统扩展到 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"});一定有办法做到这一点,因为您可以调用 tpMean 和 tpSD 的元素来填充因子的多元噪声。 我认为可能需要在 JSL 方面有更多经验的人对此发表评论。
最后,我认为您对其中一个按钮框的看法是正确的,但我也无法准确指出它 - 更专注于尝试解决 tpListY 和 corr.mat 问题! 
我对你的发现很感兴趣。
祝你好运,
DS
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@SDF1 ,
我在发布之前没有尽职调查 - 这是示例数据中的 10 行示例(4 X;TP1-TP4)。 当前脚本仅限于 4 个变量,但我希望能够将其扩展到氮未来的变数。 这个示例数据表将重现我的问题。 我相信未解决的名称错误来自对话框(可能是取消/删除按钮),但我还没有找到根本原因。
谢谢,
EA
回复:如何在 Profiler 中指定相关矩阵进行仿真?你好@eangello ,
这是一个有趣的问题,如果可以的话我想尝试提供帮助,但我无法重现您的问题。 当我尝试运行您的脚本时,它要求我从示例数据目录中打开数据表。 这里的一个问题是,我不知道您正在使用哪个数据表,并且不会遇到同样的问题。 您能提供您正在使用的数据表吗?
如果我从示例数据中选择一个数据表 - 例如 2D 高斯过程 example.jmp 文件,下一个对话窗口会要求将列转换为角色,但是当我单击“确定”时,我收到错误,表示存在未解决的问题name 超出的名称或“Button”的评估,Button(-1) /*###*/。 然后,代码中的第 124 行出现另一个错误,它不喜欢 sim.design << Simulator() 发送命令。
显然,您有一个可以实现此功能的数据表。 你能分享一下吗? 或者提供有关您使用哪个表来生成您在帖子中显示的输出的更多详细信息?
谢谢!,
DS