#python #numpy #vectorization
#python #numpy #векторизация
Вопрос:
Я написал функцию, которая занимает слишком много времени при использовании с циклами for . Он добавляет векторы numpy (10,0) в виде строк на каждой итерации. Как я могу использовать векторизованное решение numpy для итераций, чтобы ускорить это?
Любой намек, почему приведенное ниже решение vstack-array работает даже медленнее, чем решение append-list?
TIA
import numpy as np
import time
n_iterations = 1000
n_cols = 10
def sample_func():
# Addition: please notice: the randon function is not important. It is only an example function. The real function is more complex and needs to replace for loops by a faster numpy solution.
row = np.random.rand(0,n_cols)
return row
#list solution: too slow
start_time_1 = time.time()
result_list = []
for i in range(n_iterations):
result_row = sample_func()
result_list.append(np.sort(result_row))
print("Run time = {}".format(time.time() - start_time_1))
#array solution: too slow
start_time_2 = time.time()
result_array = np.empty([0,n_cols])
for i in range(n_iterations):
result_row = sample_func()
result_array = np.vstack([result_array, np.sort(result_row)])
print("Run time = {}".format(time.time() - start_time_2))
TIA
Комментарии:
1. Избегайте добавления в целом.
np.sort
разрешает сортировку по оси.2. добавление списка добавляет ссылку / указатель на существующий список.
vstack
создает новый массив с полной копией. Используйте его только один раз, чтобы объединить массивы всего списка, а не постепенно.3. Пока ваша функция написана на Python и принимает только одну строку за раз, вы мало что можете сделать. Особенно, если это сложно, будут доминировать затраты на многократную оценку этой функции. Механизм итерации, такой как добавление списка, будет относительно незначительным потребителем времени.
Ответ №1:
В общем, вы не хотите добавлять к numpy
массивам. Перераспределение пространства для них занимает слишком много времени. Если вы знаете n_iterations
, вы можете выделить заранее, как это:
result_array = np.empty([n_iterations, n_cols])
for i in range(n_iterations):
result_array[i] = sample_func()
Но вы будете намного лучше «векторизировать» все, что есть, sample_func
чтобы принимать n-d ввод. for
циклы python
выполняются медленно. numpy
дает вам множество трюков, чтобы вставить ваши for
циклы в скомпилированный c
код (называемый «векторизацией»), но, не зная, что происходит в функции, мы не можем помочь вам ее векторизовать.
Ответ №2:
np.random.rand()
предназначен для возврата выходных данных любой желаемой формы — как и многие другие numpy
методы. Таким образом, вам не нужно объединять список одинаковой длины. Попробуйте:
r_numbers = np.random.rand(n_iterations, n_cols)
И для сортировки всех столбцов:
np.sort(r_numbers, axis=1)
Комментарии:
1. Большое спасибо. Я только попытался придумать простейшую возможную функцию sample_func, чтобы сформулировать вопрос. Мой вопрос заключается в том, как ускорить вышеупомянутое решение, учитывая, что оно предназначено для другой, более сложной функции, которая не относится к случайным значениям. Как я могу заменить for loops чистым решением numpy?
2. @greg2021
numpy
не подходит для этого. Массивам не разрешается иметь нестабильную длину, в отличие от списков Python (или других структур), попробуйте найти способ его векторизации (я имею в виду найти общее правило для вычисления всех строк). Если вам нужно постоянно обновлять список, я не знаю лучшего способа, потому что все они обречены быть медленными. Но вы можете попробовать больше таких вещей, какnp.concatenate
понимание спискаappend
и те, которые вы предложили. В большинстве случаев это кажетсяappend
многообещающим.