2015-05-15 120 views
0

我試圖編寫一個循環在Matlab中迭代地解決了零和一個最佳矢量。這是我的代碼關於在Matlab中的循環結構的迭代過程

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中具有最低比率的元素。我一直需要,直到沒有比例爲負。
我需要另一個循環,還是我想念一些東西?

我希望我的問題很清楚,告訴我你是否需要我解釋更多。

預先感謝您幫助新手程序員。

編輯

我認爲我需要添加一些形式,而循環的爲好。但我看不出如何構造這個。這是流動,我想

與所有項目包括(s(i) = 1對於所有的i),計算HI,CI和標準誤差,並列出的比值,排除項目i(s(I) = 0),其對應於最低負比率。
隨着新的,包括所有的一個,但一個零,計算HI,CI和標準誤差,並列出比率,排除項目我,這對應於最低的負比率。
隨着新的,現在包括所有的一個,但兩個零,重複該過程。
做到這一點,直到沒有排除的比例爲負數。

希望它現在變得更清楚。

+1

我不會100%關注正在發生的事情,但我強烈懷疑您的問題與嘗試修改循環索引有關。實際上,我不確定當你在循環中修改'i'時,MATLAB(或者其他任何具有這種形式的for循環語法的語言)會發生什麼,但是我認爲在下一次迭代期間它很可能只是無論如何,它會被設置爲接下來的任何事情。所以在你的情況下,我懷疑循環體在'〜(s(i)== 0)的情況下不會重複,正如你似乎打算的那樣。我建議切換到'i = 1;而我<= N; ...;結束' –

+0

我對循環索引進行了修改,因爲如果它先前已設置爲零,我不想將(i)'設置爲1。但我猜這是一種不好的習慣,對吧? – eshy

+0

如果你只是把循環的內部放在'if s(i)〜= 0'循環中,它會起作用嗎? – David

回答

0

好的。在列出我的代碼之前,我想經歷幾件事情。這些只是如何會試圖做到這一點。不一定是最好的方式,或者甚至是最快的方式(儘管我認爲它會很快)。我試圖保持代碼中的結構,所以你可以很好地遵循它(即使我可能將所有計算融合到一個函數或行中)。

說我用我的代碼一些特點:

  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點乘以v矢量與A每一列。 WW_都是與A大小相同的矩陣,但第一個將會更快(通常)。

  2. 預先計算輟學:我做了select一個矩陣,之前它是一個向量。這使我可以使用邏輯結構形成一個變量included~(eye(N))產生一個單位矩陣並且否定它。通過邏輯地「選擇」和「選擇」,然後$ i $ th列被選中,並且$ i $ th元素被刪除。

  3. 您明確計算weights'*s作爲每個for-loop中的分母。通過使用上述矩陣來計算,我們現在可以做一個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); 

如果由於某種原因,它不起作用,請讓我知道。

+0

非常感謝你的教訓!然而,我確實收到錯誤: 使用bsxfun時出錯 兩個輸入數組的非單例尺寸必須相互匹配。 測試錯誤(第30行) HI = bsxfun(@rdivide,(item_c'* V),sum(V)'); item_c是一個矩陣。可能是什麼問題呢? – eshy

+0

對不起,計算'V'變量時出錯了。另外,我認爲'sum(V)''應該是'sum(V)'。我認爲應該這樣做......再次抱歉。 – aepound

+0

謝謝@aepound!現在我得到這個錯誤 錯誤使用 - 矩陣尺寸必須一致。 測試錯誤(第34行) standarderror_afterex = sqrt(var(HI - CM)); – eshy