2016-08-15 293 views
6

通常你給出代表你的標籤(也稱爲類)的整數值的向量,例如我如何在Matlab中熱編碼?

[2; 1; 3; 3; 2] 

和要熱一個編碼此載體中,使得每個值表示由在一個1柱由標籤向量的每一行中的值指示的,例如

[0 1 0; 
1 0 0; 
0 0 1; 
0 0 1; 
0 1 0] 
+0

你嘗試過什麼嗎? –

+0

是的,我一直嘗試不同的方法與sub2ind,但最終使用索引到身份矩陣如下。 – osipov

回答

4

可以使用單位矩陣和索引到它使用輸入/標籤向量,例如,如果標籤矢量X是一些隨機整數矢量

X = randi(3,5,1) 

ans = 

    2 
    1 
    2 
    3 
    3 

然後,下面將熱一個編碼X

eye(max(X))(X,:) 

其可以方便地定義爲使用

hotone = @(v) eye(max(v))(v,:) 

編輯功能:

儘管上述作品的溶液在八度,你有你修改它的Matlab如下

I = eye(max(X)); 
I(X,:) 
+0

只是指出鏈接操作不能在matlab中工作,所以你將不得不拆分你的單線程。不錯的解決方案。 –

+1

@TasosPapastylianou謝謝......我原本是用Octave寫的。剛剛編輯答案與unchained操作。 – osipov

+0

@Suever內存使用情況絕對重要。在機器學習問題的情況下,標籤集的基數通常是可管理的,所以這種「熱門編碼」方法是一種簡單的入門方法。一個更優化的解決方案是在Matlab/Octave之外進行一些操作。 – osipov

1

剛剛發佈的sub2ind解決方案太滿足您的好奇心:)
但我喜歡你的更好的解決方案:對

>> X = [2,1,2,3,3]' 
>> LinearIndices = sub2ind([length(X),3], [1:length(X)]', X); 
>> tmp = zeros(length(X), 3); 
>> tmp(LinearIndices) = 1 
tmp = 

    0  1  0 
    1  0  0 
    0  1  0 
    0  0  1 
    0  0  1 
14

對於速度和節省內存,你可以使用bsxfuneq相結合來完成一樣。儘管您的eye解決方案可能有效,但您的內存使用量將以X中的唯一值數量的平方增長。

Y = bsxfun(@eq, X(:), 1:max(X)); 

或者,如果你喜歡一個匿名函數:

hotone = @(X)bsxfun(@eq, X(:), 1:max(X)); 

或者,如果你在八度(或MATLAB版本R2016b及更高版本),你可以利用自動播放的,只是做正如@Tasos所建議的那樣。

Y = X == 1:max(X); 

基準

在這裏是表示與上X變化元件的數目和在X不同的唯一值的數目的各種回答的效果的快速基準。

function benchit() 

    nUnique = round(linspace(10, 1000, 10)); 
    nElements = round(linspace(10, 1000, 12)); 

    times1 = zeros(numel(nUnique), numel(nElements)); 
    times2 = zeros(numel(nUnique), numel(nElements)); 
    times3 = zeros(numel(nUnique), numel(nElements)); 
    times4 = zeros(numel(nUnique), numel(nElements)); 
    times5 = zeros(numel(nUnique), numel(nElements)); 

    for m = 1:numel(nUnique) 
     for n = 1:numel(nElements) 
      X = randi(nUnique(m), nElements(n), 1); 
      times1(m,n) = timeit(@()bsxfunApproach(X)); 

      X = randi(nUnique(m), nElements(n), 1); 
      times2(m,n) = timeit(@()eyeApproach(X)); 

      X = randi(nUnique(m), nElements(n), 1); 
      times3(m,n) = timeit(@()sub2indApproach(X)); 

      X = randi(nUnique(m), nElements(n), 1); 
      times4(m,n) = timeit(@()sparseApproach(X)); 

      X = randi(nUnique(m), nElements(n), 1); 
      times5(m,n) = timeit(@()sparseFullApproach(X)); 
     end 
    end 

    colors = get(0, 'defaultaxescolororder'); 

    figure; 

    surf(nElements, nUnique, times1 * 1000, 'FaceColor', colors(1,:), 'FaceAlpha', 0.5); 
    hold on 
    surf(nElements, nUnique, times2 * 1000, 'FaceColor', colors(2,:), 'FaceAlpha', 0.5); 
    surf(nElements, nUnique, times3 * 1000, 'FaceColor', colors(3,:), 'FaceAlpha', 0.5); 
    surf(nElements, nUnique, times4 * 1000, 'FaceColor', colors(4,:), 'FaceAlpha', 0.5); 
    surf(nElements, nUnique, times5 * 1000, 'FaceColor', colors(5,:), 'FaceAlpha', 0.5); 

    view([46.1000 34.8000]) 

    grid on 
    xlabel('Elements') 
    ylabel('Unique Values') 
    zlabel('Execution Time (ms)') 

    legend({'bsxfun', 'eye', 'sub2ind', 'sparse', 'full(sparse)'}, 'Location', 'Northwest') 
end 

function Y = bsxfunApproach(X) 
    Y = bsxfun(@eq, X(:), 1:max(X)); 
end 

function Y = eyeApproach(X) 
    tmp = eye(max(X)); 
    Y = tmp(X, :); 
end 

function Y = sub2indApproach(X) 
    LinearIndices = sub2ind([length(X),max(X)], [1:length(X)]', X); 
    Y = zeros(length(X), max(X)); 
    Y(LinearIndices) = 1; 
end 

function Y = sparseApproach(X) 
    Y = sparse(1:numel(X), X,1); 
end 

function Y = sparseFullApproach(X) 
    Y = full(sparse(1:numel(X), X,1)); 
end 

結果

如果你需要一個非稀疏輸出bsxfun表現最好,但如果你能使用sparse矩陣(無需轉換到全矩陣),那麼這是最快和最內存高效的選擇。

enter image description here

+0

這是爲什麼?他只是做一個簡單的索引操作 –

+1

哦,好的,你在談論眼圖矩陣的大小。 –

+0

@suever我認爲你的意思是內存使用量增長的二次方,因爲eye(max(X))佔用最大(X)^ 2內存。指數內存使用率將是c^max(X) – osipov

2

我覺得這是快特別是當矩陣尺寸長:

Y = sparse(1:numel(X), X,1); 

Y = full(sparse(1:numel(X), X,1)); 
0

萬一有人找2D情況下(我是) :

X = [2 1; ... 
    3 3; ... 
    2 4] 
Y = zeros(3,2,4) 
for i = 1:4 
    Y(:,:,i) = ind2sub(X,X==i) 
end 

沿着第三維給出一個單熱編碼矩陣。