【问题标题】:Regarding loop structure in Matlab for an iterative procedure关于迭代过程的Matlab中的循环结构
【发布时间】:2015-05-15 02:29:42
【问题描述】:

我正在尝试在 Matlab 中编写一个循环,该循环迭代地求解零和一的最佳向量 s。这是我的代码

N = 150;
s = ones(N,1);
for i = 1:N
    if s(i) == 0
        i = i + 1;
    else
        i = i;
    end
    select = s;
    HI = (item_c' * (weights.*s)) * (1/(weights'*s));
    s(i) = 0;
    CI = (item_c' * (weights.*s)) * (1/(weights'*s));
    standarderror_afterex = sqrt(var(CI - CM));
    standarderror_priorex = sqrt(var(HI - CM));
    ratio = (standarderror_afterex - standarderror_priorex)/(abs(mean(weights.*s) - weights'*select));
    ratios(i) = ratio;
    s(i) = 1;
end

[M,I] = min(ratios);
s(I) = 0;

此代码将 s 中的元素设置为零,它具有最低的比率。但是我需要重新开始这个过程,使用带有一个零的新 s 来查找比率并排除 s 中比率最低的元素。我需要一遍又一遍,直到没有比率是负的。
我需要另一个循环,还是我错过了什么?

我希望我的问题足够清楚,如果您需要我解释更多,请告诉我。

提前感谢您帮助新手程序员。

编辑

我认为我还需要添加某种形式的 while 循环。但我看不出如何构建它。这就是我想要的流程

包含所有项目(s(i) = 1 表示所有 i),计算 HI、CI 和标准误并列出比率,排除对应于最低负比率的项目 i (s(I) = 0)。
使用新的 s,包括除一个零之外的所有 1,计算 HI、CI 和标准误并列出比率,排除对应于最低负比率的第 i 项。
使用新的 s,现在包括除两个零之外的所有 1,重复该过程。
这样做直到没有要排除的比率中的负元素为止。

希望现在更清楚了。

【问题讨论】:

  • 我没有 100% 关注正在发生的事情,但我强烈怀疑您的问题与尝试修改循环索引有关。当您在循环内修改i 时,我实际上不确定在 MATLAB(或任何其他具有这种 for 循环语法风格的语言)中会发生什么,但我认为在下一次迭代中它很可能只是无论如何,它都会被设置为下一步。因此,在您的情况下,我怀疑循环体不会像您预期的那样在 ~(s(i) == 0) 的情况下重复。我建议切换到类似i=1; while i<=N; ...; end
  • 我对循环索引进行了修改,因为如果之前已将 s(i) 设置为零,我不希望将其设置为 1。但我想这是一种不好的做法,对吧?
  • 如果你只是把循环的内部放在if s(i)~=0循环里面会起作用吗?

标签: matlab for-loop iteration


【解决方案1】:

好的。在列出我的代码之前,我想先做一些事情。这些正是 会尝试的方式。不一定是最好的方式,甚至是最快的方式(尽管我认为它会很快)。我试图保持你在代码中的结构,所以你可以很好地遵循它(即使我可能会将所有计算合并到一个函数或一行中)。

我在代码中使用的一些功能:

  1. bsxfun: 学习这个!它的工作原理令人惊叹,它可以加快代码速度,并使一些事情变得更容易。

    v = rand(n,1);
    A = rand(n,4);
    % The two lines below compute the same value:
    W = bsxfun(@(x,y)x.*y,v,A);
    W_= repmat(v,1,4).*A;
    

    bsxfun dot 将v 向量与A 的每一列相乘。 WW_ 都是与 A 大小相同的矩阵,但第一个会快得多(通常)。

  2. 预先计算辍学:我将select 制作为一个矩阵,之前它是一个向量。这使我可以使用逻辑结构形成一个变量included~(eye(N)) 产生一个单位矩阵并将其取反。通过使用 select 进行逻辑“与”运算,现在第 $i$th 列被选中,第 $i$th 元素被删除。

  3. 您在每个 for 循环中明确计算 weights'*s 作为分母。通过使用上面的矩阵来计算,我们现在可以做一个sum(W),其中W 在每一列中本质上是weights.*s

  4. 利用按列操作:var()sqrt() 函数都被编码为沿矩阵的列工作,以行向量的形式输出矩阵的操作。

好的。完整的东西。有任何问题请告诉我:

% Start with everything selected:
select = true(N);

stop = false; % Stopping flag:
while (~stop)
  % Each column leaves a variable out...
  included = ~eye(N) & select;  

  % This calculates the weights with leave-one-out:
  W = bsxfun(@(x,y)x.*y,weights,included);
  % You can comment out the line below, if you'd like...
  W_= repmat(weights,1,N).*included;  % This is the same as previous line.

  % This calculates the weights before dropping the variables:
  V = bsxfun(@(x,y)x.*y,weights,select);

  % There's different syntax, depending on whether item_c is a 
  %  vector or a matrix...
  if(isvector(item_c))
    HI = (item_c' * V)./(sum(V));
    CI = (item_c' * W)./(sum(W));
  else
    % For example: item_c is a matrix... 
    % We have to use bsxfun() again
    HI = bsxfun(@rdivide, (item_c' * V),sum(V));
    CI = bsxfun(@rdivide, (item_c' * W),sum(W));
  end

  standarderror_afterex = sqrt(var(bsxfun(@minus,HI,CM)));
  standarderror_priorex = sqrt(var(bsxfun(@minus,CI,CM)));
  % or:
  % 
  % standarderror_afterex = sqrt(var(HI - repmat(CM,1,size(HI,2))));
  % standarderror_priorex = sqrt(var(CI - repmat(CM,1,size(CI,2))));


  ratios = (standarderror_afterex - standarderror_priorex)./(abs(mean(W) - sum(V)));

  % Identify the negative ratios:
  negratios = ratios < 0;
  if ~any(negratios) 
    % Drop out of the while-loop:
    stop = true;
  else
    % Find the most negative ratio:
    neginds = find(negratios);
    [mn, mnind] = min(ratios(negratios));

    % Drop out the most negative one...
    select(neginds(mnind),:) = false;  
  end

end % end while(~stop)

% Your output:
s = select(:,1);

如果由于某种原因它不起作用,请告诉我。

【讨论】:

  • 非常感谢您的课程!但是,我确实收到了一个错误:使用 bsxfun 时出错 两个输入数组的非单一维度必须相互匹配。测试错误(第 30 行)HI = bsxfun(@rdivide, (item_c' * V),sum(V)'); item_c 是一个矩阵。可能是什么问题?
  • 抱歉,计算V 变量时出现错误。另外,我认为sum(V)' 应该只是sum(V)。我认为应该这样做......对不起,再次。
  • 谢谢@aepound!现在我得到这个错误错误使用 - 矩阵尺寸必须一致。测试错误(第 34 行)standarderror_afterex = sqrt(var(HI - CM));
  • CM的尺寸是多少?很可能我们也必须使用 bsxfun() 来执行减法......
  • 我认为这应该解决它....这本质上是我在重新设计算法以更快/更矢量化时所经历的过程...对不起。小事会抓住你! :)
猜你喜欢
  • 2013-08-16
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
相关资源
最近更新 更多