NumPy: вещание на несколько внутренних продуктов и инверсий

У меня есть массивы e, (форма q от l) f (форма n от l), а также w (форма n от l), и я хочу создать массив M где M[s,i,j] = np.sum(w[s, :] * e[i, :] * e[j, :])и массив F, где F[s,j] = np.sum(w[s, :] * f[s, :] * e[j, :]),

И то, и другое достаточно легко сделать, например, перебирая элементы M, но я хочу быть более эффективным (мои реальные данные имеют что-то вроде 1M записей длиной 5k). За F, Я могу использовать F = np.inner(w * f, e) (который я проверял, дает тот же ответ, что и цикл). M является более сложным, поэтому первым шагом является циклическое прохождение нулевого измерения с пониманием списка, говоря, что M = np.stack([np.inner(r[:] * e, e) for r in w]) (Я убедился, что это также работает так же, как цикл). np.inner() не принимает аргументов осей, поэтому мне не ясно, как сказать массивам просто транслировать по всем рядам w,

Наконец, мне нужно использовать элементы M а также F создать матрицу A, где A[s,i] = np.sum(np.linalg.inv(M[s, :, :])[i, :] * F[i, :]), Это также выглядит как внутренний продукт, но получение большого количества отдельных инверсий отнимает много времени, так есть ли способ вычисления инверсий срезов, за исключением цикла?

Некоторые тестовые значения в моих массивах следующие:

e = array([[-0.9840087 , -0.17812043],
           [ 0.17812043, -0.9840087 ]])

w = array([[  1.12545297e+01,   1.48690140e+02],
           [  7.30718244e+00,   4.07840612e+02],
           [  2.62753065e+02,   2.27085711e+02],
           [  1.53045364e+01,   5.63025281e+02],
           [  8.00555079e+00,   2.16207407e+02],
           [  1.54070190e+01,   1.87213209e+06],
           [  2.71802081e+01,   1.06392902e+02],
           [  3.46300255e+01,   1.29404438e+03],
           [  7.77638140e+00,   4.18759293e+03],
           [  1.12874849e+01,   5.75023379e+02]])

f = array([[ 0.48907404,  0.06111084],
           [-0.21899297, -0.02207311],
           [ 0.58688524,  0.05156326],
           [ 0.57407751,  0.10004592],
           [ 0.94172351,  0.03895357],
           [-0.7489003 , -0.08911183],
           [-0.7043736 , -0.19014227],
           [ 0.58950925,  0.16587887],
           [-0.35557142, -0.14530267],
           [ 0.24548714,  0.03221844]])

1 ответ

Решение
M[s,i,j] = np.sum(w[s, :] * e[i, :] * e[j, :])

переводит на

M = np.einsum('sk,ik,jk->sij',w,e,e)

а также

F[s,j] = np.sum(w[s, :] * f[s, :] * e[j, :])
F = np.einsum('sk,sk,jk->sj', w, f, e)

Я не проверял их на ваших примерах, но перевод достаточно прост.

С большими массивами вам может потребоваться разбить выражения на части. С 4 переменными итерации общее пространство итерации может быть очень большим. Но сначала посмотрите, работают ли эти выражения с массивами небольшого размера.

Что касается

A[s,i] = np.sum(np.linalg.inv(M[s, :, :])[i, :] * F[i, :])

Я похож np.linalg.inv(M) работает, выполняя s иси инверс

Если так то

 IM = np.linalg.inv(M)
 A = np.einsum('skm,ik,im->si', IM, F)

Я предполагаю больше здесь.

Опять же, измерение может стать слишком большим, но сначала попробуйте его маленьким.

Как правило, решения линейных уравнений рекомендуются для прямых инверсий, что-то вроде

  A = F/M
  A = np.linalg.solve(M, F)

так как вы, вероятно, хотите A такой, что M@A=F (@ матричный продукт). Но я немного подзабыл по этим вопросам. Также проверьте tensorsolve а также tensorinv,

Другие вопросы по тегам