プロジェクト

全般

プロフィール

Python NumPy

はじめに

Pythonは、すべてのデータ(整数値、浮動小数点数値も)がオブジェクトとしてメモリ上に生成・配置され、メモリ管理の対象となります。
数値計算の分野では、多数のデータを配列に格納し演算のためにこれらをまとめて読み書きします。C言語などでは言語標準で配列を提供していますが、Pythonは配列を型として提供しておらず、配列の代替えとしてリストを使います。リストではデータ1個1個がオブジェクトとして独立にメモリ上に管理され、要素をまとめてアクセスする場合、配列に比べて非常に効率が悪くなります(例、メモリの局所性がないとキャッシュミスが起きてCPUの演算性能低下を招いてしまう)。
NumPyは、データをC言語で記述されたライブラリ側で配列に格納し演算することでPythonメモリ管理の性能問題を回避します。またベクトル演算のAPIを介して1回の関数呼び出しで複数の値をまとめて演算することで、ループ制御が不要となりコードが簡潔になるとともにPythonのアプリケーションとC言語で実装したNumPyライブラリ側のインタフェースが少なくなりPythonとC言語間のオーバーヘッドを減らしています。

一方で、NumPyを活用したプログラムは、ベクター(配列)とその計算を主体とした記述となるので、いわゆるPythonらしいコードとはちょっと異なります。このあたりは数値計算、データ処理といった用途に特化したコードと割り切って使うのがよさそうです。

例)円周のプロット

円周上に100個の点を生成し、matplotlibのグラフに点を線で結ぶグラフを表示するソースコードを、Python標準とnumpyとを使った場合で比較してみます。

Python標準

import math
import matplotlib.pyplot as plt

x = [] # Python標準ライブラリのリスト
y = []

for t in range(0, 101): # 整数0から100まで1ずつ増やして順番に生成
  theta = math.pi * 2 * t / 100 # 0から2πの範囲を100区分した値をtに応じて生成
  x.append(math.cos(theta))
  y.append(math.sin(theta))

plt.plot(x, y, '.-') # ポイントを小さい丸でプロットしポイント間を線で結ぶ
plt.grid()
plt.gca().set_aspect('equal')
plt.show()
  • Pythonの標準数学ライブラリのsin/cosは、スカラー(単一の値)を入力し計算し出力するので、生成する点の数だけループ制御をする
  • 配列の代替えとするリストに点を生成するたびに追加(append)する

NumPy使用

import numpy as np
import matplotlib.pyplot as plt

theta = np.linspace(0, 2 * np.pi, 100) # 初期値、最大値、区分数を指定し数列の配列を生成
x = np.cos(theta) # 100個の角度を入れてそのcos値を100個生成(theta, xはnumpy配列)
y = np.sin(theta) # 同上

plt.plot(x, y, '.-')
plt.grid()
plt.gca().set_aspect('equal')
plt.show()
  • NumPyの数学ライブラリのsin/cosは、ベクター(複数の値)を入力し計算し出力するので、生成する点の数を格納した配列(ndarray)を一回の呼び出しで完結し、ループ制御は不要
  • 配列への値の追加処理も記述不要

インストールとセットアップ

pip install numpy

ただし、NumPyは他のライブラリ(Pandas等)で使われることも多く、そうしたライブラリをinstallした時に合わせてインストールされていることがあります。

import numpy

慣習的に、npの略名でエイリアスしてインポートすることもあります。import numpy as np

データ型

ndarray

多次元配列のndarray型が提供されます。配列の要素は全て同じ型である必要があります。

ndarrayの要素の型

int8, uint8, int16, uint16, int32, uint32, int64, uint64, float16, float32, float64, float128, complex64, complex128, complex256, bool, object, string_, unicode_

1次元のndarray

array関数を使って、引数のシーケンスからndarrayを生成する。

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

配列の要素の型は自動推論され、この場合はint64となりました。

arr = np.array([1.5, 3, 5]) とすると、配列の要素の型はfloat64となりました。

要素の型を指定して配列を生成することができます。

arr = np.array([1, 3, 5], dtype=np.float64)

2次元の要素の型

arr = np.array([1, 2, 3], [4, 5, 6])

matrix

T.B.D.

演算

ベクトル

単位ベクトル

長さ1のベクトルを求めます。直接生成するAPIはないので、ベクトルのnorm(長さ)を求めてから、ベクトルをその長さで除算して求めます。

vector = np.array([1, 3, 5])
norm = np.linalg.norm(vector)
unit_vector = vector / norm

外積

numpy.cross で外積の計算ができます。

行列

行列とベクトルの積

演算子 @ を用います。


約1時間前に更新