Одно горячее кодирование с использованием numpy
Если вход равен нулю, я хочу создать массив, который выглядит так:
[1,0,0,0,0,0,0,0,0,0]
и если вход 5:
[0,0,0,0,0,1,0,0,0,0]
Для вышеизложенного я написал:
np.put(np.zeros(10),5,1)
но это не сработало.
Есть ли способ, который может быть реализован в одной строке?
Ответы
Ответ 1
Обычно, когда вы хотите получить горячую кодировку для классификации в машинное обучение, у вас есть массив индексов.
import numpy as np
nb_classes = 6
targets = np.array([[2, 3, 4, 0]]).reshape(-1)
one_hot_targets = np.eye(nb_classes)[targets]
Теперь one_hot_targets
array([[[ 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 1., 0.],
[ 1., 0., 0., 0., 0., 0.]]])
.reshape(-1)
должен быть уверен, что у вас есть правильный формат меток (у вас также может быть [[2], [3], [4], [0]]
). -1
- особое значение, которое означает "положить все остальное в этом измерении". Поскольку есть только один, он выравнивает массив.
Решение для копирования-вставки
def get_one_hot(targets, nb_classes):
return np.eye(nb_classes)[np.array(targets).reshape(-1)]
Ответ 2
Что-то вроде:
np.array([int(i == 5) for i in range(10)])
Должен сделать трюк.
Но я полагаю, что существуют другие решения, использующие numpy.
edit: причина, по которой ваша формула не работает: np.put ничего не возвращает, он просто изменяет элемент, указанный в первом параметре. Хороший ответ при использовании np.put()
:
a = np.zeros(10)
np.put(a,5,1)
Проблема заключается в том, что она не может быть выполнена в одной строке, так как вам нужно определить массив, прежде чем передать его в np.put()
Ответ 3
Проблема заключается в том, что вы сохраняете свой массив нигде. Функция put
работает на месте массива и ничего не возвращает. Поскольку вы никогда не даете вашему массиву имя, вы не можете его обработать позже. Итак, это
one_pos = 5
x = np.zeros(10)
np.put(x, one_pos, 1)
будет работать, но тогда вы можете просто использовать индексирование:
one_pos = 5
x = np.zeros(10)
x[one_pos] = 1
По моему мнению, это был бы правильный способ сделать это, если нет особых причин для этого в качестве одного лайнера. Это также может быть проще для чтения и чтения кода является хорошим кодом.
Ответ 4
np.put
мутирует свой массив arg на месте. В Python он является обычным для функций/методов, которые выполняют мутацию in-place для возврата None
; np.put
придерживается этого соглашения. Поэтому, если a
является 1D-массивом, и вы делаете
a = np.put(a, 5, 1)
то a
будет заменено на None
.
Ваш код аналогичен этому, но он передает неименованный массив в np.put
.
Компактный и эффективный способ делать то, что вам нужно, - это простая функция, например:
import numpy as np
def one_hot(i):
a = np.zeros(10, 'uint8')
a[i] = 1
return a
a = one_hot(5)
print(a)
Выход
[0 0 0 0 0 1 0 0 0 0]
Ответ 5
Используйте np.identify
или np.eye
. Вы можете попробовать что-то подобное с вашим входом i, а размер массива s:
np.identify(s)[i:i+1]
Например, print(np.identity(5)[0:1])
приведет к:
[[ 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
Если вы используете TensorFlow, вы можете использовать tf.one_hot
: https://www.tensorflow.org/api_docs/python/array_ops/slicing_and_joining#one_hot
Ответ 6
Внимательно просмотрев руководство, вы увидите, что np.put
не возвращает значение. Хотя ваша техника в порядке, вы получаете доступ к None
вместо массива результатов.
Для одномерного массива лучше просто использовать прямую индексацию, особенно для такого простого случая.
Вот как переписать свой код с минимальной модификацией:
arr = np.zeros(10)
np.put(arr, 5, 1)
Вот как сделать вторую строку с индексированием вместо put
:
arr[5] = 1
Ответ 7
Вы можете использовать List comprehension:
[0 if i !=5 else 1 for i in range(10)]
превращается в
[0,0,0,0,0,1,0,0,0,0]
Ответ 8
import time
start_time = time.time()
z=[]
for l in [1,2,3,4,5,6,1,2,3,4,4,6,]:
a= np.repeat(0,10)
np.put(a,l,1)
z.append(a)
print("--- %s seconds ---" % (time.time() - start_time))
#--- 0.00174784660339 seconds ---
import time
start_time = time.time()
z=[]
for l in [1,2,3,4,5,6,1,2,3,4,4,6,]:
z.append(np.array([int(i == l) for i in range(10)]))
print("--- %s seconds ---" % (time.time() - start_time))
#--- 0.000400066375732 seconds ---
Ответ 9
Я не уверен, что производительность, но следующий код работает, и он опрятен.
x = np.array([0, 5])
x_onehot = np.identity(6)[x]