3A
  • Portfolio Top
  • Categories
  • Tags
  • Archives

Numpyの行列計算チートシート

はじめに¶

様々なアルゴリズムを実装する際に漸化式は出るけど実装時にうまくいかない。ということは良くあります。また、Python を使って実装する場合、そのほとんどが行列の取り扱いです。(柔軟であるが故にエラーを吐かずに動いてしまう…笑)

そこで、まずは行列計算のチートシートを作成します。(随時加筆修正していきます。)

目次

  1. 基本事項
  2. 内積(行列積)
  3. 外積
In [1]:
import numpy as np

基本事項

In [2]:
N = 3
A = np.arange(N)
B = np.arange(N).reshape(-1,N) # np.expand_dims(A, axis=0), A[None,:]
C = np.arange(N).reshape(N,-1) # np.expand_dims(A, axis=1), A[:,None]
D = np.arange(N*N).reshape(N,N)
In [3]:
print(f"A = {A}")
print(f"B = {B}")
print(f"C = {C}")
print(f"D = {D}")
A = [0 1 2]
B = [[0 1 2]]
C = [[0]
     [1]
     [2]]
D = [[0 1 2]
     [3 4 5]
     [6 7 8]]
In [4]:
print(f"A.shape = {A.shape}")
print(f"B.shape = {B.shape}")
print(f"C.shape = {C.shape}")
print(f"D.shape = {D.shape}")
A.shape = (3,)
B.shape = (1, 3)
C.shape = (3, 1)
D.shape = (3, 3)
In [5]:
print(f"A.ndim = {A.ndim}")
print(f"B.ndim = {B.ndim}")
print(f"C.ndim = {C.ndim}")
print(f"D.ndim = {D.ndim}")
A.ndim = 1
B.ndim = 2
C.ndim = 2
D.ndim = 2
ndim ex.
scalar $(0)$ 1,2,...
vector $1$ A
matrix $\geq2$ B,C,D

内積(行列積)

vector & scalar / matrix & scalar¶

  • スカラーが絡むと、各要素とスカラーの積となる。
  • shape の変化はない。
  • どちらから掛けてもエラーは起こらない。
In [6]:
print(f"np.dot(A,2) = {np.dot(A,2)}") # vector & scalar
print(f"np.dot(B,2) = {np.dot(B,2)}") # matrix & scalar
print(f"np.dot(C,2) = {np.dot(C,2)}") # matrix & scalar
print(f"np.dot(D,2) = {np.dot(D,2)}") # matrix & scalar
np.dot(A,2) = [0 2 4]
np.dot(B,2) = [[0 2 4]]
np.dot(C,2) = [[0]
               [2]
               [4]]
np.dot(D,2) = [[ 0  2  4]
               [ 6  8 10]
               [12 14 16]]

vector & vector¶

  • 内積となる。
  • 結果はスカラーとなる。
  • shape が異なると、エラーが起きる。
In [7]:
print(f"np.dot(A,A) = {np.dot(A,A)}") # vector & vector
np.dot(A,A) = 5
In [8]:
np.dot(A, np.arange(N-1)) # shape=(3,) & shape=(2,)
ValueError: shapes (3,) and (2,) not aligned: 3 (dim 0) != 2 (dim 0)

vector & matrix¶

  • 行列積となる。
  • ベクトルは、位置によって変換のされ方が異なる。
    • 左がベクトルの場合: np.dot((x,) (y,z)) = np.dot((1,x) (y,z))
    • 右がベクトルの場合: np.dot((y,z) (x,)) = np.dot((y,z) (x,1))
  • 行列積であるので、結果の shape は np.dot((x,y) (y,z)) = (x,z) となる。
  • 上で y が異なるとエラーが生じる。
In [9]:
print(np.dot(A,B)) # np.dot((3,)(1,3))
print(np.dot(A,C)) # np.dot((3,)(3,1))
print(np.dot(B,A)) # np.dot((1,3)(3,))
print(np.dot(C,A)) # np.dot((3,1)(3,))
ValueError: shapes (3,) and (1,3) not aligned: 3 (dim 0) != 3 (dim 0)
[5]
[5]
ValueError: shapes (3,1) and (3,) not aligned: 1 (dim 1) != 3 (dim 0)

matrix & matrix¶

c = np.dot(a,b)

  • a.shape=(a1,a2,...,aN,X)
  • b.shape=(b1,b2,...,X,bM)
  • c.shape=(a1,a2,...,aN,b1,b2,...,bM)
  • c[i1,i2,...,iN,j1,j2,...,jM] == a[i1,i2,...,iM,:].dot(b[j1,j2,...,jM-1,:,jM])
In [10]:
import itertools
def checkNPdot(shape1, shape2):
    """ 計算可能なshapeの関係を列挙する。 """
    a = np.arange(np.prod(shape1))
    b = np.arange(np.prod(shape2))
    
    for comb1 in itertools.permutations(shape1, len(shape1)):
        for comb2 in itertools.permutations(shape2, len(shape2)):
            try:
                print(f"{comb1}.dot({comb2}) = {(a.reshape(comb1).dot(b.reshape(comb2))).shape}")
            except:
                pass

以下で具体的に見ていく!

np.dot(2D, 3D)¶

c = np.dot(a,b)

  • a.shape=(i,X)
  • b.shape=(j,X,k)
  • c.shape=(i,j,k)
  • c[i,j,k] == a[i,:].dot(b[j,:,k])
In [11]:
a = np.arange(6).reshape(2,3)
b = np.arange(24).reshape(2,3,4)
c = np.dot(a,b)
In [12]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
print(f"np.dot(a,b).shape = {c.shape}")
a.shape = (2, 3)
b.shape = (2, 3, 4)
np.dot(a,b).shape = (2, 2, 4)
In [13]:
I,J,K = c.shape
In [14]:
np.all([c[i,j,k]==a[i,:].dot(b[j,:,k]) for i in range(I) for j in range(J) for k in range(K)])
Out[14]:
True

np.dot(3D,2D)¶

c = np.dot(a,b)

  • a.shape=(i,j,X)
  • b.shape=(X,k)
  • c.shape=(i,j,k)
  • c[i,j,k] == a[i,j,:].dot(b[:,k])
In [15]:
a = np.arange(24).reshape(4,2,3)
b = np.arange(6).reshape(3,2)
c = np.dot(a,b)
In [16]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
print(f"np.dot(a,b).shape = {c.shape}")
a.shape = (4, 2, 3)
b.shape = (3, 2)
np.dot(a,b).shape = (4, 2, 2)
In [17]:
I,J,K = c.shape
In [18]:
np.all([c[i,j,k] == a[i,j,:].dot(b[:,k]) for i in range(I) for j in range(J) for k in range(K)])
Out[18]:
True

np.dot(3D,3D)¶

c = np.dot(a,b)

  • a.shape=(i,j,X)
  • b.shape=(k,X,l)
  • c.shape=(i,j,k,l)
  • c[i,j,k,l] == a[i,j,:].dot(b[k,:,l])
In [19]:
a = np.arange(24).reshape(2,3,4)
b = np.arange(60).reshape(3,4,5)
c = np.dot(a,b)
In [20]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
print(f"np.dot(a,b).shape = {c.shape}")
a.shape = (2, 3, 4)
b.shape = (3, 4, 5)
np.dot(a,b).shape = (2, 3, 3, 5)
In [21]:
I,J,K,L = c.shape
In [22]:
np.all([c[i,j,k,l] == a[i,j,:].dot(b[k,:,l]) for i in range(I) for j in range(J) for k in range(K) for l in range(L)])
Out[22]:
True

np.dot(2D,4D)¶

c = np.dot(a,b)

  • a.shape=(i,X)
  • b.shape=(j,k,X,l)
  • c.shape=(i,j,k,l)
  • c[i,j,k,l] == a[i,:].dot(b[j,k,:,l])
In [23]:
a = np.arange(6).reshape(2,3)
b = np.arange(120).reshape(2,4,3,5)
c = np.dot(a,b)
In [24]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
print(f"np.dot(a,b).shape = {c.shape}") # c[i,j,k,l] == a[i,j,:].dot(b[k,:,l])
a.shape = (2, 3)
b.shape = (2, 4, 3, 5)
np.dot(a,b).shape = (2, 2, 4, 5)
In [25]:
I,J,K,L = c.shape
In [26]:
np.all([c[i,j,k,l] == a[i,:].dot(b[j,k,:,l]) for i in range(I) for j in range(J) for k in range(K) for l in range(L)])
Out[26]:
True

np.dot(3D,4D)¶

c = np.dot(a,b)

  • a.shape=(i,j,X)
  • b.shape=(k,l,X,m)
  • c.shape=(i,j,k,l,m)
  • c[i,j,k,l,m] == a[i,j,:].dot(b[k,l,:,m])
In [27]:
a = np.arange(24).reshape(2,3,4)
b = np.arange(360).reshape(3,5,4,6)
c = np.dot(a,b)
In [28]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
print(f"np.dot(a,b).shape = {c.shape}")
a.shape = (2, 3, 4)
b.shape = (3, 5, 4, 6)
np.dot(a,b).shape = (2, 3, 3, 5, 6)
In [29]:
I,J,K,L,M = c.shape
In [30]:
np.all([c[i,j,k,l,m] == a[i,j,:].dot(b[k,l,:,m]) for i in range(I) for j in range(J) for k in range(K) for l in range(L) for m in range(M)])
Out[30]:
True

np.dot(4D,4D)¶

c = np.dot(a,b)

  • a.shape=(i,j,k,X)
  • b.shape=(l,m,X,n)
  • c.shape=(i,j,k,l,m,n)
  • c[i,j,k,l,m,n] == a[i,j,k,:].dot(b[l,m,:,n])
In [31]:
a = np.arange(120).reshape(2,3,4,5)
b = np.arange(360).reshape(3,4,5,6)
c = np.dot(a,b)
In [32]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
print(f"np.dot(a,b).shape = {c.shape}")
a.shape = (2, 3, 4, 5)
b.shape = (3, 4, 5, 6)
np.dot(a,b).shape = (2, 3, 4, 3, 4, 6)
In [33]:
I,J,K,L,M,N = c.shape
In [34]:
np.all([c[i,j,k,l,m,n] == a[i,j,k,:].dot(b[l,m,:,n]) for i in range(I) for j in range(J) for k in range(K) for l in range(L) for m in range(M) for n in range(N)])
Out[34]:
True

外積

  • c = np.outer(a,b)
  • c[i][j] = a.reshape(-1,)[i]*b.reshape(-1,)[j]
In [35]:
c = np.outer(a,b)
In [36]:
print(f"a.shape = {a.shape}")
print(f"b.shape = {b.shape}")
a.shape = (a1,a2,...,aN)
b.shape = (b1,b2,...,bM)
In [37]:
Na = np.prod(a.shape)
Nb = np.prod(b.shape)
In [38]:
print(f"Na = {Na}")
print(f"Nb = {Nb}")
Na = a1*a2*・・・*aN
Nb = b1*b2*・・・*bM
In [39]:
print(c.shape)
(Na, Nb)
In [40]:
np.all([c[i][j] == a.reshape(-1,)[i]*b.reshape(-1,)[j] for i in range(Na) for j in range(Nb)])
Out[40]:
True
In [ ]:
 

  • « 分子生命科学Ⅲ 第1回
  • HMMの最尤推定 »
hidden
Table of Contents
Published
Sep 26, 2019
Last Updated
Sep 26, 2019
Category
情報基礎実験(浅井)
Tags
  • 3A 127
  • 情報基礎実験(浅井) 13
Contact
Other contents
  • Home
  • Blog
  • Front-End
  • Kerasy
  • Python-Charmers
  • Translation-Gummy
    • 3A - Shuto's Notes
    • MIT
    • Powered by Pelican. Theme: Elegant