How can I hot code in Matlab?

Often you are given a vector of integer values ​​representing your labels (aka classes), for example

[2; 1; 3; 3; 2] 

and you want the hot to encode this vector so that each value is represented by the character 1 in the column indicated by the value in each row of the label vector, for example

 [0 1 0; 1 0 0; 0 0 1; 0 0 1; 0 1 0] 
+6
source share
5 answers

To save speed and memory, you can use bsxfun in combination with eq to accomplish the bsxfun same thing. Although your eye solution may work, your memory usage grows quadratically with the number of unique values ​​in X

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

Or as an anonymous function if you prefer:

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

Or, if you are on Octave (or MATLAB R2016b and later), you can use automatic broadcasting and just do the following, as suggested by @Tasos.

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

Benchmark

Here is a quick test showing the performance of different answers with different number of elements on X and different number of unique values ​​in 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 

results

If you need an unsharp bsxfun output, then it's best, but if you can use the sparse matrix (without converting to a full matrix), then this is the fastest and most memory-efficient option.

enter image description here

+14
source

You can use the identification matrix and index in it using the input / label vector, for example, if the label vector X is a random integer vector

 X = randi(3,5,1) ans = 2 1 2 3 3 

then hot coding X

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

which is conveniently defined as a function using

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

EDIT:

Although the solution above works in Octave, you can change it for Matlab as follows

 I = eye(max(X)); I(X,:) 
+4
source

I think this is fast, especially when the size of the matrix grows:

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

or

 Y = full(sparse(1:numel(X), X,1)); 
+2
source

Just submit a sub2ind solution to satisfy your curiosity :)
But I like your solution better: p

 >> 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 
+1
source

Just in case, someone is looking for a 2D case (like me):

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

gives a single-string encoded matrix along the third dimension.

0
source

All Articles