Горячее кодирование по произвольному измерению с помощью NumPy - PullRequest
2 голосов
/ 23 апреля 2019

Учитывая массив с произвольным количеством измерений, я хотел бы иметь возможность горячего кодирования любого из этих измерений. Например, скажем, у меня есть массив a формы (10, 20, 30, 40) Я мог бы хотеть одним горячим образом кодировать второе измерение, то есть преобразовать a так, чтобы результат содержал только значения 0 и 1 и a[i, :, j, k] содержит ровно одну нулевую запись для каждого выбора i, j и k (в позиции предыдущего максимального значения вдоль этого измерения).

Я думал о том, чтобы сначала получить a.argmax(axis=1), а затем использовать np.ogrid, чтобы превратить это в индексы, указывающие на максимумы, но я не могу выяснить детали. Меня также беспокоит потребление памяти при таком подходе.

Есть ли простой способ сделать это (в идеале требующий немного дополнительной памяти)?

1 Ответ

3 голосов
/ 24 апреля 2019

Вот один из способов с array-assignment -

def onehotencode_along_axis(a, axis):
    # Setup o/p hot encoded bool array 
    h = np.zeros(a.shape,dtype=bool)
    idx = a.argmax(axis=axis)

    # Setup same dimensional indexing array as the input
    idx = np.expand_dims(idx, axis) # Thanks to @Peter

    # Finally assign True values
    np.put_along_axis(h,idx,1,axis=axis)
    return h

Образцы выполняются в 2D случае -

In [109]: np.random.seed(0)
     ...: a = np.random.randint(11,99,(4,5))

In [110]: a
Out[110]: 
array([[55, 58, 75, 78, 78],
       [20, 94, 32, 47, 98],
       [81, 23, 69, 76, 50],
       [98, 57, 92, 48, 36]])

In [112]: onehotencode_along_axis(a, axis=0)
Out[112]: 
array([[False, False, False,  True, False],
       [False,  True, False, False,  True],
       [False, False, False, False, False],
       [ True, False,  True, False, False]])

In [113]: onehotencode_along_axis(a, axis=1)
Out[113]: 
array([[False, False, False,  True, False],
       [False, False, False, False,  True],
       [ True, False, False, False, False],
       [ True, False, False, False, False]])

Образец запуска для проверки в более высоком (многомерном) 5D случае-

In [114]: np.random.seed(0)
     ...: a = np.random.randint(11,99,(2,3,4,5,6))
     ...: for i in range(a.ndim):
     ...:     out = onehotencode_along_axis(a, axis=i)
     ...:     print np.allclose(out.sum(axis=i),1)
True
True
True
True
True

Если вам нужен окончательный вывод в виде массива int с 0 с и 1 с, используйте представление для логического выходного массива:

onehotencode_along_axis(a, axis=0).view('i1') и т. д.

...