numpy.einsum()Sezgisel olarak anlarsanız fikrini kavramak çok kolaydır. Örnek olarak, matris çarpımını içeren basit bir tanımla başlayalım .
Kullanmak için numpy.einsum()yapmanız gereken tek şey sözde abonelik dizesini argüman olarak, ardından da girdi dizilerinizi iletmektir .
Diyelim ki iki 2D diziler var, diyelim Ave Bve matris çarpma yapmak istiyorum. Yani, şunları yaparsınız:
np.einsum("ij, jk -> ik", A, B)
Burada alt simge dizisi ij diziye karşılık Agelirken, alt simge dizisi jk diziye karşılık gelir B. Ayrıca, burada dikkat edilmesi gereken en önemli şey , her bir alt simge dizesindeki karakter sayısının dizinin boyutlarıyla eşleşmesi gerektiğidir . (2B diziler için iki karakter, 3B diziler için üç karakter vb.) Ve alt simge dizeleri arasındaki karakterleri ( bizim durumumuzda) tekrarlarsanız , toplamın bu boyutlar boyunca olmasını istediğiniz anlamına gelir . Böylece, toplamlar azaltılacaktır. (yani bu boyut kaybolacaktır ) jein
Alt simge dize bundan sonra ->, bizim elde edilen dizi olacak. Boş bırakırsanız, her şey toplanır ve sonuç olarak bir skaler değer döndürülür. Aksi takdirde sonuç dizisinin alt simge dizesine göre boyutları olacaktır . Örneğimizde olacak ik. Biz matris çoğalması için dizideki sütun sayısı biliyoruz çünkü bu sezgisel Adizideki satır sayısını eşleşmesi gerekir Bburada neler olduğunu ise (kömürü tekrarlayarak bu bilgiyi kodlamak yani jiçinde alt simge dize )
Aşağıda, bazı np.einsum()yaygın tensör veya nd-dizi işlemlerinin uygulanmasının kullanımını / gücünü gösteren bazı örnekler verilmiştir .
Girdiler
# a vector
In [197]: vec
Out[197]: array([0, 1, 2, 3])
# an array
In [198]: A
Out[198]:
array([[11, 12, 13, 14],
[21, 22, 23, 24],
[31, 32, 33, 34],
[41, 42, 43, 44]])
# another array
In [199]: B
Out[199]:
array([[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
[4, 4, 4, 4]])
1) Matris çarpımı (benzeri np.matmul(arr1, arr2))
In [200]: np.einsum("ij, jk -> ik", A, B)
Out[200]:
array([[130, 130, 130, 130],
[230, 230, 230, 230],
[330, 330, 330, 330],
[430, 430, 430, 430]])
2) Ana diyagonal boyunca elemanları çıkarın (benzer np.diag(arr))
In [202]: np.einsum("ii -> i", A)
Out[202]: array([11, 22, 33, 44])
3) Hadamard ürünü (yani iki dizinin eleman-bazlı ürünü) (benzer arr1 * arr2)
In [203]: np.einsum("ij, ij -> ij", A, B)
Out[203]:
array([[ 11, 12, 13, 14],
[ 42, 44, 46, 48],
[ 93, 96, 99, 102],
[164, 168, 172, 176]])
4) Eleman-bazlı kareleme ( np.square(arr)veya benzeri arr ** 2)
In [210]: np.einsum("ij, ij -> ij", B, B)
Out[210]:
array([[ 1, 1, 1, 1],
[ 4, 4, 4, 4],
[ 9, 9, 9, 9],
[16, 16, 16, 16]])
5) İz (yani ana diyagonal elemanların toplamı) (benzer np.trace(arr))
In [217]: np.einsum("ii -> ", A)
Out[217]: 110
6) Matris devri (benzeri np.transpose(arr))
In [221]: np.einsum("ij -> ji", A)
Out[221]:
array([[11, 21, 31, 41],
[12, 22, 32, 42],
[13, 23, 33, 43],
[14, 24, 34, 44]])
7) Dış Ürün (vektörlerin) (benzeri np.outer(vec1, vec2))
In [255]: np.einsum("i, j -> ij", vec, vec)
Out[255]:
array([[0, 0, 0, 0],
[0, 1, 2, 3],
[0, 2, 4, 6],
[0, 3, 6, 9]])
8) İç Ürün (vektörlerin) (benzeri np.inner(vec1, vec2))
In [256]: np.einsum("i, i -> ", vec, vec)
Out[256]: 14
9) Eksen 0 boyunca toplam (benzer np.sum(arr, axis=0))
In [260]: np.einsum("ij -> j", B)
Out[260]: array([10, 10, 10, 10])
10) Eksen 1 boyunca toplam (benzer np.sum(arr, axis=1))
In [261]: np.einsum("ij -> i", B)
Out[261]: array([ 4, 8, 12, 16])
11) Parti Matrisi Çarpımı
In [287]: BM = np.stack((A, B), axis=0)
In [288]: BM
Out[288]:
array([[[11, 12, 13, 14],
[21, 22, 23, 24],
[31, 32, 33, 34],
[41, 42, 43, 44]],
[[ 1, 1, 1, 1],
[ 2, 2, 2, 2],
[ 3, 3, 3, 3],
[ 4, 4, 4, 4]]])
In [289]: BM.shape
Out[289]: (2, 4, 4)
# batch matrix multiply using einsum
In [292]: BMM = np.einsum("bij, bjk -> bik", BM, BM)
In [293]: BMM
Out[293]:
array([[[1350, 1400, 1450, 1500],
[2390, 2480, 2570, 2660],
[3430, 3560, 3690, 3820],
[4470, 4640, 4810, 4980]],
[[ 10, 10, 10, 10],
[ 20, 20, 20, 20],
[ 30, 30, 30, 30],
[ 40, 40, 40, 40]]])
In [294]: BMM.shape
Out[294]: (2, 4, 4)
12) Eksen 2 boyunca toplam (benzer np.sum(arr, axis=2))
In [330]: np.einsum("ijk -> ij", BM)
Out[330]:
array([[ 50, 90, 130, 170],
[ 4, 8, 12, 16]])
13) Dizideki tüm elemanları toplar (şuna benzer np.sum(arr))
In [335]: np.einsum("ijk -> ", BM)
Out[335]: 480
14) Birden fazla eksen üzerinde toplam (marjinalleştirme)
(benzer np.sum(arr, axis=(axis0, axis1, axis2, axis3, axis4, axis6, axis7)))
# 8D array
In [354]: R = np.random.standard_normal((3,5,4,6,8,2,7,9))
# marginalize out axis 5 (i.e. "n" here)
In [363]: esum = np.einsum("ijklmnop -> n", R)
# marginalize out axis 5 (i.e. sum over rest of the axes)
In [364]: nsum = np.sum(R, axis=(0,1,2,3,4,6,7))
In [365]: np.allclose(esum, nsum)
Out[365]: True
15) Çift Nokta Ürünleri ( np.sum (hadamard-ürünü) benzeri krş 3 )
In [772]: A
Out[772]:
array([[1, 2, 3],
[4, 2, 2],
[2, 3, 4]])
In [773]: B
Out[773]:
array([[1, 4, 7],
[2, 5, 8],
[3, 6, 9]])
In [774]: np.einsum("ij, ij -> ", A, B)
Out[774]: 124
16) 2D ve 3D dizi çarpımı
Böyle bir çarpma sonucu doğrulamak istediğiniz doğrusal denklem sistemini ( Ax = b ) çözerken çok yararlı olabilir .
# inputs
In [115]: A = np.random.rand(3,3)
In [116]: b = np.random.rand(3, 4, 5)
# solve for x
In [117]: x = np.linalg.solve(A, b.reshape(b.shape[0], -1)).reshape(b.shape)
# 2D and 3D array multiplication :)
In [118]: Ax = np.einsum('ij, jkl', A, x)
# indeed the same!
In [119]: np.allclose(Ax, b)
Out[119]: True
Aksine, eğer np.matmul()bu doğrulama için kullanmak gerekiyorsa reshape, aynı sonucu elde etmek için birkaç işlem yapmalıyız :
# reshape 3D array `x` to 2D, perform matmul
# then reshape the resultant array to 3D
In [123]: Ax_matmul = np.matmul(A, x.reshape(x.shape[0], -1)).reshape(x.shape)
# indeed correct!
In [124]: np.allclose(Ax, Ax_matmul)
Out[124]: True
Bonus : Daha fazla matematik burada okuyun: Einstein-Summation ve kesinlikle burada: Tensor-Notasyonu
(A * B)^Tya da eşdeğer olacakB^T * A^T.