2015-06-02 1 views
1

У меня есть последовательность s = [4,3,1,0,5] и num_classes = 6 и я хочу, чтобы генерировать матрицу Numpy m в форме (len(s), num_classes), где m[i,j] = 1 if s[i] == j else 0.генерируют последовательность с помощью индексов/один горячего кодирования

Есть ли такая функция в Numpy, где я могу пройти s и num_classes?

Это также называется кодировкой 1-k или одноразовым.


timeit результаты:

def b(): 
    m = np.zeros((len(s), num_classes)) 
    m[np.arange(len(s)), s] = 1 
    return m 

In [57]: timeit.timeit(lambda: b(), number=1000) 
Out[57]: 0.012787103652954102 

In [61]: timeit.timeit(lambda: (np.array(s)[:,None]==np.arange(num_classes))+0, number=1000) 
Out[61]: 0.018411874771118164 

ответ

3

Так как вы хотите один 1 для каждой строки, вы можете фантазии-индекс, используя arange(len(s)) вдоль первой оси, а также с помощью s вдоль второй:

s = [4,3,1,0,5] 
n = len(s) 
k = 6 
m = np.zeros((n, k)) 
m[np.arange(n), s] = 1 
m 
=> 
array([[ 0., 0., 0., 0., 1., 0.], 
     [ 0., 0., 0., 1., 0., 0.], 
     [ 0., 1., 0., 0., 0., 0.], 
     [ 1., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 1.]]) 

m.nonzero() 
=> (array([0, 1, 2, 3, 4]), array([4, 3, 1, 0, 5])) 

Это можно считать использованием индекса (0,4), затем (1,3), затем (2,1), (3,0), (4,5).

+0

Любая хорошая причина для downvote на другой ответ? – Divakar

+0

Я играл с 'timeit', и это кажется самым быстрым решением. Благодаря! – Albert

+0

@Albert прохладно. Было бы неплохо, если бы вы могли добавить свои результаты времени на вопрос, для потомков – shx2

1

Вы можете использовать broadcasting -

(np.array(s)[:,None]==np.arange(num_classes))+0 

Sample пробег -

In [439]: s 
Out[439]: [4, 3, 1, 0, 5] 

In [440]: num_classes = 9 

In [441]: (np.array(s)[:,None]==np.arange(num_classes))+0 
Out[441]: 
array([[0, 0, 0, 0, 1, 0, 0, 0, 0], 
     [0, 0, 0, 1, 0, 0, 0, 0, 0], 
     [0, 1, 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]]) 
0

Принятый ответ не будет работать, если один горячее кодирование добавляет дополнительное измерение многомерного массива. Использование трансляции даст вам неожиданные результаты - https://scipy.github.io/old-wiki/pages/Cookbook/Indexing. Это решение элегантно, но не очень эффективно.

labels.shape # (80, 256, 10) 

def b(labels): 
    onehot = np.zeros((a,b,c,num_classes), dtype=float) 

    # This is the slow, dumb line: 
    (onehot_i, onehot_j, onehot_k) = np.ones(labels.shape).nonzero() 

    thehotone = labels[onehot_i, onehot_j, onehot_k] 
    onehot[onehot_i, onehot_j, onehot_k, thehotone] = 1 
    return onehot 
1

Brocasting все еще работает только делать

$ (этикетки [:,:,:, Ни] == np.arange (num_classes)) + 0