У меня есть функция, написанная на python, которая выполняет две процедуры:
- Предварительная обработка: считывание данных из массива и вычисление некоторых значений, которые позже понадобятся мне для предотвращения повторных вычислений
- Итерируйте и вычисляйте «сводку» данных на каждом этапе и используйте ее для решения задачи оптимизации.
Код выглядит следующим образом:
import numpy as np
def iterative_hessian(data, targets,
sketch_method, sketch_size, num_iters):
'''
Original problem is min 0.5*||Ax-b||_2^2
iterative_hessian asks us to minimise 0.5*||S_Ax||_2^2 - <A^Tb, x>
for a summary of the data S_A
'''
A = data
y = targets
n,d = A.shape
x0 = np.zeros(shape=(d,))
m = int(sketch_size) # sketching dimension
ATy = A.T@y
covariance_mat = A.T.dot(A)
for n_iter in range(int(num_iters)):
S_A = m**(-0.5)*np.random.normal(size=(m, n))
B = S_A.T.dot(S_A)
z = ATy - covariance_mat@x0 + np.dot(S_A.T, np.dot(S_A,x0)) #
x_new = np.linalg.solve(B,z)
x0 = x_new
return np.ravel(x0)
На практике яне используйте строку S_A = m**(-0.5)*np.random.normal(size=(m, n))
, но используйте другое случайное преобразование, которое применяется быстрее, но в принципе этого достаточно для вопроса.Этот код хорошо работает для того, что мне нужно, но мне было интересно, есть ли разумный способ сделать следующее:
- Вместо того, чтобы повторять строку
S_A = m**(-0.5)*np.random.normal(size=(m, n))
для каждой итерации, есть ли способ указатьколичество независимых случайных копий (num_iters
- которые можно считать между 10 и 30) из S_A
, которые необходимы до итерации и сканируют входные данные только один раз, чтобы сгенерировать все такие копии?Я думаю, что в этом случае переменные S_A
будут храниться в каком-то многомерном массиве, но я не уверен, как лучше это сделать, или даже практично ли это.Я попробовал базовый пример, делающий это параллельно, но он медленнее, чем многократно проходящий через матрицу. - Предположим, что я хочу наделить эту функцию большим количеством свойств, например, я хочу вернуть среднее время, затраченное налиния
x_new = np.linalg.solve(B,z)
.Сделать это просто - импортируйте модуль времени и поместите код в функцию, однако это всегда будет время функции, и, возможно, я хочу сделать это только при тестировании.Простой способ обойти это - создать параметр в определении функции time_updates = False
и затем if time_updates == False:
продолжить, как описано выше else:
, скопировать точно такой же код, но с добавлением некоторой функциональности синхронизации.Есть ли лучший способ сделать это, который может использовать классы в Python?
Я собираюсь использовать эту итерацию для блоков данных, считываемых из файла, который не помещается в память.Хотя можно сохранить блок в памяти, было бы удобно, если бы функция проходила через этот блок только один раз, а не num_iters
раз.Прохождение по вычисленным величинам, S_A
, covariance_matrix
и т. Д., Хорошо, однако.