2016/03/25更新

[Python] 行列やベクトルを扱うことができるNumPyに入門

このエントリーをはてなブックマークに追加      

こんにちは、@yoheiMuneです。
本日はPythonで行列やベクトルの演算ができるNumPyライブラリの基本的な使い方をブログに書きたいと思います。

画像


目次




NumPyライブラリとは

NumPyは、Pythonで科学計算ができるライブラリで、線形代数などを扱うことができます。Pythonでの機械学習となるとほぼ必須のライブラリです。OctaveやMatlabほど直感的に行列演算ができないですが、色々と機能は用意されているので、それらについてブログで触れてみたいと思います。



NumPyのインストール

インストールは簡単でpipで行うことができます。
$ pip install --upgrade numpy
これでインストールは完了です。



NumPyを使ってみる

ここからは具体的にNumPyを使ってみたいと思います。


配列、ベクトル、行列を作成する

以下のようにすることで、色々とデータを作成することができます。
import numpy as np

# ベクトル
a = np.array([1,2,3])
print(a)                 # [1 2 3]
print(type(a))           # <class 'numpy.ndarray'>
print(a.shape)           # (3,)
print(a[0], a[1], a[2])  # 1 2 3

# 行列
b = np.array([[1,2,3], [4,5,6]])
print(b)
# [[1 2 3]
#  [4 5 6]]
print(type(b))                # <class 'numpy.ndarray'>
print(b.shape)                # (2, 3)
print(b[0,0], b[0,1], b[1,1]) # 1 2 5

# 各種便利に行列を作れる(ゼロ行列、単位行列、など)
a = np.zeros((2,2))
print(a)
# [[ 0.  0.]
#  [ 0.  0.]]

b = np.ones((1,2))
print(b)
# [[ 1.  1.]]

c = np.full((2,2), 7)
print(c)
# [[ 7.  7.]
#  [ 7.  7.]]

d = np.eye(2)
print(d)
# [[ 1.  0.]
# [ 0.  1.]]

e = np.random.random((2,2))
print(e)
# [[ 0.35882145  0.82999821]
#  [ 0.58963763  0.58711411]]
さらに詳しく


行列から部分行列を取り出す

要素を取り出すときに、範囲を指定して部分行列を取り出すことができます。
import numpy as np

# 配列の要素取得と同じ感じで、"a"の一部を取り出せる    
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = a[:2, 1:3]
print(b)
# [[2 3]
#  [6 7]]

# "b"は"a"への参照実装なので、書き換えると"a"も変わる
print(a[0,1])  # 2
b[0,0] = 7
print(a[0,1])  # 7

# 取り出し方によって、ランク(Rank)が違う
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# Rank1
row_r1 = a[1,:]
print(row_r1)        # [5 6 7 8]
print(row_r1.shape)  # (4,)
# Rank2
row_r2 = a[1:2,:]    
print(row_r2)        # [[5 6 7 8]]
print(row_r2.shape)  # (1, 4)
# Rank1
col_r1 = a[:,1]
print(col_r1, col_r1.shape)  # [ 2  6 10] (3,)
# Rank2
col_r2 = a[:,1:2]
print(col_r2, col_r2.shape)
# [[ 2]
#  [ 6]
#  [10]] (3, 1)


Integer Array Indexing

これはちょっと分かりづらいですが、便利です。行列から値を取り出す場合にa[[行一覧],[列一覧]]で取り出すことができます。
import numpy as np

# 「a[[行一覧],[列一覧]]」で値を取り出す
a = np.array([[1,2], [3,4], [5,6]])
print(a[[0,1,2], [0,1,0]])
# [1 4 5]

# 以下でも同じ要素を取り出せる
print(np.array([a[0,0], a[1,1], a[2,0]]))
# [1 4 5]

# もう一例
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
b = np.array([0,2,0,1])
print(a[np.arange(4), b])
# [ 1  6  7 11]

# 以下のように値の更新にも使える
a[np.arange(4), b] += 10
print(a)
# [[11  2  3]
# [ 4  5 16]
# [17  8  9]
# [10 21 12]]
さらに詳しく


Boolean Array Indexing

条件に合致する要素のみを取り出すことができます。
import numpy as np

# 条件のTrue/Falseの行列を得ることができる
a = np.array([[1,2], [3,4], [5,6]])
bool_idx = (a > 2)
print(bool_idx)
# [[False False]
#  [ True  True]
#  [ True  True]]

# 上記を使って、条件がTrueの要素のみを取り出せる
print(a[bool_idx])
# [3 4 5 6]

# 以下のショートハンドでもOK
print(a[a > 2])
# [3 4 5 6]


データ型

データ型の確認や指定をすることができます。
import numpy as np

a = np.array([1,2])
print(a.dtype)       # int64

b = np.array([1.0,2.0])
print(b.dtype)       # float64
c = np.array([1,2], dtype=np.uint8)
print(c.dtype)       # uint8
さらに詳しく


ベクターや行列の演算

ベクターや行列について、四則演算や内積、外積などの計算を行うことができます。
import numpy as np

## 要素ごとの演算
a = np.array([[1,2], [3,4]])
b = np.array([[5,6], [7,8]])
# 足し算
print(a + b)
print(np.add(a,b))
# 引き算
print(a - b)
print(np.subtract(a,b))
# 掛け算
print(a * b)
print(np.multiply(a,b))
# 割り算
print(a / b)
print(np.divide(a,b))
# ルート
print(np.sqrt(a))

# 行列・ベクトルの演算
x = np.array([[1,2], [3,4]])
y = np.array([[5,6], [7,8]])
v = np.array([9,10])
w = np.array([11,12])
# 内積
print(v.dot(w))
print(np.dot(v, w))
# 外積(行列 × ベクトル)
print(x.dot(w))
print(np.dot(x, w))
# 外積(行列 × 行列)
print(x.dot(y))
print(np.dot(x, y))

# 要素の値の合計
x = np.array([[1,2], [3,4]])
print(np.sum(x))
print(np.sum(x, axis=0)) # compute sum of each column.
print(np.sum(x, axis=1)) # compute sum of each row.

# 転置
x = np.array([[1,2], [3,4]])
print(x.T)
v = np.array([1,2,3])
print(v.T) # これは意味ない(.Tする前と一緒)

# ベクトル同士の外積
v = np.array([1,2,3])
w = np.array([4,5])
print(np.reshape(v, (3,1)) * w) # 3×2行列
さらに詳しく

さらに詳しく(ユニバーサル関数)



ブロードキャスト

ブロードキャスト機能もあります。
import numpy as np

#1: for文を使ったブロードキャスト(処理速度が遅い)
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1,0,1])
y = np.empty_like(x) # Create an empty matrix with the same shape as "x"
for i in range(4):
    y[i,:] = x[i,:] + v

#2: 同じ次元の行列を作って足す(これはこれで良い)
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1,0,1])
y = np.empty_like(x)
vv = np.tile(v, (4,1))
y = x + vv

#3: ブロードキャスト(xの各行にvを足す)
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
v = np.array([1,0,1])
y = x + v

# ブロードキャスト(xの各列にwを足す)
x = np.array([[1,2,3], [4,5,6]])
w = np.array([4,5])
y = (x.T + w).T

# ブロードキャスト(xの各列にwを足す)(別ソリューション)
y = x + np.reshape(w, (2,1))

# 各要素に実数を掛ける
x = np.array([[1,2,3], [4,5,6]])
y = x * 2
さらに詳しく


参考資料

今回の内容については、以下の2つを参照しました。ありがとうございます。

Python Numpy Tutorial | CS231n Convolutional Neural Networks for Visual Recognition

NumPy本家のサイト(英語)



最後に

今回はNumPyの入門として、いろいろな使い方をブログに書きました。行列演算を高速に行えるのは素敵ですね。今後のマシーンラーニングの学習や実装に大いに役立てられそうです。

本ブログでは、フロントエンド・Python・機械学習を中心に発信していきます。気になった方はぜひ、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。