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
,