如何在 Matlab 中进行热编码? [复制]

Posted

技术标签:

【中文标题】如何在 Matlab 中进行热编码? [复制]【英文标题】:How can I hot one encode in Matlab? [duplicate] 【发布时间】:2016-12-21 05:42:23 【问题描述】:

例如,通常会给你一个整数值向量,代表你的标签(又名类)

[2; 1; 3; 3; 2]

并且您想对这个向量进行热编码,例如,每个值在由标签向量的每一行中的值指示的列中由 1 表示,例如

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

【问题讨论】:

你有什么尝试吗? 是的,我一直在尝试使用 sub2ind 的不同方法,但最终使用了对单位矩阵的索引,如下所示。 【参考方案1】:

为了速度和节省内存,您可以使用bsxfuneq 组合来完成同样的事情。虽然您的eye 解决方案可能有效,但您的内存使用量会随着X 中唯一值的数量呈二次方增长。

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

如果您愿意,也可以作为匿名函数:

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

或者,如果您使用的是 Octave(或 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 矩阵(无需转换为完整矩阵),那么这是最快且内存效率最高的选项。

【讨论】:

这是为什么呢?他只是在做一个简单的索引操作 哦,好吧,你说的是眼睛矩阵的大小。 @suever 我认为您的意思是内存使用量呈二次增长,因为 eye(max(X)) 占用 max(X)^2 内存。指数内存使用量为 c^max(X) @osipov 是的,你是对的。更新。我还添加了一个基准来显示这些技术的相对性能。 @TasosPapastylianou 是的,我指的是 eye 不必要地庞大。【参考方案2】:

您可以使用单位矩阵并使用输入/标签向量对其进行索引,例如,如果标签向量 X 是某个随机整数向量

X = randi(3,5,1)

ans =

   2
   1
   2
   3
   3

那么,下面将热一编码X

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

可以方便地定义为一个函数使用

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

编辑:

虽然上面的解决方案在 Octave 中有效,但你可以为 Matlab 修改它,如下所示

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

【讨论】:

只指出链式操作在 matlab 中不起作用,因此您必须拆分单行。不错的解决方案。 @TasosPapastylianou 谢谢...我最初是用 Octave 编写的。刚刚用未链接的操作编辑了答案。 @Suever 内存使用绝对是需要牢记的重要因素。在机器学习问题的情况下,标签集的基数通常是可管理的,因此这种“热编码”方法是一种简单的入门方法。更理想的解决方案是在 Matlab/Octave 之外进行一些操作。 @osipov 在 MATLAB 中,最好从一开始就设计出可以很好扩展的东西,因为这样的事情很快就会失控(参见基准),不使用最佳的真的没有意义如果您有一个可以使用的解决方案。此外,正如基准所显示的,它是内存使用执行时间。【参考方案3】:

我认为这在矩阵维度增长时特别快:

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

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

【讨论】:

【参考方案4】:

只需发布sub2ind 解决方案即可满足您的好奇心 :) 但我更喜欢你的解决方案: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

【讨论】:

【参考方案5】:

以防万一有人正在寻找 2D 案例(就像我一样):

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

给出一个沿第 3 维的 one-hot 编码矩阵。

【讨论】:

以上是关于如何在 Matlab 中进行热编码? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何获得一个句子的热编码? [复制]

Julia DataFrames - 如何进行一次热编码?

如何在 R 中对多个分类变量进行一次热编码

如何使用 sklearn 对 CSV 文件中的多列进行一次热编码?

独热编码(one-hot)是什么?什么数据类型需要进行独热编码?pandas如何进行独热编码(one-hot)?

如何在 python 中对数字进行一次热编码?