Преобразовать один столбец в указанное c количество столбцов - PullRequest
2 голосов
/ 06 января 2020

Я пытаюсь преобразовать один столбец данных со значениями в range(0,5) в 6 столбцов в соответствии с их значением. Например, если его значение равно 0, первый столбец из этих шести один становится одним, а другой становится 0 и т. Д. Однако, поскольку форма моей цели (1034892, 1), это занимает много времени и даже иногда происходит сбой. Этот код работал для 500000 данных, но для этого количества это не так.

Есть ли способ сделать возможным для такого количества данных?

def convert_to_num_class(target):
    for i, value in enumerate(target):
        if i ==0:
            y_new =np.array( np.eye(6)[int(value[0])])
        else:
            y_new = np.vstack((y_new, np.eye(6)[int(value[0])]))
    return(y_new)

Ответы [ 3 ]

1 голос
/ 06 января 2020

Использование pandas get_dummies:

>>> target = np.random.randint(6, size=(10, 1))  # the original target is of shape (1034892, 1)
>>> target = target.flatten()
array([0, 1, 0, 0, 4, 3, 1, 5, 4, 5])

>>> pd.get_dummies(target).to_numpy()
array([[1, 0, 0, 0, 0],
       [0, 1, 0, 0, 0],
       [1, 0, 0, 0, 0],
       [1, 0, 0, 0, 0],
       [0, 0, 0, 1, 0],
       [0, 0, 1, 0, 0],
       [0, 1, 0, 0, 0],
       [0, 0, 0, 0, 1],
       [0, 0, 0, 1, 0],
       [0, 0, 0, 0, 1]])

В случае, если ваша цель не имеет всех значений в нужном диапазоне (как в приведенном выше примере, где target не имеет значение 2), будут отсутствовать столбцы для этих пропущенных значений. Один из обходных путей следующий:

>>> target = pd.Categorical(target, categories=np.arange(6))

>>> pd.get_dummies(target).to_numpy()
array([[1, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0],
       [1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0],
       [0, 0, 0, 1, 0, 0],
       [0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1],
       [0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1]])

Это очень быстро, даже если у вас есть target размера (1034892, 1).

0 голосов
/ 09 января 2020

Не нужно прибегать к pandas или keras, просто индексировать с помощью кортежа:

import numpy as np

categories = 6
N = 10
target = np.random.randint(categories, size=(N,1)) # this should be your data

y = np.zeros((N, categories), dtype=np.uint8)
mask = (np.arange(N), target.flatten())
y[mask] = 1

Проверка производительности:

def one_hot(target, categories=None): 
    target = target.flatten() 
    N = target.size 
    if categories is None:
        categories = target.max() - target.min() + 1 
    y = np.zeros((N, categories), dtype=np.uint8) 
    mask = (np.arange(N), target) 
    y[mask] = 1 
    return y 

N = 1034892
cats = 6
r = np.random.randint(cats, size=(N))

%timeit one_hot(r)
# 9.63 ms ± 187 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

import pandas as pd
%timeit pd.get_dummies(r).to_numpy()
# 18.2 ms ± 183 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
0 голосов
/ 09 января 2020

Я также решил это с помощью to_categorical из keras.utils.np_utils, и это занимает всего секунду для этого количества данных:

from keras.utils.np_utils import to_categorical
def convert_to_num_class(target):
target = target.astype(np.int)
return(to_categorical(target, len(np.unique(target))))
...