对列表进行编码的优雅方式。

问题描述 投票:1回答:1

目前我正试图对一个包含单元素的列表进行热编码。有什么干净的Pythonic方法可以从表示方式2转到表示方式1?此外,我还想知道从表示1到表示2的简洁方法。

表示法1

[[1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 ...
 [0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0. 0.]]
(256, 6)

表述2

[[0.]
 [3.]
 [3.]
 ...
 [2.]
 [3.]
 [2.]]
(256, 1)
python numpy encoding one-hot-encoding
1个回答
3
投票

使用纯粹的基本条件列表理解,对于表示方式1到2。

r1 = [[1., 0., 0., 0., 0., 0.],
      [0., 0., 0., 1., 0., 0.],
      [0., 0., 0., 0., 1., 0.]]
len_r1l = len(r1[0]) # length of each sublist, here 6

r2 = [[0], [3], [4]]

r1_r2 = [[i] for l in r1 for i in range(len_r1l) if l[i]==1]
>>> [[0], [3], [4]]

和表征2到1:

r2_r1 = [[1. if i==idx[0] else 0 for i in range(len_r1l)] for idx in r2]
>>> [[1.0, 0, 0, 0, 0, 0],
     [0, 0, 0, 1.0, 0, 0],
     [0, 0, 0, 0, 1.0, 0]]

等价地使用numpy,与... np.非零:

# convert to array
r1_np = np.asarray(r1)
r2_np = np.asarray(r2)

r1_r2 = np.nonzero(r1_np)[1]
>>> array([0, 3, 4])

r2_r1 = np.zeros_like(r1_np)
r2_r1[np.arange(r1_r2.shape[0]),r1_r2] = 1.
>>> array([[1., 0., 0., 0., 0., 0.],
           [0., 0., 0., 1., 0., 0.],
           [0., 0., 0., 0., 1., 0.]])

如果你真的想保持它 list 使用 np.ndarray.tolist。 方法。

r1_r2.tolist()
>>> [0, 3, 4]
r2_r1.tolist()
>>> [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
     [0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
     [0.0, 0.0, 0.0, 0.0, 1.0, 0.0]]

以这些答案为基准,打算投入的规模。256 清楚地显示了numpy的效率。

# representation 1 to 2
%timeit [[i] for l in r1 for i in range(len_r1l) if l[i]==1]
>>> 199 µs ± 431 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.nonzero(r1_np)[1]
>>> 13 µs ± 32.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# representation 2 to 1
%timeit [[1. if i==idx[0] else 0 for i in range(len_r1l)] for idx in r2]
>>> 243 µs ± 820 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit r2_r1 = np.zeros_like(r1_np); r2_r1[np.arange(r1_r2.shape[0]),r1_r2] = 1.
>>> 9.42 µs ± 15.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

希望这对你有帮助


1
投票

表示方式1--> 2:

如果你知道每一个列表都有一个且只有一个。1,您可以使用 list.index 在...中 名单理解:

list_of_lists = [  # Your initial list
    [1, 0, 0],
    [0, 1, 0],
    [0, 0, 1]
]

list_of_ones_indices = [[lst.index(1)] for lst in list_of_lists]
# [0, 1, 2]

代表2-> 1:

该numpy解决方案 可能更接近你的需求。如果你想要一个纯Python的解决方案,你可以这样做。

index_list = [1, 2, 3]
LENGTH = 6
one_hot_list = []

# This can also be achieved with a list comprehension and range()
for index in index_list:
    one_hot = [0] * LENGTH
    one_hot[index[0]] = 1
    one_hot_list.append(one_hot)

print(one_hot_list)
# [
#     [0, 1, 0, 0, 0, 0],
#     [0, 0, 1, 0, 0, 0],
#     [0, 0, 0, 1, 0, 0]
# ]

0
投票

为了将表示方式2转换为表示方式1,你可以使用类似于... keras.np_utils.to_categorical:

>>> y = [0, 1, 2]
>>> np_utils.to_categorical(y)
array([[ 1., 0., 0.],
       [ 0., 1., 0.],
       [ 0., 0., 1.]])

0
投票

:国际联合检查组。

np.argmax(a, axis=1)[:, None]

使用@Yacola设置。

r1 = [[1., 0., 0., 0., 0., 0.],
      [0., 0., 0., 1., 0., 0.],
      [0., 0., 0., 0., 1., 0.]]

a = np.array(r1)
np.argmax(a, axis=1)[:, None]

输出:

array([[0],
       [3],
       [4]])

0
投票

使用numpy,

rep_2 = np.where(condition)[1].reshape(rep1.shape[0], 1)

哪儿 condition 可以用很多方式来说明,其中有。

  • rep_1 == 1
  • rep_1 !=0

根据你的要求。如果你愿意,可以将rep_2转换为一个列表。

© www.soinside.com 2019 - 2024. All rights reserved.