Numpy

pythonで高速に数値計算を行うためのモジュールで,デファクト・スタンダードになっている. 他のモジュールもほぼこのNumpyを使うのでこれを知っておく必要がある.

Python Data Science Handbook に詳しくnumpyのことが書かれており,どのように書いたら高速なプログラムが書けるかが分かる. 高速化に関しては numba によるJIT(Just-In-Time)コンパイルという方法がある.これは実用的に知っておいたほうが良い.

配列

基本的にnumpy配列は一度作成したら長さは固定(pythonのリストとは異なるので注意).

配列の形を指定して配列を作成

arr = np.zeros((2,3),dtype=float)

dtype=floatがデフォルトなので指定する必要はない.dtype=intにしたいときは必須.

pythonのリストから配列を作成

list1 = [1,3,5,3,1,6,7]
arr = np.array(list1)

配列の平均,分散,標準偏差

arr = np.array([[1,2],[3,4],[5,6]],dtype=int)
print(arr.shape)
print(arr)
print(arr.mean(axis=0), arr.mean(axis=1))
print(arr.var(axis=0), arr.var(axis=1))
print(arr.std(axis=0), arr.std(axis=1))

Output:
  (3, 2)
  [[1 2]
   [3 4]
   [5 6]]
  [3. 4.] [1.5 3.5 5.5]
  [2.66666667 2.66666667] [0.25 0.25 0.25]
  [1.63299316 1.63299316] [0.5 0.5 0.5]

二次元配列の場合,どの軸に対して平均などを取るか指定する(axis). axis=0は第一引数に関して平均をとり,axis=1は第二引数に関して平均をとる.ちょっと分かりづらいから注意が必要.


numpy配列に対するif文

numpy配列xに対して,

    for i in range(x):
        if x[i] > 1000:
            x[i] = 1000

このようなことがやりたい場合,つまり,すべての要素が1000以下となるように修正したい場合,配列全体をif文に渡して,

    if x > 1000

というような文を作ると,配列に対してif文を使えないのでエラーとなる. このような場合は,numpy.where()を用いる.

    numpy.where(条件, X, Y)

Xは条件が真のときの返り値で,Yは条件が偽のときの返り値なので,今の場合,

    numpy.where( x > 1000, 1000, x)

とすれば良い.

例:

    arr = [1,1400, 100]
    x = np.array(arr)
    print(x)
    y = np.where(x>1000,1000,x)
    print(y)
    # [   1 1400  100]
    # [   1 1000  100]

numpy.dot

np.dot(A,B) 関数はベクトル間の内積や行列間の積に使えるが,多次元になるとちょっと理解が難しいか?むしろ易しいか?

np.dot(A,B)[i,j,k,m] = np.sum( A[i,j,:] * B[k,:,m])

上のように,左の行列Aの最後のインデックスと,右の行列Bの最後から2つ目のインデックスの間の要素毎の積の和をとって,新たな行列の[i,j,k,m]要素とする. なので,ベクトル間の積のときには,

np.dot(a,b) = np.sum( a[np.newaxis,:] * b[:,np.newaxis])

という行列間の積と考えれば分かりやすいのか?