生成一个独热编码的字符串表示

3
在Python中,我需要生成一个将字母映射到预定义的“one-hot”表示的dict。举个例子,这个dict应该长这样:
{ 'A': '1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0',
  'B': '0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0', # ...
}

每个字母用一个字符表示一个二进制位。因此,每个字符串将包含 25 个零和一个 1。对应字母在字母表中的位置决定了 1 的位置。

我写了一些代码来生成这个结果:

# Character set is explicitly specified for fine grained control
_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
n = len(_letters)
one_hot = [' '.join(['0']*a + ['1'] + ['0']*b)
            for a, b in zip(range(n), range(n-1, -1, -1))]
outputs = dict(zip(_letters, one_hot))

有没有更高效/更简洁/更符合Python风格的方法来完成同样的事情?
4个回答

7
我认为这样更易读:
from string import ascii_uppercase

one_hot = {}
for i, l in enumerate(ascii_uppercase):
    bits = ['0']*26; bits[i] = '1'
    one_hot[l] = ' '.join(bits)

如果您需要一个更通用的字母表,只需枚举字符字符串,并将['0']*26替换为['0']*len(alphabet)

很好。我觉得我尝试了一种丑陋的函数式编程方式。不过你的版本要可读性更强。 - E.M.
使用 ascii_uppercase 是一个不错的点睛之笔(我甚至不知道它的存在),但我不确定这比原始代码更易读。列表推导式简洁,但也非常表达清晰。在我的眼中,使用显式循环会使代码的目的不太清晰。 - bcat

2
在Python 2.5及以上版本中,您可以使用条件运算符:
from string import ascii_uppercase

one_hot = {}
for i, c in enumerate(ascii_uppercase):
    one_hot[c] = ' '.join('1' if j == i else '0' for j in range(26))

1
one_hot = [' '.join(['0']*a + ['1'] + ['0']*b)
            for a, b in zip(range(n), range(n-1, -1, -1))]
outputs = dict(zip(_letters, one_hot))

特别是这两行代码中有很多代码。您可以尝试介绍解释变量重构。或者也可以使用提取方法

以下是一个示例:

def single_onehot(a, b):
    return ' '.join(['0']*a + ['1'] + ['0']*b)

range_zip = zip(range(n), range(n-1, -1, -1))
one_hot = [ single_onehot(a, b) for a, b in range_zip]
outputs = dict(zip(_letters, one_hot))

虽然您可能不同意我的命名。


-1

对我来说,这似乎非常清晰、简洁和符合 Python 风格。


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