python — Калькулятор степени Херста
Несколько замечаний:
s_t = np.zeros(n)
и r_t = np.zeros(n)
больше, чем вам нужно. Поскольку вы на самом деле не используете значения массива, а только перезаписываете их, вы можете использовать здесь np.empty
.
Вы выполняете довольно много избыточной работы в цикле для
.
При вычислении s_t[i]
numpy в основном должен повторить все вычисления, которые он уже сделал для с_т[i-1]
. Если вы посмотрите на определение np.std
, вы увидите, что здесь играет роль среднее значение. Поскольку вы уже придумали хорошее решение для среднего значения, вы можете использовать его здесь:
s_t = np.empty(n) для я в диапазоне (n): s_t[i] = np.mean((sig[:i+1] - mean_t[i])**2) ... s_t = np.sqrt (s_t)
Я проверил это по исходному коду с помощью np.allclose
.
r_t
также имеет дополнительную работу, от которой можно избавиться.
x_t = y - t * mean_t[i] r_t[i] = np.ptp(x_t[:i + 1])
Все значения x_t
в [i+1:n]
вычисляются, но никогда не используются, поэтому вы можете сделать
r_t[i] = np.ptp(y[:i+1] - t [:i+1] * среднее_t[i])вместо
без изменения результата. Вы также можете написать это как два понимания списка:
s_t = np.sqrt( np.array([np.mean((sig[:i+1] - mean_t[i])**2) для i в диапазоне (n)]) ) r_t = np.array([np.ptp(y[:i+1] - t[:i+1] * mean_t[i]) для i в диапазоне(n)])
Или даже один, если вы хотите проявить немного творчества:
rs_t = np.array([ [ np.mean((sig[:i + 1] - mean_t[i])**2), np.ptp(y[:i + 1] - t[:i + 1] * mean_t[i]) ] для i в диапазоне (n) ]) rs_t [:, 0] = np.sqrt (rs_t [:, 0])
Полностью векторизованное вычисление x_t
Я придумал, начиная с
x_t = y.reshape(1, -1) - mean_t.reshape(-1, 1) @ t. reshape(1, -1) )
значительно медленнее, чем зацикленная версия.
На самом деле я не совсем уверен в остальной части кода с этого момента. Мне нужно будет присмотреться, чтобы дать значимый обзор производительности. В качестве первого нефункционального отзыва я хотел бы предложить вам подумать о более осмысленных именах переменных в будущем. Особенно в конце кода вокруг оптимизации методом наименьших квадратов, их довольно сложно понять.
Я замерял время разных версий этого алгоритма. Полный код теста можно найти в этой сути. Это то, что я получил до сих пор (за n=15360
):
база: 3,748915 с лучший_цикл: 2.605374 с двойной_лк: 2.430255с single_lc: 2,445943 с ----------------------- base_numba: 0,866583 с better_loop_numba: 0,813630 с double_lc_numba: 0,776361 с single_lc_numba*: Н/Д
Нижняя группа результатов использует numba, своевременный компилятор для кода Python, который иногда помогает ускорить выполнение циклов.