NumPy - 从2D NumPy数组创建1-hot张量

3

我有一个numpy 2D数组,其值的范围从0到59。

对于那些熟悉深度学习和特别是图像分割的人-我从.png图像创建数组(称其为L),每个像素的值L[x,y]表示该像素所属的类别(共60个类别)。

我想创建一个1-hot张量-Lhot,其中仅当(L[x,y] == z)时(Lhot[x,y,z] == 1),否则为0。

我想使用某种广播/索引(1,2行)创建它-不使用循环。

它应该在功能上等同于此代码片段(Dtype对应于L):

Lhot = np.zeros((L.shape[0], L.shape[1], 60), dtype=Dtype)
for i in range(L.shape[0]):
    for j in range(L.shape[1]):
        Lhot[i,j,L[i,j]] = 1

有人有想法吗? 谢谢!

2个回答

4

使用纯粹的 numpy 更快更清洁的方法

Lhot = np.transpose(np.eye(60)[L], (1,2,0))

使用多维度的一位热编码会遇到一个问题,就是它们会变得非常大、非常稀疏,并且没有好的方法来处理超过二维的稀疏数组在numpy/scipy(或者sklearn或许多其他机器学习包中)。(你)真的需要一个n-d的一位热编码吗?


我正在创建一个LMDB文件,用于FCN-8s网络中图像分割的标签(该网络使用PASCAL-VOC 2012数据集进行训练)。最终的softmax层需要2个参数 - 网络得分和这些标签,并且我发现得分维度为{width,height,numClasses},这使我认为它必须是1-hot表示法,并且我必须以相同的方式构建标签。 - Itai Mesery

3

由于典型的一热编码是针对1D向量定义的,所以您只需要将您的矩阵展开,使用scikit-learn(或任何其他拥有一热编码的库)的一热编码器,然后重新整形回来。

from sklearn.preprocessing import OneHotEncoder
n, m = L.shape
k = 60
Lhot = np.array(OneHotEncoder(n_values=k).fit_transform(L.reshape(-1,1)).todense()).reshape(n, m, k)

当然你也可以手动完成此操作。
n, m = L.shape
k = 60
Lhot = np.zeros((n*m, k)) # empty, flat array
Lhot[np.arange(n*m), L.flatten()] = 1 # one-hot encoding for 1D
Lhot = Lhot.reshape(n, m, k) # reshaping back to 3D tensor

谢谢,我现在正在运行它,但是需要一些时间,因为我有很多图片(标签)需要运行。 - Itai Mesery
问题是你真的需要它吗?你也可以让你的系统(我想是神经网络)接受ID而不是one-hot数据。将one-hot处理表达为网络的一部分也会节省大量RAM/时间。 - lejlot
你说得没错,但我正在使用caffe上预定义的网络运行它,似乎那里的3D softmax期望标签是1-hot表示法,以符合分数blob的维度。 - Itai Mesery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接