2009-10-10 32 views
3

在Python中,我需要生成一個dict,它將一個字母映射到該字母的預定義「one-hot」表示形式。通過圖示的方式,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的方式做同樣的事情?

回答

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

可讀性很強。 +1 – 2009-10-10 20:43:21

+0

不錯。我想我在函數式編程中嘗試了一個醜陋的嘗試。儘管你的版本更易讀。 – 2009-10-10 20:51:54

+0

'ascii_uppercase'的使用是一個很好的接觸(我甚至不知道它存在),但我不確定這比原始代碼更具可讀性。列表理解簡潔,但也非常有表現力。使用明確的循環使得代碼的目的在我眼中不太清晰。 – bcat 2009-10-10 20:57:58

0

這似乎很清楚,簡潔,Pythonic對我來說。

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)) 

特別是,有一個代碼很多擠進這兩條線。您可以嘗試Introduce Explaining Variable重構。或者可能是extract method

這裏有一個例子:

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)) 

雖然你可能與我的不同意命名。

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))