Учитывая, что я правильно вывел все измерения различных терминов, вот способ сделать это.Но сначала краткий обзор размеров (снимок экрана, поскольку его легче объяснить с помощью настройки математического типа; пожалуйста, проверьте, верны ли они):
Также обратите вниманиедвойная производная второго члена, которая дает:
, где индексы обозначают образцы, а верхние индексы обозначают признаки.
Таким образом, мы можем создатьдва термина с использованием np.einsum
(аналогично torch.einsum
) и широковещательная рассылка :
grad_y_K = (X[:, None, :] - Y) / h * K[:, :, None] # Shape: N_x, N_y, D
term_1 = np.einsum('ij,ikl->ikjl', grad_log_px, grad_y_K) # Shape: N_x, N_y, D_x, D_y
term_2_h = np.einsum('ij,kl->ijkl', K, np.eye(D)) / h # Shape: N_x, N_y, D_x, D_y
term_2_h2_xy = np.einsum('ijk,ijl->ijkl', grad_y_K, grad_y_K) # Shape: N_x, N_y, D_x, D_y
term_2_h2 = K[:, :, None, None] * term_2_h2_xy / h**2 # Shape: N_x, N_y, D_x, D_y
term_2 = term_2_h - term_2_h2 # Shape: N_x, N_y, D_x, D_y
Затем дается результатпо:
(term_1 + term_2).sum(axis=0) / N # Shape: N_y, D_x, D_y