Цикл Python быстрее, чем Pandas - PullRequest
0 голосов
/ 11 июня 2018

Приведенный ниже код покажет, что использование цикла python быстрее, чем использование Pandas.Мое понимание до того, как я проверил это, было другим.Так что мне интересно, я неправильно использую панды для этой операции?Приведенный ниже код показывает, что решение Pandas работает примерно в 7 раз медленнее:

Pandas time  0.0008931159973144531
Loop time    0.0001239776611328125

Код:

import pandas as pd
import numpy as np
import time
import torch

batch_size = 5
classes = 4
raw_target = torch.from_numpy(np.array([1, 0, 3, 2, 0]))
rows = np.array(range(batch_size))

t0 = time.time()
zeros = pd.DataFrame(0, index=range(batch_size), columns=range(classes))
zeros.iloc[[rows, raw_target.numpy()]] = 1
t1 = time.time()

print("Pandas time ", t1-t0)
t0 = time.time()

target = raw_target.numpy()
zeros = np.zeros((batch_size, classes), dtype=np.float64)
for zero, target in zip(zeros, target):
    zero[target] = 1

t1 = time.time()
print("Loop  time  ", t1-t0)

Код использует PyTorch, поскольку реальный код, в котором существует проблема, использует PyTorch.Что может быть лучшим / оптимальным решением для этого примера?Результирующая матрица:

[[0. 1. 0. 0.]
 [1. 0. 0. 0.]
 [0. 0. 0. 1.]
 [0. 0. 1. 0.]
 [1. 0. 0. 0.]]

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

В зависимости от вашего варианта использования, все, что работает через PyTorch, может быть выгодным (например, для сохранения всех вычислений на GPU).

Решение только для PyTorch будет следовать синтаксису numpy (то есть zeros[rows, raw_target] = 1.):

import numpy as np
import torch

batch_size = 5
classes = 4
raw_target = torch.from_numpy(np.array([1, 0, 3, 2, 0]))
rows = torch.range(0, batch_size-1, dtype=torch.int64)

x = torch.zeros((batch_size, classes), dtype=torch.float64)
x[rows, raw_target] = 1.

print(x.detach())
# tensor([[ 0.,  1.,  0.,  0.],
#         [ 1.,  0.,  0.,  0.],
#         [ 0.,  0.,  0.,  1.],
#         [ 0.,  0.,  1.,  0.],
#         [ 1.,  0.,  0.,  0.]], dtype=torch.float64)
0 голосов
/ 11 июня 2018

Вы действительно должны ожидать, что код pandas, работающий с большими данными, будет быстрее, чем перебирать его и архивировать с помощью Python.Одна из причин заключается в том, что Pandas / Numpy могут работать с базовыми непрерывными данными, в то время как с циклом for у вас есть накладные расходы на создание всех объектов Python.Вы не видите этого в своем профилировании, так как данные вашего примера слишком малы, поэтому меры в основном представляют собой установочный код.

При выполнении профилирования времени вы должны позаботиться о том, чтобы вы измеряли именно то, что вас интересуети что ваши меры повторяемы (не утоплены в шуме).

Здесь у вас очень мало данных (только 5x5), тогда как ваши фактические данные, вероятно, намного больше.

Несколько советов:

  • не измерять установочный код (например, создание объекта pandas, что, вероятно, выполняется только один раз)
  • измерять с помощью iPython %timeit, чтобы получить статистическую информацию, а неизмерение шума
  • измерение с данными, достаточно большими, чтобы увидеть разницу в том, что вы измеряете.нет необходимости оптимизировать операции с матрицей 5x5

Что касается практического решения вашей проблемы, pandas в любом случае использует только numpy для представления данных.Вы можете пропустить панд и перейти непосредственно к numpy:

zeros[rows, target] = 1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...