亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

數組元素的重復拷貝:matlab中的游程解碼

數組元素的重復拷貝:matlab中的游程解碼

慕容3067478 2019-07-02 11:21:53
數組元素的重復拷貝:matlab中的游程解碼我試圖使用“值”數組和“計數器”數組向數組中插入多個值。例如,如果:a=[1,3,2,5]b=[2,2,1,3]我要一些函數的輸出c=somefunction(a,b)成為c=[1,1,3,3,2,5,5,5]a(1)遞歸b(1)次,a(2)遞歸b(2)次等.在MATLAB中有一個內置函數來實現這個功能嗎?如果可能的話,我想避免使用for循環。我嘗試過“repmat()”和“kron()”的變體,但都沒有用。這基本上是Run-length encoding.
查看完整描述

3 回答

?
largeQ

TA貢獻2039條經驗 獲得超8個贊

問題陳述

我們有一系列的價值觀,vals以及奔跑的長度,runlens:

vals     = [1,3,2,5]runlens  = [2,2,1,3]

中的每個元素都需要重復。vals中的每個對應元素的時間。runlens..因此,最后的產出將是:

output = [1,1,3,3,2,5,5,5]

前瞻性方法

使用matlab最快的工具之一是cumsum在處理不規則模式的矢量化問題時非常有用。在所述問題中,不規則性伴隨著runlens.

現在,利用cumsum,我們需要在這里做兩件事:初始化zeros并將“適當”值放置在零數組的“key”位置,以便在“cumsum“如果應用,我們將得到一個最后的重復數組。valsrunlens時代。

步驟:讓我們對上面提到的步驟進行編號,為未來的方法提供一個更簡單的視角:

1)初始化零數組:長度必須是多少?因為我們在重復runlens時間,零數組的長度必須是所有值的總和。runlens.

2)查找關鍵位置/索引:現在這些關鍵位置是零位數組中每個元素從vals開始重復。因此,為了runlens  = [2,2,1,3],映射到零數組的關鍵位置是:

[X 0 X 0 X X 0 0] % where X's are those key positions.

3)找出合適的值:最后的釘子在使用前要錘打。cumsum就是把“適當的”價值觀放在這些關鍵的位置上。既然我們要cumsum不久之后,如果你仔細想想,你就需要一個differentiated版本values帶著diff,所以cumsum關于那些把我們的values..由于這些區分值將放置在由runlens使用后的距離cumsum我們會讓每個人vals元素重復runlens時間作為最終輸出。

解碼

以下是上述所有步驟的實現-

% Calculate cumsumed values of runLengths. % We would need this to initialize zeros array and find key positions later on.clens = c
umsum(runlens)% Initalize zeros arrayarray = zeros(1,(clens(end)))% Find key positions/indiceskey_pos = [1 clens(1:end-1)+1]% Find appro
priate valuesapp_vals = diff([0 vals])% Map app_values at key_pos on arrayarray(pos) = app_vals% cumsum array for final outputoutput = cum
sum(array)

預分配哈克

可以看出,上面列出的代碼使用了帶零的預分配?,F在,根據這個無文件的matlab博客關于更快的預分配,一個人可以實現更快的預分配-

array(clens(end)) = 0; % instead of array = zeros(1,(clens(end)))

結束語:功能代碼

為了結束一切,我們將有一個緊湊的函數代碼來實現這樣的游程解碼。

function out = rle_cumsum_diff(vals,runlens)clens = cumsum(runlens);idx(clens(end))=0;idx([1 clens(1:end-1)+1]) = diff([0 vals]);out = cu
msum(idx);return;

標桿

基準代碼

下面列出的是基準測試代碼,用于比較所述運行時和加速比。cumsum+diff在本文中通過其他cumsum-only基方法在……上面MATLAB 2014B-

datasizes = [reshape(linspace(10,70,4).'*10.^(0:4),1,[]) 10^6 2*10^6]; %fcns = {'rld_cumsum','rld_cumsum_diff'}; % approaches to be benchm
arkedfor k1 = 1:numel(datasizes)
    n = datasizes(k1); % Create random inputs
    vals = randi(200,1,n);
    runs = [5000 randi(200,1,n-1)]; % 5000 acts as an aberration
    for k2 = 1:numel(fcns) % Time approaches  
        tsec(k2,k1) = timeit(@() feval(fcns{k2}, vals,runs), 1);
    endendfigure,      % Plot runtimesloglog(datasizes,tsec(1,:),'-bo'), hold onloglog(datasizes,tsec(2,:),'-k+')set(gca,'xgrid','on'),
    set(gca,'ygrid','on'),xlabel('Datasize ->'), ylabel('Runtimes (s)')legend(upper(strrep(fcns,'_',' '))),title('Runtime Plot')figure,  
        % Plot speedupssemilogx(datasizes,tsec(1,:)./tsec(2,:),'-rx')        
        set(gca,'ygrid','on'), xlabel('Datasize ->')legend('Speedup(x) with cumsum+diff over cumsum-only'),title('Speedup Plot')

關聯函數代碼rld_cumsum.m:

function out = rld_cumsum(vals,runlens)index = zeros(1,sum(runlens));index([1 cumsum(runlens(1:end-1))+1]) = 1;out = vals(cumsum(index));
return;

運行時和加速圖



結論

建議的方法似乎使我們在cumsum-only方法,這是關于3x!

為什么這是新的cumsum+diff基于基礎的方法比以前更好cumsum-only接近?

嗯,原因的本質在于cumsum-only需要將“累計”值映射到vals..在新的cumsum+diff基于方法,我們正在做diff(vals)相反,matlab只對其進行處理。n元素(其中n是運行長度的數目)與sum(runLengths)的元素數。cumsum-only接近時,這個數字必須是這個數字的許多倍。n因此,這一新方法的顯著加速!


查看完整回答
反對 回復 2019-07-02
?
侃侃無極

TA貢獻2051條經驗 獲得超10個贊

我不知道內置函數,但有一個解決方案:

index = zeros(1,sum(b));index([1 cumsum(b(1:end-1))+1]) = 1;c = a(cumsum(index));

說明:

首先創建與輸出數組長度相同的零向量(即b)。然后,將它們放在第一個元素中,每個后續元素表示一個新的值序列的開始在輸出中的位置。向量的累積和index然后可以用來索引到a,復制每個值所需的次數。

為了清晰起見,這就是各種向量對于ab在問題中:

        index = [1 0 1 0 1 1 0 0]cumsum(index) = [1 1 2 2 3 4 4 4]
            c = [1 1 3 3 2 5 5 5]

編輯:為了完整起見另一種選擇阿瑞芬,但是這似乎需要花費20到100倍的時間才能運行到上面的向量長達10,000個元素的解決方案:

c = arrayfun(@(x,y) x.*ones(1,y),a,b,'UniformOutput',false);c = [c{:}];


查看完整回答
反對 回復 2019-07-02
  • 3 回答
  • 0 關注
  • 1053 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號