NumPy

NumPyはベクトルや行列の演算を高速に行うことが可能な多次元配列のためのライブラリ. 中身はC言語等で実装されているので高速.

ここでは,機械学習の基礎を学ぶ際に使用するものを中心に, NumPyの基礎を記しておく. jupyterでの使用を想定していて,最後に変数だけ書いた行はその変数情報を表示するために書いてある.

NumPyのインポート

グラフを描く場合は,matplotlibもインポートする.

import matplotlib.pyplot as plt
import numpy as np

NumPyの配列(ndarray)

  • 1次元はベクトルで,2次元は行列.
  • 1次元配列に縦ベクトル,横ベクトルの区別はない(転置しても変化無し).

リストをndarrayに変換

a = [0, 1, 2, 3, 4]
b = np.array(a)
b    # jupyterで変数の情報を表示
[出力]
array([0, 1, 2, 3, 4])

和や積など

b * 2    # 要素を2倍
[出力]
array([0, 2, 4, 6, 8])
b + 2    # 要素に2を足す
[出力]
array([2, 3, 4, 5, 6])

2次元配列

c = np.array([[1, 2, 3], [4, 5, 6]])
c
[出力]
array([[1, 2, 3],
       [4, 5, 6]])

配列の情報

c.shape    # 配列の形状
[出力]
(2, 3)
c.size    # サイズ(全要素数)
[出力]
6

転置

c.T    # 転置
[出力]
array([[1, 4],
       [2, 5],
       [3, 6]])

配列の形状変更(reshape)

2行3列を3行2列に変更.

c.reshape(3, 2)
[出力]
array([[1, 2],
       [3, 4],
       [5, 6]])

reshapeでは引数に-1を指定すれば自動でうまく形状を変更してくれる.

c.reshape(3, -1)    # 3行だけ指定
[出力]
array([[1, 2],
       [3, 4],
       [5, 6]])

指定した範囲の離散化

グラフを描く時などによく利用する.

arange()

ステップ(刻み幅)を指定する.
arange([start,] stop[, step,], dtype=None)
初期値とステップは省略できる.デフォルトは0と1.

np.arange(10)    # 0から10まで1刻み(10は含まない)
[出力]
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

linspace()

要素数を指定する.
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0,)
デフォルトではstopの値も含まれる(endpoint=True).

np.linspace(0, 10, 4)    # 0から10まで,要素数4
[出力]
array([ 0.        ,  3.33333333,  6.66666667, 10.        ])

乱数

random.rand()

要素が0以上1未満の乱数である配列を作る.

np.random.rand(3)    # 1次元
[出力]
array([0.71185075, 0.41201444, 0.26437563])
np.random.rand(2, 3)    # 2次元
[出力]
array([[0.12970969, 0.93839695, 0.37753812],
       [0.36536463, 0.46674746, 0.5813878 ]])

random.normal()

ガウス分布に従う乱数を作る.
random.normal(loc=0.0, scale=1.0, size=None)

  • loc: 平均
  • scale: 標準偏差
  • size: arrayのサイズ(次元)
np.random.normal(0.0, 1.0)    # スカラー
[出力]
-0.3152600672885223
np.random.normal(0.0, 1.0, 4)    # 1次元
[出力]
array([-0.89806864, -1.25102037,  1.80407245,  0.2544276 ])
np.random.normal(0.0, 1.0, (2, 3))    # 2次元
[出力]
array([[-0.36909568,  0.39672614,  1.45321506],
       [-0.42459074, -2.07548469, -1.70934341]])

べき乗

power()

np.power(2, 3)    # 2の3乗
[出力]
8
np.power([1, 2, 3], 2)    # リストの要素をそれぞれ2乗
[出力]
array([1, 4, 9])
np.power([1, 2, 3], [1, 2, 3])    # 一つ目の要素を1乗,2つ目を2乗,...
[出力]
array([ 1,  4, 27])
np.power(2, [1, 2, 3])    # 2の1乗,2乗,3乗,...
[出力]
array([2, 4, 8])
d = np.array([[1], [2], [3]])    # 3行1列の2次元配列
np.power(d, [1, 2, 3])    # 各行について,1乗,2乗,3乗
[出力]
array([[ 1,  1,  1],
       [ 2,  4,  8],
       [ 3,  9, 27]])

ベクトル,行列の積

NumPyではベクトル,行列の積の計算に

  • matmul()
  • dot()
  • @

が利用できる. 2次元まではmatmul()dot()は同じ演算を行うが,3次元以上では異なるので注意. @a @ bのように用いる.これはmatmul(a, b)と同じ. @による演算はPython 3.5からサポート.

ベクトルの内積

a = np.array([0, 1, 2])
b = np.array([3, 4, 5])
np.matmul(a, b)    # 0*3 + 1*4 + 2*5
[出力]
14

ベクトルと行列の積

1次元配列(ベクトル)は縦ベクトル,横ベクトルの区別は無いので,引数の位置によって結果が異なる.

ベクトルを左から行列にかける場合

ベクトルを第1引数にする場合,下記の例では1行2列と解釈される.

$$ \begin{pmatrix} 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} = \begin{pmatrix} 2 & 3 \\ \end{pmatrix} $$

この計算で得られるのは1次元配列なので行とか列の区別はなくなる.

a = np.array([0, 1])    # ベクトル
bmat = np.array([[0, 1], [2, 3]])    # 行列
np.matmul(a, bmat)
[出力]
array([2, 3])

ベクトルを右から行列にかける場合

ベクトルを第2引数にする場合,下記の例では2行1列と解釈される.

$$ \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 1 \\ 3 \\ \end{pmatrix} $$

この計算で得られるのは1次元配列なので行とか列の区別はなくなる.

np.matmul(bmat, a)
[出力]
array([1, 3])

行列の積

$$ \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 2 & 3 \\ \end{pmatrix} = \begin{pmatrix} 2 & 3 \\ 6 & 11 \\ \end{pmatrix} $$

amat = np.array([[0, 1],[2, 3]])
bmat = np.array([[0, 1], [2, 3]])
np.matmul(amat, bmat)
[出力]
array([[ 2,  3],
       [ 6, 11]])

sin関数のグラフ

$$y = \sin (2\pi x)$$

  • 円周率はnp.pi
  • sin関数はnp.sin()
  • xは0から1までが連続的に見えるように細かく刻む(0.01).
x =  np.arange(0, 1, 0.01)    # 要素数100の1次元配列
x
[出力]
array([0.  , 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 ,
       0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2 , 0.21,
       0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3 , 0.31, 0.32,
       0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4 , 0.41, 0.42, 0.43,
       0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5 , 0.51, 0.52, 0.53, 0.54,
       0.55, 0.56, 0.57, 0.58, 0.59, 0.6 , 0.61, 0.62, 0.63, 0.64, 0.65,
       0.66, 0.67, 0.68, 0.69, 0.7 , 0.71, 0.72, 0.73, 0.74, 0.75, 0.76,
       0.77, 0.78, 0.79, 0.8 , 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87,
       0.88, 0.89, 0.9 , 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98,
       0.99])
y = np.sin(2 * np.pi * x)    # 要素数100の1次元配列
plt.plot(x, y)    # matplotlibでプロット
前へ
次へ