Work in progress. Basic linear algebra to be included here. (基礎の線形代数がここに含まれる。)
See linalg.py
in numpy folder for more.
import numpy as np
a = np.array([
[1.0, 2.0],
[3.0, 4.0]
])
print(a)
[[ 1. 2.] [ 3. 4.]]
a.transpose() # 転置
array([[ 1., 3.], [ 2., 4.]])
a.transpose() == a.T # Tも同じ
array([[ True, True], [ True, True]], dtype=bool)
np.linalg.inv(a) # 逆行列
array([[-2. , 1. ], [ 1.5, -0.5]])
$ A = \left( \begin{array}{cc} a & b \\ c & d \end{array} \right) $ , $ A^{-1} = \left( \begin{array}{cc} a^{-1} & b^{-1} \\ c^{-1} & d^{-1} \end{array} \right) $ として、
$$ \left( \begin{array}{cc} a & b \\ c & d \end{array} \right) \left( \begin{array}{cc} a^{-1} & b^{-1} \\ c^{-1} & d^{-1} \end{array} \right) = \left( \begin{array}{cc} 1 & 0 \\ 0 & 1 \end{array} \right) $$\begin{eqnarray} a * a^{-1} + b * c{^-1} = 1\\ a * b^{-1} + b * d^{-1} = 0\\ c * a^{-1} + d * c^{-1} = 0\\ c * b^{-1} + d * d^{-1} = 1\\ \end{eqnarray}$$ c * a^{-1} + d * c^{-1} = 0 \\ c^{-1} = - \frac{c*a^{-1}}{d} $$\begin{eqnarray} a * a^{-1} + b * c{^-1} &=& 1 \\ a * a^{-1} - b * \frac{c*a^{-1}}{d} &=& 1 \\ (a - \frac{bc}{d})a^{-1} &=&1\\ a^{-1} &=& \frac{1}{(a - \frac{bc}{d})}\\ &=& \frac{d}{(ad - bc)}\\ \end{eqnarray}\begin{eqnarray} c^{-1} &=& - \frac{c}{d}*\frac{d}{(ad - bc)}\\ &=& - \frac{c}{(ad - bc)}\\ \end{eqnarray}\begin{eqnarray} c^{-1} &=& - \frac{c}{d}*\frac{d}{(ad - bc)}\\ &=& - \frac{c}{(ad - bc)}\\ \end{eqnarray}\begin{eqnarray} a * b^{-1} + b * d^{-1} &=& 0 \\ d^{-1} &=& -\frac{a * b^{-1}}{b} \end{eqnarray}\begin{eqnarray} c * b^{-1} + d * d^{-1} &=& 1 \\ c * b^{-1} + d * -\frac{a * b^{-1}}{b} &=& 1 \\ (c - d\frac{a}{b})b^{-1} &=& 1\\ b^{-1} &=& - \frac{1}{d\frac{a}{b} - c}\\ &=& - \frac{b}{ad - bc} \end{eqnarray}\begin{eqnarray} d^{-1} &=& -\frac{a * b^{-1}}{b}\\ &=& -\frac{a}{b} * - \frac{b}{ad - bc}\\ &=& \frac{a}{ad - bc}\\ \end{eqnarray}$$ A^{-1} = \frac{1}{ad-bc} \left( \begin{array}{cc} d & -b \\ -c & a \end{array} \right) $$u = np.eye(2) # unit 2x2 matrix; "eye" represents "I" 単位行列
u
array([[ 1., 0.], [ 0., 1.]])
j = np.array([
[0.0, -1.0],
[1.0, 0.0]
])
j
array([[ 0., -1.], [ 1., 0.]])
np.dot(j, j) # matrix product
array([[-1., 0.], [ 0., -1.]])
j.dot(j)
array([[-1., 0.], [ 0., -1.]])
np.trace(u) # trace
2.0
y = np.array([
[5.],
[7.]
])
y
array([[ 5.], [ 7.]])
np.linalg.solve(a, y) # 2元連立方程式 A^-1 * y
array([[-3.], [ 4.]])
eig_val, eig_vec = np.linalg.eig(j)
eig_val, eig_vec
(array([ 0.+1.j, 0.-1.j]), array([[ 0.70710678+0.j , 0.70710678-0.j ], [ 0.00000000-0.70710678j, 0.00000000+0.70710678j]]))
A = np.matrix('1.0 2.0; 3.0 4.0')
A
matrix([[ 1., 2.], [ 3., 4.]])
type(A) # クラスを定義しているファイル
numpy.matrixlib.defmatrix.matrix
A.T # 転置
matrix([[ 1., 3.], [ 2., 4.]])
X = np.matrix('5.0 7.0')
X
matrix([[ 5., 7.]])
Y = X.T
Y
matrix([[ 5.], [ 7.]])
print(A * Y) # 行列の乗算
[[ 19.] [ 43.]]
print(A.I) # 逆行列
[[-2. 1. ] [ 1.5 -0.5]]
np.linalg.solve(A, Y) # 線形方程式を解く
matrix([[-3.], [ 4.]])
NumPy の配列と行列の間にはいくつかの重要な差異があることに注意。
NumPy は、
という2種類の基本的なオブジェクトを用意している。 その他のオブジェクトはこれら2つの上に構築されている。
特に、行列はNumPyのarrayオブジェクトを継承した2次元配列オブジェクトである。 配列も行列も、添字は以下の1つもしくは複数の適切な組み合わせで構成されていなければならない:整数スカラー値、省略記号、整数または真偽値のリスト、整数または真偽値のタプル、整数または真偽値の1次元配列。 行列を行列のindex として用いることもできるが、普通は配列、リスト、あるいは他の形で事が足りる。 Pythonでもそうであるように、index は0ベースである。 伝統的に我々は2次元配列や行列を行と列の長方形の配列として表す。 軸0に沿った動きは行を横切り、軸1に沿った動きは列を横切る。
A = np.arange(12)
A
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
A.shape = (3,4)
A
array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
M = np.mat(A.copy())
M
matrix([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
print(type(A), ' ', type(M))
<class 'numpy.ndarray'> <class 'numpy.matrixlib.defmatrix.matrix'>
print(A)
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
print(M)
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
ここで、いくつか単純なスライスを取ってみる。 基本的なスライシングにはスライスオブジェクトまたは整数の組を用いる。
例えば、A[:]
と M[:]
の評価はPython の index付けに似たものに見えるのだが、重要なのはNumPy配列のスライシングはデータをコピーしないという点である。
スライシングは同じデータに対し新しいview を提供する。
print(A[:])
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
print(A[:].shape)
(3, 4)
print(M[:])
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]]
print(M[:].shape)
(3, 4)
Python のindex付けと異なるが、 複数の軸に沿って同時にindex付けする場合にカンマ区切りのindex が使える。
print(A[:, 1])
[1 5 9]
print(A[:, 1].shape)
(3,)
print(M[:, 1])
[[1] [5] [9]]
print(M[:, 1].shape)
(3, 1)
最後の2つの結果は異なる。
行列のスライスは常に行列を生み出す。
例えばスライス M[2, :]
は shape (1, 4)
の行列になるが、
対照的に、配列のスライスは常に可能な限り一番低い次元の配列になる。
例えば C
が3次元配列だとすると、
C[..., 1]
は2次元配列に、C[1, :, 1]
は1次元配列になる。配列の1番目と3番目の列が欲しいとしよう。 リストを使ってスライスするのが1つの方法である:
A
array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
A[:, [1, 3]]
array([[ 1, 3], [ 5, 7], [ 9, 11]])
take()
メソッドを使うというのもある:
A.take([1, 3], axis=1)
array([[ 1, 3], [ 5, 7], [ 9, 11]])
最初の行(第0軸の0番目)を飛ばしたいなら以下のようになる:
A[1:,].take([1, 3], axis=1)
array([[ 5, 7], [ 9, 11]])
あるいは単に A[1:, [1, 3]]
としてもよい。
上のをスライスするもう1つの方法は、numpy.ix_
の利用がある:
np.ix_((1, 2), (1, 3))
(array([[1], [2]]), array([[1, 3]]))
A
array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
A[np.ix_((1, 2), (1, 3))]
array([[ 5, 7], [ 9, 11]])
1行目が1より大きい全ての列を保持したいととする。 まずは真偽値のindex を作る方法:
A[0, :] > 1
array([False, False, True, True], dtype=bool)
しかし行列をindex付けするのはあまり便利ではない。
M[0, :] > 1
matrix([[False, False, True, True]], dtype=bool)
M[:, M[0, :] > 1]
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-44-d1c10536344f> in <module>() ----> 1 M[:, M[0, :] > 1] C:\Miniconda3\lib\site-packages\numpy\matrixlib\defmatrix.py in __getitem__(self, index) 316 317 try: --> 318 out = N.ndarray.__getitem__(self, index) 319 finally: 320 self._getitem = False IndexError: too many indices for array
問題としているのは、行列スライスをスライスすることで行列が生成されてしまう点である。 しかし行列には便利な'A'属性があって、この値はその行列の配列表現になっているので、代わりにこうするだけで良い:
M[:, M.A[0, :] > 1]
matrix([[ 2, 3], [ 6, 7], [10, 11]])
行列を条件によって2つの方向にスライスしたいのであれば、 戦略をわずかに補正しなければならない。
A
array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
A[:, 0] > 2
array([False, True, True], dtype=bool)
A[0, :] > 1
array([False, False, True, True], dtype=bool)
A[A[:, 0] > 2, A[0, :] > 1]
array([ 6, 11])
の代わりに、外積 'ix_'
を用いる:
np.ix_(A[:, 0] > 2, A[0, :] > 1)
(array([[1], [2]], dtype=int64), array([[2, 3]], dtype=int64))
A[np.ix_(A[:, 0] > 2, A[0, :] > 1)]
array([[ 6, 7], [10, 11]])
M[np.ix_(M.A[:, 0] > 2, M.A[0, :] > 1)]
matrix([[ 6, 7], [10, 11]])
How do we construct a 2D array from a list of equally-sized row vectors? (サイズの等しい行ベクトルのリストから2次元配列を構築するにはどうするか?)
In MATLAB this is quite easy(MATLABではこれはとても簡単):
if x
and y
are two vectors of the same length you only need do m = [x; y]
.
(x
と y
の2つが同じ長さのベクトルなら、m=[x;y]
とするだけで良い。)
In NumPy this works via the functions column_stack
,
dstack
, hstack
and vstack
,
depending on the dimension in which the stacking is to be done.
(NumPyでは、関数 column_stack
, dstack
, hstack
, vstack
で同じことができる、
関数の選択はスタックが行われる次元に依存する。)
For example:
x = np.arange(0, 10, 2) # x=([0,2,4,6,8])
y = np.arange(5)# y=([0,1,2,3,4])
m = np.vstack([x, y]) # m=([[0,2,4,6,8],
m # [0,1,2,3,4]]), 2 * 5
array([[0, 2, 4, 6, 8], [0, 1, 2, 3, 4]])
m.shape
(2, 5)
xy = np.hstack([x, y]) # xy =([0,2,4,6,8,0,1,2,3,4]) # 1 * 10
xy
array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4])
xy.shape
(10,)
See alse:
The NumPy histogram
function applied to an array returns a pair of vectors(NumPy のhistogram
関数は、2つのベクトルを返す配列に適用される):
the histogram of the array and the vector of bins.
(配列のヒストグラムと、瓶(bins)のベクトル、が返ってくる。)
Beware: matplotlib
also has a function to build histograms (called hist
, as in Matlab) that differs from the one in NumPy.
(注意:matplotlib
にもヒストグラムを構築する関数がある
(Matlabと同様 hist と呼ばれる)が、NumPyのものとは異なる。)
The main difference is that pylab.hist
plots the histogram automatically,
while numpy.histogram
only generates the data.
(主な違いは、pylab.hist
はヒストグラムを自動的に描画するが、
numpy.histogram
はデータを生成するところまでしか行わない点である。
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
(mu, sigma) = 2, 0.5
v = np.random.normal(mu, sigma, 10000)
# Plot a normalized histogram with 50 bins
plt.hist(v, bins=50, normed=1) # matplotlib version (plot)
plt.show()
%matplotlib inline
# Compute the histogram with numpy and then plot it
(n, bins) = np.histogram(v, bins=50, normed=True) # NumPy version (no plot)
print('n ', n)
print('bins', bins)
print('bins[:-1]', bins[:-1])
plt.plot(.5 * (bins[:-1] + bins[1:]), n)
n [ 0.00547374 0.00136843 0.00547374 0.01231591 0.01505278 0.02326339 0.02189496 0.04242148 0.0547374 0.07526392 0.09305357 0.16284375 0.17379123 0.21073898 0.28052916 0.31337159 0.41874108 0.56926892 0.57611109 0.66505936 0.70748085 0.72663893 0.77453416 0.69242806 0.81969251 0.79779755 0.73484954 0.75400763 0.69242806 0.56653205 0.54053179 0.43242543 0.36810899 0.31200316 0.25452889 0.20115993 0.17515967 0.12042227 0.07526392 0.07115862 0.05063209 0.03421087 0.01778965 0.01505278 0.01505278 0. 0.00136843 0.00821061 0.00273687 0.00136843] bins [ 0.22548126 0.29855745 0.37163363 0.44470981 0.517786 0.59086218 0.66393836 0.73701455 0.81009073 0.88316691 0.9562431 1.02931928 1.10239546 1.17547165 1.24854783 1.32162401 1.3947002 1.46777638 1.54085256 1.61392875 1.68700493 1.76008111 1.8331573 1.90623348 1.97930966 2.05238585 2.12546203 2.19853821 2.2716144 2.34469058 2.41776676 2.49084295 2.56391913 2.63699531 2.7100715 2.78314768 2.85622386 2.92930005 3.00237623 3.07545241 3.1485286 3.22160478 3.29468096 3.36775715 3.44083333 3.51390951 3.5869857 3.66006188 3.73313806 3.80621425 3.87929043] bins[:-1] [ 0.22548126 0.29855745 0.37163363 0.44470981 0.517786 0.59086218 0.66393836 0.73701455 0.81009073 0.88316691 0.9562431 1.02931928 1.10239546 1.17547165 1.24854783 1.32162401 1.3947002 1.46777638 1.54085256 1.61392875 1.68700493 1.76008111 1.8331573 1.90623348 1.97930966 2.05238585 2.12546203 2.19853821 2.2716144 2.34469058 2.41776676 2.49084295 2.56391913 2.63699531 2.7100715 2.78314768 2.85622386 2.92930005 3.00237623 3.07545241 3.1485286 3.22160478 3.29468096 3.36775715 3.44083333 3.51390951 3.5869857 3.66006188 3.73313806 3.80621425]
[<matplotlib.lines.Line2D at 0x25abbc7f780>]