Не является тривиальной проблемой, поскольку данные являются несогласованными. Производительность зависит от длины . Возьмите пример квадратного проблемы: много, долго, регулярной и нули последовательность (n_iter==n_reg==lag_mean
):
import numpy as np
n_iter = 1000
n_reg = 1000
regular_sequence = np.arange(n_reg, dtype=np.int)
lag_mean = n_reg # mean length of zeros sequence
lag_sd = lag_mean/10 # standard deviation of zeros sequence length
lag_seq=np.int64(np.random.normal(lag_mean,lag_sd,n_iter)) # Sequence of lags lengths
Сначала ваше решение:
def seq_hybrid():
seqs = [np.concatenate((np.zeros(x, dtype=np.int), regular_sequence)) for x in lag_seq]
seq = np.concatenate(seqs)
return seq
Тогда чистый NumPy один:
def seq_numpy():
seq=np.zeros(lag_seq.sum()+n_iter*n_reg,dtype=int)
cs=np.cumsum(lag_seq+n_reg)-n_reg
indexes=np.add.outer(cs,np.arange(n_reg))
seq[indexes]=regular_sequence
return seq
A для зольного золя социологическое загрязнение:
def seq_python():
seq=np.empty(lag_seq.sum()+n_iter*n_reg,dtype=int)
i=0
for lag in lag_seq:
for k in range(lag):
seq[i]=0
i+=1
for k in range(n_reg):
seq[i]=regular_sequence[k]
i+=1
return seq
И как раз во время компиляции с Numba:
from numba import jit
seq_numba=jit(seq_python)
Тесты теперь:
In [96]: %timeit seq_hybrid()
10 loops, best of 3: 38.5 ms per loop
In [97]: %timeit seq_numpy()
10 loops, best of 3: 34.4 ms per loop
In [98]: %timeit seq_python()
1 loops, best of 3: 1.56 s per loop
In [99]: %timeit seq_numba()
100 loops, best of 3: 12.9 ms per loop
Ваше гибридное решение является столь же скоростью, как и чистый NumPy один в этом случае потому что производительность зависит, главным образом, от внутреннего цикла. И ваш (нули и конкатенаты) - это числовое. Как и ожидалось, решение python медленнее с традиционным значением около 40x. Но numpy здесь не является оптимальным, потому что он использует фантастическую индексацию, необходимую с несогласованными данными. В этом случае numba может помочь вам: минимальные операции выполняются на уровне C, для 120x коэффициент усиления на этот раз по сравнению с решением python.
Для других значений n_iter,n_reg
усилений фактора по сравнению с решением питона является:
n_iter= 1000, n_reg= 1000 : seq_numba 124, seq_hybrid 49, seq_numpy 44.
n_iter= 10, n_reg= 100000 : seq_numba 123, seq_hybrid 104, seq_numpy 49.
n_iter= 100000, n_reg= 10 : seq_numba 127, seq_hybrid 1, seq_numpy 42.
Возможно, стоит сначала генерировать нулевой инициализированный массив, а затем помещать 'regular_sequence' в тщательно выбранные случайные места в этом массиве? –
@Istrel, что вы будете делать, когда вы произнесете отрицательное число из своего 'N (10, 1)'? Шансы того, что это происходит, астрономически малы, но если эти параметры не исправлены, вы можете столкнуться с этой проблемой. Можно ли просто выбирать из однородного распределения по некоторому диапазону? –
@N. Wouda благодарит вас за предложение. В моем случае любое значение, меньшее или равное 0, будет означать отсутствие отставания между последовательными «регулярными» последовательностями. Итак, будет еще одна строка кода, которая заменит любое отрицательное значение 'lag_seq' на 0. – Istrel