【问题标题】:Index when mean is constant均值恒定时的索引
【发布时间】:2020-01-22 14:46:03
【问题描述】:

我对 matlab 比较陌生。我找到了一组具有均值和标准差的 1E6 个随机数的连续均值。最初计算的平均值会波动,然后收敛到某个值。 我想知道平均值收敛的索引(即第 100 个位置)。我不知道该怎么做。

我尝试使用逻辑运算符,但我必须通过 1e6 个数据点。即使这样我仍然找不到索引。

Y_c= sigma_c * randn(n_r, 1) + mu_c; %Random number creation

Y_f=sigma_f * randn(n_r, 1) + mu_f;%Random number creation

P_u=gamma*(B*B)/2.*N_gamma+q*B.*N_q + Y_c*B.*N_c; %Calculation of Ultimate load

prog_mu=cumsum(P_u)./cumsum(ones(size(P_u))); %Progressive Cumulative Mean of system response

logical(diff(prog_mu==0)); %Find index

【问题讨论】:

  • 没有一个特定的索引可以让平均值“收敛”。收敛是一个极限过程;它是逐渐发生的,并且永远不会完全实现

标签: matlab statistics mean


【解决方案1】:

我怀疑问题在于平均值永远不会真正保持不变,而是会围绕“真实平均值”波动。因此,您很可能永远不会遇到累积平均值的两个连续值相同的情况。您应该做的是确定某个阈值,低于该阈值您认为平均值的波动大约等于零,并将累积平均值的差异与该值进行比较。例如:

epsilon = 0.01;
const_ind = find(abs(diff(prog_mu))<epsilon,1,'first');

其中 epsilon 将是您选择的阈值。 find 命令将返回累积平均值的变化首先下降到此阈值以下的索引。

编辑:正如所指出的,如果生成的前几个随机数使得它们之间的差小于 epsilon 值但尚未收敛,则此方法可能会失败。那么,我想建议一种不同的方法。

我们像以前一样计算累积均值,如下所示:

prog_mu=cumsum(P_u)./cumsum(ones(size(P_u)));

我们还像以前一样计算这些累积均值的差异:

df_prog_mu = diff(prog_mu);

现在,为了确保已实现转换,我们找到累积均值低于阈值的第一个索引epsilon并且所有后续均值也低于阈值。换一种说法,我们想在数组中 last 位置之后找到累积平均值高于阈值的索引:

conv_index = find(~df_prog_mu,1,'last')+1;

在此过程中,我们保证索引处的值以及所有后续值均收敛于您的预定阈值以下。

【讨论】:

  • 谢谢。我似乎仍然无法理解 find 功能是如何工作的。我在matlab上查看了find的帮助,仍然无法弄清楚。 '1' 表示 find 表达式中的什么?
  • 如果将逻辑矩阵传递给find 命令,它将返回所有为真元素的索引。 find 的第二个参数允许您限制返回的索引数量,因此在上面的示例中,1 表示它将仅返回矩阵中为真的第一个元素(即累积平均值的差异小于您的阈值)。 'first' 告诉find 返回第一个真值的索引(而不是'last',后者将返回纬度真值的索引。
  • 我现在更喜欢这个答案,尽管我必须承认我没有注意到那里的diff,它确实改变了一些事情。尽管如此,我仍然更喜欢做类似df_prog_mu = prog_mu - prog_mu(end) 的事情,假设最后一个平均值是最精确的。我认为这只是个人喜好...... :)
【解决方案2】:

我不会想象平均值会突然在单个索引处变得恒定。它不会渐近地接近一个常数值吗?我会推荐一个 for 循环来计算平均值(听起来你可能已经完成了这部分?),如下所示:

avg = [];
for k=1:length(x)
avg(k) = mean(x(1:k));
end

然后绘制连续平均值:

plot(avg)

hold on % this will allow us to plot more data on the same figure later

如果您试图找到连续平均值在真实平均值的特定范围内的点,请尝试以下操作:

Tavg = 5; % or whatever your true mean is
err = 0.01; % the range you want the consecutive mean to reach before we say that it "became constant"

inRange = avg>(Tavg-err) & avg<(Tavg+err); % gives you a binary logical array telling you which values fell within the range

q = 1000; % set this as high as you can while still getting a value for consIndex
constIndex = [];

for k=1:length(inRange)
if(inRange(k) == sum(inRange(k:k+q))/(q-1);)
constIndex = k;
end
end

下面的答案采用了类似的方法,但做出了不安全的假设,即落在该范围内的第一个值是函数开始收敛的值。任何值都可能随机落在该范围内。我们需要确保以下值也在该范围内。在上面的代码中,你可以编辑“q”和“err”来优化你的结果。我建议通过绘图仔细检查它。

plot(avg(constIndex), '*')

【讨论】:

  • 谢谢布雷特。但是我有点困惑。我尝试运行代码以便能够按照解释进行操作。我得到了这个错误。我创建了 x=1:100;因为您的初始代码没有给出 x 的范围。索引超出矩阵维度。堆栈错误(第 18 行) if(inRange(k) == sum(inRange(k:k+q))/(q-1));你是对的,平均值不会变得恒定,而是会波动。我对我的帖子进行了编辑。我确实用实现的数量绘制了我获得的平均值。波动最初会收敛。
  • 这是一种计算元素1:k 均值的昂贵方法。 OP 具有使用cumsum 执行相同操作的代码。不同的是,一个需要大约 N*N/2 次操作,另一个只需要 N 个。
  • @CrisLuengo 谁是 OP?
  • OP的意思是“原帖”,指的是页面顶部的问题。
  • 对不起,我没有检查我的代码(只是把它写在我的头上)。 x 应该是您的 100 万个随机数集。返回错误的 for 循环应该从 1:(length(inRange)-q) 开始。希望这会更好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 2014-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多