コードを書く¶
Todo
全面改訂予定。
SciPy ノートと内容が重複するトピックがどうしても残る?
ヘルプ¶
NumPy Reference の Numpy-specific help functions セクションを見ておくこと。これらのヘルプ関数を覚えておくと IDLE での作業時には重宝するだろう。
キーワードから機能を探す¶
関数 lookfor
を利用すると、NumPy 内の docstring からそれらしい機能をリストアップしてくれる。
>>> import numpy as np
>>> np.lookfor('least square')
Search results for 'least square'
---------------------------------
numpy.polyfit
Least squares polynomial fit.
numpy.ma.polyfit
Least squares polynomial fit.
numpy.linalg.lstsq
Return the least-squares solution to a linear matrix equation.
...
NumPy のバージョンを知る¶
version.py
の変数 version
を参照する。
>>> np.version.version
'1.11.1'
関数またはオブジェクト array
¶
ヘルプの使い方を習得したら、まずは array
周辺から攻略する。なお、本テキストで array
と言うときは、同名の関数を指すか、同名の関数が返す値の型を指すかの両方があることをことわっておく。
array
オブジェクトを生成する¶
NumPy Reference の Array creation routines のセクションできれいにまとめてある。
array
オブジェクトの生成方法の基本は関数array
呼び出しだ。関数array
はたいていの場合ndarray
型のオブジェクトを返すようだ。import numpy as np # Create a vector. v = np.array([0., 0., 1.]) # Create a matrix. m = np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
zeros_like
,ones_like
,empty_like
をワンセットで習得すること。既存の array_like オブジェクトから同じ shape の array を生み出す関数だ。よく利用するのは
ndarray
だが、コンストラクターを直接利用せずに、関数array
,zeros
,empty
等からオブジェクトを作成すること。copy
関数で array_like オブジェクトのコピーオブジェクトを同一あるいは別の array オブジェクトとして作成することができる。>>> a = [1., 2., 3.] >>> np.copy(a) array([ 1., 2., 3.])
変わったところでは
arange
関数で「連番」配列を生成できる。Python のrange
関数の array 版といったところだ。>>> np.arange(3.0) array([ 0., 1., 2.])
場合によっては array
オブジェクトを生成したくない場合¶
もっと優れているのは関数 array
のキーワード引数 copy
を使い分けることだろう。例えば自作関数で array-like な引数をとる場合、「それが本当に array
ならそのまま参照し、実は組み込み型のコンテナーオブジェクトならば array
オブジェクトを新たに生成したい」ことがままある。そのような状況にはうってつけである。
def orthonormalize(center, eye, up):
zdir = np.array(eye, copy=False) - np.array(center, copy=False)
zdir /= np.linalg.norm(zdir)
ydir = np.array(up)
ydir /= np.linalg.norm(ydir)
xdir = np.cross(ydir, zdir)
return (xdir, ydir, zdir)
array
の要素の型を明示的に指定する¶
キーワード引数 dtype
を用いる。値の指定方法は色々あるが、次の方式を推奨する:
>>> x_axis = np.array([1, 0, 0], dtype=np.float64)
>>> x_axis[:]
array([ 1., 0., 0.])
既存の array
の型をキャストした array
を得る¶
メソッド .astype
を用いる。キーワード引数 copy
も併用可能。
>>> x_axis.astype(np.int8)
array([1, 0, 0], dtype=int8)
array
の shape を変える¶
NumPy Reference の Array manipulation routines のセクションで表にまとめてある。
1-D array_like オブジェクトを多次元化するには
reshape
メソッドまたは同名の関数を利用する。order
引数でメモリレイアウトを指示できる。多次元
array
を「一次元配列化」するにはflatten
メソッドまたは関数ravel
を利用する。確実にコピーオブジェクトが欲しい場合は
flatten
を利用するのがよい?引数が
order
を表すので、PyOpenGL の行列系関数に渡すときに調整できるかも。>>> a = np.arange(16).reshape(4, 4) >>> a array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15]]) >>> a.flatten() array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) >>> a.flatten('F') array([ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15])
同型 array
オブジェクト同士に算術演算子を作用させる¶
+
, -
等の二項演算子を同型 array
オブジェクト同士に作用させることができる。各演算の定義は、成分ごとの算術演算のようだ。また、同型でなくとも
broadcasting rule が適用できる場合は二項演算が実現できる。特にスカラーを作用させる場合は常に可能と考えていい。
array
オブジェクトのスライシング¶
行列を表現する array
オブジェクトから部分ベクトルを得るようなときには、
Python の list
同様、スライシングの技法を利用する。
>>> a = np.arange(24).reshape(3, 8)
>>> a
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22, 23]])
>>> a[:,0]
array([ 0, 8, 16])
>>> a[0,:]
array([0, 1, 2, 3, 4, 5, 6, 7])
NumPy はより高性能なスライスをサポートしているが、深みにはまると危ないのでこの辺で。
線形代数関連¶
スカラー積、ベクトル積¶
スカラー積、ベクトル積を求めたい場合、それぞれ関数 dot
, cross
を利用すること。
>>> x = [1., 0., 0.]
>>> y = [0., 1., 0.]
>>> np.dot(x, y)
0.0
>>> np.cross(x, y)
array([ 0., 0., 1.])
dot
については引数の shape さえ適合すれば行列の乗算もサポートする。
>>> x = [100., 200.]
>>> M = np.array([[1., 2.],
... [3., 4.]])
>>> np.dot(x, M)
array([ 700., 1000.])
>>> np.dot(M, x)
array([ 500., 1100.])
ベクトルの長さ¶
二項演算が幅広くサポートされているので、1-D array
オブジェクトをベクトルとみなすのが楽だ。が、ベクトルならば「長さ」を計算する関数が欲しい。ここでは dot
を利用する。
>>> import math, numpy as np
>>> v = array([1., 1., 1.])
>>> math.sqrt(np.dot(v, v)) # By the way, sqrt is also provided in np.
1.7320508075688772
あるいは linalg パッケージにある norm
関数も有用だ。デフォルト引数をそのまま利用すれば 2-norm を計算してくれる。
>>> # v is the same as above example.
>>> vlen = np.linalg.norm(v)
>>> vlen
1.7320508075688772
ベクトル正規化¶
正規化とは長さが 1 になるようにベクトルの成分を定数倍することとする。それには、ベクトルの長さを上述の方法で得てから、長さが非ゼロであることを確認後、array
オブジェクトに対して /=
する。
>>> # v is the same as above example.
>>> v /= vlen
>>> v
array([ 0.57735027, 0.57735027, 0.57735027])
ベクトルの一致に関数 allclose
を用いる¶
同次元空間にある 2 ベクトル v1
, v2
が等しいか否かのテストをする。要するに、アプリケーション定義のトレランスを与えて、両者の差ベクトルの長さがそれ以内に収まっているかどうかを調べる。
関数 allclose
をアプリケーション由来のトレランスを明示的に与えた上で適用するのがよかろう。デフォルトのトレランスではモデリング等で利用するには厳しすぎる。
ベクトルのなす角¶
これも自分でコードを書く。二ベクトルのスカラー積 (dot
) とそれぞれの長さからなす角の cos
が求まる。
二ベクトルの位置関係判定¶
二ベクトルが平行なのか、または直交するのかをテストしたい場合、dot
と
cross
を組み合わせれば何とかなる。
一発で identity matrix を生成する関数 eye
, identity
¶
関数 eye
を利用する。ずばり identity
という関数も存在するが、タイプし易いほうを選ぶ。
>>> np.eye(4)
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
対角行列を生成するには関数 diag
を利用する¶
関数 diag
を利用すると、手軽に対角行列を作成できる。
>>> A = np.diag([1.,2.,3.])
>>> A
array([[ 1., 0., 0.],
[ 0., 2., 0.],
[ 0., 0., 3.]])
行列から対角成分を抽出するのも関数 diag
を利用する¶
やはり関数 diag
を利用する。引数に二次元の array
オブジェクトを渡すこと。
>>> # A is the same as above example.
>>> np.diag(A)
array([1., 2., 3.])
統計関連¶
NumPy は標本を表現するデータ構造としても array
を利用している。 NumPy
Reference の Statistics のセクションでまとめてある。
統計関連の機能がまれにメソッドの形式で提供されていることがある?
個人的な用途では 1-D
array
オブジェクトを主に対象とする(このノートでも)が、当然 n-Darray
オブジェクトについても各種統計関数を適用できる。サンプリングの対象はarray
オブジェクトの各要素でも、 along on axis でも OK だ。確率と統計 も参照して欲しい。
総和¶
Python 組み込み関数の sum
を含む、色々な選択肢がある。ここは np.sum
に統一したい。
>>> v = np.arange(100.)
>>> np.sum(v)
4950.0
最小値、最大値¶
np.min
, np.max
関数がそれぞれ array
オブジェクトの最小値、最大値を検索できる。
>>> # v is the same as above example.
>>> np.amin(v)
0.0
>>> np.amax(v)
99.0
平均値¶
細かいことを言えば平均値の定義によるが、np.average
と np.mean
が利用できる。個人的には、相加平均を使うという意味を表現したいので mean
を用いる。
>>> # v is the same as above example.
>>> np.mean(v)
49.5
ヒストグラム¶
関数 np.histogram
で array
からヒストグラムを作成することができる。ビンの与え方もその気になれば非等幅ビンを指定することもできる。
ビンの個数はデフォルトで 10 らしい。サンプル数からそれらしいビン数を計算するのは自力でやれということか。
各ビンは半開区間(左閉)なのだが、最後のビンのみ閉区間になることに注意が必要。
>>> sample = np.arange(16.) >>> hist, binedges = np.histogram(sample) >>> hist array([2, 1, 2, 1, 2, 1, 2, 1, 2, 2]) >>> binedges array([ 0. , 1.5, 3. , 4.5, 6. , 7.5, 9. , 10.5, 12. , 13.5, 15. ])
乱数関連¶
NumPy Reference の Random sampling (
numpy.random
) セクションに多数。乱数は奥が深い。追究し出すときりがない。目的を達成するのに十分見合いそうな関数を見つけたら、他の乱数関数を調べないこと。
分布モノは一通り網羅しているようなので、業務上必要になったら文献を当たろう。
内容がランダムな整数 array
を得る¶
np.random.randint(low, high, size)
を利用する。引数リストが独特なので、すべての引数に明示的に実引数を渡した方がよいだろう。
>>> np.random.randint(0, 500, 4)
array([210, 332, 476, 488])
>>> np.random.randint(0, 500, 4)
array([149, 183, 182, 40])
内容がランダムな float 型数 array
を得る¶
np.random.random_sample(size)
を利用する。こいつは \({[0, 1)}\) の値を
size
回ランダムに抽出するだけなので、欲しい値の範囲には、自分で線形変換をかけて値を得る。
>>> np.random.random_sample(15)
array([ 0.54368538, 0.65534826, 0.42464352, 0.21621149, 0.55229361,
0.15027351, 0.23596445, 0.04811345, 0.11326923, 0.36599603,
0.32611298, 0.29099913, 0.6946677 , 0.51569253, 0.25698767])
array
の内容をランダムにシャッフルする¶
C++ で言うところの std::random_shuffle(first, last)
と同等のことをしたい(現代では非推奨だが)。それには np.random.shuffle(x)
を利用すればよい。
>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> np.random.shuffle(a)
>>> a
array([2, 4, 0, 1, 3])
どうも shape のある array
には効き目が薄いようだ(確かめろ)。