Разгрузите вычисление вероятностей как можно скорее:
possible_paths = np.vstack(
np.random.choice(state_idx, p=prob_nor[curr_state, :], size=n_frames)
for curr_state in range(n_states)
)
Тогда вы можете просто выполнить поиск, чтобы следовать вашему пути:
path_trace = [None]*n_frames
for step in range(n_frames):
path_trace[step] = possible_paths[current_state, step]
current_state = possible_paths[current_state, step]
Как только вы получите свой путь, выможете вычислить ваш след:
sigma = 0.1
trace = np.random.normal(loc=state_val[path_trace], scale=sigma, size=n_frames)
Сравнение времени:
Чистый питон for
цикл
%%timeit
trace_list = []
current_state = np.random.choice(state_idx)
for _ in range(n_frames):
trace_list.append(np.random.normal(loc=state_val[current_state], scale=sigma))
current_state = np.random.choice(state_idx, p=prob_nor[current_state, :])
Результаты:
30.1 ms ± 436 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Векторизованный поиск :
%%timeit
current_state = np.random.choice(state_idx)
path_trace = [None]*n_frames
possible_paths = np.vstack(
np.random.choice(state_idx, p=prob_nor[curr_state, :], size=n_frames)
for curr_state in range(n_states)
)
for step in range(n_frames):
path_trace[step] = possible_paths[current_state, step]
current_state = possible_paths[current_state, step]
trace = np.random.normal(loc=state_val[path_trace], scale=sigma, size=n_frames)
Результаты:
641 µs ± 6.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Ускорение примерно в 50 раз.