python の数値計算関連ライブラリ numpy のtipsまとめ
-- しましま
pip や easy_install によるインストールの前に多くの外部ライブラリやfortranコンパイラなどが必要になるので,numpy等の科学技術計算パッケージをインストールするには以下のようなパッケージを一般には利用する:
ここでの記述は
import numpy as np import scipy as sp
とされていることが前提.ここにはよく使うものだけを示しているので,詳細はリファレンスを参照のこと.
ndarray オブジェクトは Numpy の配列で,python の配列と比べて,格納される内容の型を指定してメモリの効率化を図ったり,様々な操作が可能になる.ただし,python のようにリストではないので,配列内の要素型は全く自由というわけではなく,各行ごとに決めておく必要がある.matrix というオブジェクトもあって,行列積とかで動作が異なるが使わない方がいい.
普通のオブジェクトのようにオブジェクトそのものと,オブジェクトの内容のコピーとの区別には注意すること.同じメモリ上の要素を,異なるindexingで参照できるようにしたビューの概念もある(indexingを参照)
a * b などのかけ算は要素積で行列積にはならないことに注意.内積も行列積も dot(a,b)
生成方法:基本は以下のとおり
np.array([2, 3, 4]) … 1次元配列 np.array([[3, 4], [8, 10]]) … 2次元配列
ここではリストからの変換だったが,タプルからの変換もできる. 配列の型は次のように指定
np.array([2,3,4], dtype=int)
ndarrayの属性:
ndarrayのメソッド:
その他にも,argmax などの関数は a.argmax などのメソッドとして使えるものも多数ある.
python にある int や float に該当するスカラーの型.ndarray 配列の要素の型にできる.
bool_,int_,float_,complex_ が主な型だが,python標準の int や float でもまあ困らない.違いは float とかだとbit数がシステム依存だったりするが,float_ だと64bit指定.型はbit数なども細かく指定できるので,メモリが逼迫していたら指定するとよい.
配列の要素がスカラー型だとオブジェクトを代入できない.そんなときは配列を作るときに dtype=object_ としておくこと
値の参照と代入:次元ごとに "," で区切って要素を指定.
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a[1, 2]
6
逆に代入もできる
>>> a[2, 1] = -1
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, -1, 10, 11]])
添え字に負数を指定すると最後からの指定になる
>>> a[-1, -2] 10
1次元配列の 0, 3, 4 番目を参照しようとして "," で区切るとうまくいかないのでリストにする
>>> b array([ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> b[[0,3,4]] array([2, 5, 6])
a の 0,2行と,0,3列 で構成される 2×2 行列を作ろうとして次のようにすると
>>> a[[0,2],[0,3]] array([ 0, 11])
要素 [0,0] と [2,3] の指定になってしまう.こんなときは ix_ を使うと
>>> a[np.ix_([0,2],[0,3])]
array([[ 0, 3],
[ 8, 11]])
bool値での指定もできる(リストのままだと True=1, False=0 と解釈されるので配列にすること)
>>> a[np.array([False, True, True, False]), :]
array([[[ 4, 5, 6, 7],
[ 8, -1, 10, 11]]])
":" を使うとその次元の全ての要素になる.
>>> a[1, :] array([4, 5, 6, 7])
もちろん行や列ごとの代入もできる. 連続した要素は普通のシーケンスと同様に参照できる(シーケンスと同様に 1:3 の終わりは一つ少ない 1〜2 の意味であることに注意)
>>> a[:, 1:3]
array([[ 1, 2],
[ 5, 6],
[-1, 10]])
シーケンスと同様に増分も指定できる.
>>> b[1::3] array([3, 6, 9])
増分に負数を指定すると順序が逆転する
>>> a[:, ::-1]
array([[ 3, 2, 1, 0],
[ 7, 6, 5, 4],
[11, 10, -1, 8]])
次元数を増やしたいときは newaxis を使う
>>> b[np.newaxis, :]
array([[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])
>>> b[:, np.newaxis]
array([[ 2],
[ 3],
[ 4],
[ 5],
[ 6],
[ 7],
[ 8],
[ 9],
[10],
[11]])
3次元以上の配列で複数の次元の ":" をまとめて指定するには "..."(Ellipsisオブジェクト)を使う.
>>> c
array([[[10, 11],
[12, 13]],
[[14, 15],
[16, 17]]])
>>> c[..., 1]
array([[11, 13],
[15, 17]])
ビュー:同じメモリ領域に対し,異なる indexing で参照できる.同じメモリ領域なので,一方の内容を変更すると,もう一つのビューでの値も変わることに注意.
>>> a
array([[1, 2, 3],
[4, 5, 6]])
>>> b = a[:, 1:3]
>>> b
array([[2, 3],
[5, 6]])
>>> a[1,2] = -1
>>> b
array([[ 2, 3],
[ 5, -1]])
違う配列にしたいときは copy メソッドを使う
>>> c = a[:, 0:2].copy()
>>> c
array([[1, 2],
[4, 5]])
>>> a[0,0]=-10
>>> c
array([[1, 2],
[4, 5]])
イテレータ:ndarray をイテレータとして使うと,a.ndim より一つ次元の小さな部分配列を順次参照することになる.ndenumarate を使うと,全ての要素を順次参照できるタプルを返すイテレータ.要素の内容を順次参照したければ1次元配列のビュー a.flat などを使う.
broadcasting:"*" や "+" など配列の要素間で2項を演算するときに,二つ配列の要素の対応付けを行う規則.対応付けができる条件は以下のいずれかの場合
最後の条件は一方がスカラーの場合以外はあまり使わない方が安全
>>> a
array([[1, 2],
[3, 4]])
>>> a * 3
array([[ 3, 6],
[ 9, 12]])
2番目の条件を満たすように,明示的に newaxis を入れる方が安全
>>> b
array([10, 20])
>>> a * b[np.newaxis, :]
array([[10, 40],
[30, 80]])
>>> a * b[:,np.newaxis]
array([[10, 20],
[60, 80]])
エラー処理
キャスト規則:型のキャストルール
基本生成
既存データからの作成
範囲
行列生成
形状変換
転置
次元数の変換
結合・連結
分割
タイル
要素の追加・削除
要素の再配置
インデックスの配列の生成
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> c_[np.ones(a.shape[0]), a]
array([[ 1., 0., 1., 2., 3.],
[ 1., 4., 5., 6., 7.],
[ 1., 8., 9., 10., 11.]])nz = np.nonzero(a) a[nz] += a[nz] **2みたいにすると疎行列では効率的になる.メソッドもある.ちなみに次のように for を使うと遅い
for ix in np.nonzero(a):
a[ix] += a[ix] **2要素を選択して操作
配列へのデータの代入
イテレータ
dtype型の操作をする.普通に数値計算してるときはあまりお世話になることはないと思う.
print np.finfo(np.float32) print np.iinfo(np.uint8)
NPY/NPZ形式
テキスト形式
文字列フォーマット
memmapファイル
テキストのprint形式オプション
行列・ベクトルの積
分解
ノルムなど
線形方程式の解と逆行列
例外
乱数生成には python標準の random もある.こちらの random は高度なアルゴリズムを使っていて偏りが少なくなっているので,数値計算ではかならず np.random を使うべき.
乱数生成だけなので,確率密度関数や分位点が必要なときは scipy の sp.stats を使う.
再現性のある実験やテストをしたいときには,np.random.seed で乱数のシードを固定するとよい.
たいていの分布はあるのだが,Bernoulli分布 がなくて困ることがある.そのときは,2項分布・多項分布の np.binomial, np.multinomial で試行数を 1 に設定する.
np.random.binomial(1, p, size=100)
Pr[x=1 | y] を長さ 2 の配列 p[y] に入れているとする.y の実現値が配列 y = np.array([0, 1, 0, 0,..., 1]) のように入っているとき,Pr[x | y] に従う乱数を y 中のそれぞれの値について得るには次のようにする.for yi in y: などとすると遅い.
np.random.binomial(1, p[y])
順列
Sorting, searching, and counting
ソート
探索
計数
真理値のテスト
配列の内容チェック
行列の型チェック
論理演算
比較
要素ごとのビット演算
ビットのパック
分布の統計量などは sp.stats を参照のこと.
極値
平均と分散
相関
ヒストグラム
pxy = np.histogram2d(x, y, bins=(k, k), range=((0, k), (0, k)))[0] pxy = pxy / np.sum(pxy)
digamma や erf などもっと高度な数学関数は sp.special を参照のこと
三角関数
双曲線関数
まるめ
和・積・差
>>> n
array([[ 2., 3.],
[ 4., 2.]])
>>> n / np.sum(n, axis=1)[:, np.newaxis]
array([[ 0.4 , 0.6 ],
[ 0.66666667, 0.33333333]])指数・対数関数
その他の数学関数
浮動小数点
四則演算
複素数
その他
apply_along_axis(sigmoid, 1, x, w)関数の返す次元が100ぐらいまでは,リスト内包表記,それ以降は np.apply_along_axis がよいようだ
[sigmoid(x[i, :], w) for i in xrange(x.shape[0])]
apply_over_axes(np.sum, n, [1, 2]) / np.sum(n)
print numpy.vectorize(lambda x: x*2)(numpy.arange(1, 3)) #=> [2 4]
Polynomial, Legendre などいくつかの級数展開した式のクラスがあり評価や当てはめができる.多項式は特に以下のような簡易な関数がある.
離散フーリエ変換
libfft を呼び出す離散フーリエ変換の関数群.scipy があれば,そちらのルーチンが自動的に利用される.
日時処理関数
営業日かどうかを調べる
金融関数
金利関連計算
窓関数
関数や系列に掛け合わせる窓関数
浮動小数点エラー処理
オーバーフローなどの数値演算上のエラーがあるとき例外にするか何もしないかなどを決める seterr など
マスク付き配列
通常の配列用の関数をマスク付き配列用にしたもの.マスクの操作なども.
雑多な関数
メモリ領域(バッファ)の確保など
テスト用
unittest や doctest などを書くときに使う関数
自動型適応する数学関数
複素数を使うときに型変換が通常のものと異なる数学関数
scipyで高速化されうる関数
固有値・逆行列,フーリエ変換,Bessel関数の i0 などは scipy のものの方が高速だったりする.scipy がインストールされればそちらが使われる.
文字列操作
通常の文字列処理関数をベクトル処理できるように拡張
k-means法 の sp.cluster.vq と凝集型階層的クラスタリングの sp.cluster.hierarchy とがある
定数
黄金比,光速,重力定数,アボガドロ数など様々な定数
フーリエ変換
scipy があれば,numpy のものを呼び出してもこちらが使われる.
数値積分
関数や数列から数値積分を行う.
補間
numpy は interp は線形1次だけだが,多次元や,多項式・スプライン補間もある
入出力
matlab, matrix market, wav, arff, netcdf の入出力
線形代数
numpyより関数の種類は増えている.scipy があれば,numpy のものを呼び出してもこちらが使われる.
その他の関数
n次導関数,階乗など
画像処理.フィルタ処理など簡単なもの.より高度なものは opencv のラッパ関数など使うべき.
直交距離回帰
説明変数が独立でない場合の回帰
最適化と求根
最適化関数群だが,共役勾配法やニュートン法など基本的なものだけ.より高度な数値計画法は openopt,cvxopt,scikits.optimization パッケージを参照.
信号処理
たたみ込み,Bスプライン,ウェーブレット,各種フィルタ処理.
疎行列
ほとんどの要素が 0 の疎行列を処理する.あまりよくないとも聞くので Pysparse などのパッケージの方がよいかも.
空間アルゴリズムとデータ構造
近傍点の検索を高速化する kd-木 や,Delaunay三角形分割など
距離計算
ベクトル間の距離だけでなく,距離行列をまとめて計算できたりする.
特殊関数
numpy は初等関数だけだが,こちらは Bessel関数,ガンマ関数,誤差関数 (erf関数),Legendre関数の他,聞いたこともない関数がいろいろ.
統計関数