線形代数の基本計算
Contents
3. 線形代数の基本計算¶
3.1. はじめに¶
3.1.1. 開始前に行うこと(重要)¶
まず,Chrome 等のブラウザを利用して,本教材の URL にアクセスし,画面の指示に従い Google アカウントにログインしてください.その後,ブラウザ表示画面左上の「ファイル」をクリックし,さらにポップアップで出てくる項目から「ドライブにコピーを保存」をクリックしてください.これにより,本教材のコピーが自分のGoogleドライブに保存され,自分で書いたプログラムを実行できるようになります.
また,多くのセルが非表示になっていると思われるため,同じくブラウザ表示画面上の「表示」をクリックし,さらにその項目から「セクションを展開」をクリックし,非表示のセルを表示させてください.
Hint
各ページの上部にロケットのアイコン があるのでこれをクリックして各ページのファイルを Google Colaboratory 上で開いて利用してください.
3.1.2. 到達目標¶
NumPy を利用して複雑な行列計算ができるようになること目標とします.
3.1.3. NumPy とは¶
NumPy は Python で科学技術などを行う際に使用する基本的なライブラリです.ベクトルや行列を扱えるほか,線形代数や統計の基本処理や離散フーリエ変換を行うこともできます.C言語でコンパイルされているため,C言語並みに高速に動作します.使い方の概要や詳細については,NumPyユーザーガイドをご覧ください.
3.1.4. NumPy のインポート¶
NumPy は以下のようにインポートします.NumPy には np という略称を与えて利用するのが普通です.その都度 numpy とタイピングするのが面倒だからです.
import numpy as np
3.1.5. 学習の進め方¶
上から順に読み進み,【実習】と書いてある箇所でコードを書いて実行してください.基本的に入力するコードの前に見本のコードが書かれており,見本と同じコードを書けば正しく動作するようになっています(見本コードの上下に入っている区切り線は入力する必要ありません).理解を深めるには,見本とは異なるコードを書いて試してみることも役立つと思います. なお, Colab では,コードが書かれている領域をコードセル,説明文等が書かれている領域をテキストセルといいます.
3.2. ベクトルの基本操作¶
3.2.1. ベクトルの生成¶
NumPy の ndarray クラスを用いてベクトルを生成するには NumPy の array 関数にリストを渡します.
【実習】ベクトル x=[6 7 8] を生成する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
x = np.array([6, 7, 8])
print(x)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
リストを print すると,[6, 7, 8]のように要素間にカンマ(,)が入りますが,ndarray のベクトルを print すると[6 7 8]のようにカンマが入りません.これによりリストとベクトルを区別することができます.
生成したベクトル x のデータ型を確認するには,type(x)と書きます.
【実習】 ベクトル x の型を確認する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
type(x)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
生成したベクトルxの形(要素数)を確認するには,x.shapeと書きます.
【実習】 ベクトル x の形(要素数)を確認する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(x.shape)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
ベクトルのshapeは要素数1のタプルになります.値は3になっていますが,これは,1次元配列でその要素数が3であるという意味です.
3.2.2. ベクトルの基本演算¶
ベクトル x,y の足し算はx + y,引き算はx - y とすれば計算できます.
【実習】 ベクトル x=[6 7 8] とy = [1 2 3] に対して, x + yとx - y を計算する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
x = np.array([6, 7, 8])
y = np.array([1, 2, 3])
print(x + y)
print(x - y)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
掛け算や割り算についても同じ位置の要素ごとに演算が行われます.通常のベクトルの演算と異なるので注意が必要です.
【実習】 ベクトル x=[6 7 8] とy = [1 2 3] に対して, xと y の要素ごとの掛け算と割り算を計算する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(x * y)
print(x / y)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
同じ位置の要素ごとの積のことは,他の積と区別してアダマール積と呼ばれます.
ベクトルu,vの内積を行うにはnp.dot(u,v),外積を行うにはnp.cross(u,v)とします.
【実習】 ベクトル u=[3 4 0] とy = [-4 3 0] に対して, uと v の内積と外積を計算する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
u = np.array([3, 4, 0])
v = np.array([-4, 3, 0])
print(np.dot(u, v))
print(np.cross(u, v))
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
ndarrayによるベクトルには縦ベクトル(列ベクトル),横ベクトル(行ベクトル)といった方向の概念がないので注意しましょう.ベクトルと呼んでいますが,単にベクトル等の演算をサポートする1次元配列のことです.方向が必要な時は,ベクトルでなく行列(2次元配列)を使えばよいですが,ベクトルと行列は別物(ベクトルは1次元配列で行列は2次元配列)なので注意しましょう.詳細はNumPyユーザガイドを参照ください.
3.2.3. ブロードキャスト¶
ベクトルにスカラーをかけると,ベクトルの各要素にスカラー値が掛け算されます.このようにある演算をベクトル(や行列)の全要素に適用することをブロードキャストといいます.NumPyでは,乗算だけでなく,除算,加算,減算,べき乗などもブロードキャストできます.
【実習】 ブロードキャストを利用してベクトルxの各要素を2倍する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
x = np.array([6, 7, 8])
print(x * 2)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
【実習】 ブロードキャストを利用してベクトルxの各要素に10を足す
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(10 + x)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
【実習】 ブロードキャストを利用してベクトルxの各要素を2乗する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(x ** 2)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.2.4. 算術関数¶
NumPyの算術関数をベクトルに適用すると,基本的には要素ごとに計算します.
np.exp(x): eのべき乗np.log(x): 対数(底はe)np.sqrt(x): 平方根
使用可能な算術関数については,NumPy API ReferenceのMathematical functionsをご覧ください.
【実習】 ベクトルの各要素の平方根をとる
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
z = np.array([2, 3, 4])
print(np.sqrt(z))
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.2.5. 要素の確認と変更¶
リストと同様の書き方でベクトルの要素にアクセスできます.
【実習】 ベクトル x = [6 7 8] の2番目(index 1)の要素にアクセスする.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
x = np.array([6, 7, 8])
print(x[1])
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
リストと同様,スライスを使って複数の要素にアクセスすることもできます.
【実習】 ベクトル x = [6 7 8] の先頭2要素にアクセスする.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(x[0:2])
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
x[0:2] と書いた時,インデックス 0 は含まれるが,インデックス 2 は含まれないことに注意しましょう.つまりこの書き方ではインデックスが 0 以上 1 以下の要素が抜き出されます.
要素の値を変更するには,指定要素に値を代入します.
【実習】 ベクトル x = [6 7 8] の3番目(index 2)の要素の値を20に変更する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
x[2] = 20
print(x)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
スライスを使って複数要素に同時に値を代入することもできます.
【実習】 ベクトル x = [6 7 20] の先頭2要素の値を30, 31に変更する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
x[0:2] = 30, 31
print(x)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.2.6. ベクトルのコピー¶
ベクトルxをベクトルyにコピーする際は,y = np.copy(x) と書きます.
決して y = x と書いてはいけません.
【実習】 ベクトル x = [6 7 8] の値をベクトル y にコピーする.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
x = np.array([6, 7, 8])
#y = x # Wrong
y = np.copy(x)
x[1] = 100
print(y)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
y = x と書いてしまうと,変数yと変数xが同じオブジェクトIDを持つことになり,yはxの別名を表すことになってしまいます.つまり,xの値を変更すると勝手にyの値も変わってしまいします.リストでは,y = x[:]という書き方でコピーができましたが,NumPy の ndarray ではできません(これもyがxの別名になってしまう)ので注意しましょう.
3.3. 行列の基本操作¶
3.3.1. 行列の生成¶
NumPy の ndarray クラスを用いて行列を生成するには NumPy の array 関数に2次元リストを渡します.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}\) を生成する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
X = np.array([[1,2],[3,4]])
print(X)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
生成した行列Xの形(行と列それぞれの要素数)を確認するには,X.shapeと書きます.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}\) の形(行と列の要素数)を確認する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(X.shape)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Hint
1行(もしくは1列)の行列とベクトルは厳密に区別されますので注意しましょう.行列は2次元配列に線形代数の機能を追加したものであり,ベクトルは1次元配列に線形代数の機能を追加したものです.shapeで得られるタプルの要素数は,ベクトルでは1つ,行列では2つになります.
3.3.2. 行列に対する基本演算¶
行列に対する加減乗除は同じ位置の成分同士に対して行われます.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}, Y=\begin{bmatrix}5 & 6\\7 & 8\end{bmatrix}\) に対して,\(X+Y\)を計算する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
X = np.array([[1,2],[3,4]])
Y = np.array([[5,6],[7,8]])
print(X+Y)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
算術計算の関数も基本的には要素ごとに計算されます.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}\) に対して,成分ごとに対数をとる
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(np.log(X))
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
行列 X,Y に対して,X * Y と書くと,X と Y の成分ごとの積(アダマール積)が計算されます.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}, Y=\begin{bmatrix}5 & 6\\7 & 8\end{bmatrix}\) に対して,\(X\)と\(Y\)の成分ごとの積(アダマール積)を計算する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(X * Y)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
行列の成分ごとに積をとったもののことをアダマール積といいます.用語としては便利ですが,万人に通じる用語ではないので,使用する際は注意しましょう.
行列Xと行列Yの行列積を計算するには,X @ Yと書きます.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}, Y=\begin{bmatrix}5 & 6\\7 & 8\end{bmatrix}\) に対して,\(X\)と\(Y\)の行列積を計算する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(X @ Y)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
@による行列積計算はバージョン3.5以降のPythonで使用できます.それより前のPythonを使用する場合は,np.matmul関数を使用する必要があります.
行列においても,ベクトルと同様にブロードキャストを行うことができます.
【実習】 行列 \(X=\begin{bmatrix}1 & 2\\3 & 4\end{bmatrix}\) に対して,各成分の値を半分にした行列を計算する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(X / 2)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
行列\(S\) の行列式 \(det(S)\) を計算するにはnp.linalg.det(S) と書きます.
\(S=\begin{bmatrix}a & b\\c & d\end{bmatrix}\) の時,\(det(S)\) はベクトル \(\begin{bmatrix}a\\c\end{bmatrix}\) とベクトル \(\begin{bmatrix}b\\d\end{bmatrix}\) により作られる平行四辺形の符号付き面積を表します.
【実習】 行列 \(S=\begin{bmatrix}3 & 1\\1 & 2\end{bmatrix}\) に対して,\(S\)の行列式を計算する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
S = np.array([[3,1],[1,2]])
print(np.linalg.det(S))
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
Xの行列式は-2になりますが,np.linalg.det(X) の値は計算誤差により,-2ぴったりになっていないかもしれません.
行列Pの転置はP.Tと書きます.
【実習】 行列 \(P=\begin{bmatrix}1 & 2 \\3 & 4 \\ 5 & 6\end{bmatrix}\) に対して,\(P\)の転置を出力する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
P = np.array([[1,2],[3,4],[5,6]])
print(P.T)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Hint
ここで挙げたもの以外にも行列に関する様々な計算をNumPyを使って行うことができます.詳しくはNumpy API Reference Linear algebraをご覧ください.
3.3.3. 行列とベクトルの積¶
行列とベクトルとの行列積も @演算子を使って計算できます.この場合の計算結果はベクトルになります.NumPyのベクトルには向き(縦ベクトルや横ベクトル)の区別がないため,行列積を計算する際には最初に向きを決めないといけませんが,NumPy側でいい感じに向きを決めてくれます.
Note
Numpy API Referenceによれば,行列積計算において第1項が(n要素の)ベクトルの際は,まずそれを1行n列の行列に変換してから行列積を計算するようです.同様に,第2項がベクトルの際は,まずそれをn行1列の行列に変換してから行列積を計算するようです.そして行列積計算後,行列からベクトルに変換する(次元を上げた分を元に戻す)ようです.
【実習】 行列 \(W=\begin{bmatrix}5 & 2\\1 & 3\end{bmatrix}\),ベクトル \(z=\begin{bmatrix}2 \\1 \end{bmatrix}\) に対して,行列積\(Wz\)と\(z^T W\)を計算する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
W = np.array([[5,2],[1,3]])
z = np.array([2,1])
print(W @ z)
print(z @ W)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.3.4. 要素の確認と変更¶
行列Xの要素にアクセスするにはX[ ]の中にカンマ区切りで行と列を指定します.
インデックスが0始まりであることに気をつけましょう.
行列X の左上の要素は X[0,0] です.
【実習】 行列 \(Q=\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}\) の 0行1列の要素にアクセスする
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
Q = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(Q[0,1])
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
行と列のそれぞれに対してスライスを使って範囲を指定することができます.
【実習】 行列 \(Q=\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}\) の すべての行の先頭2列の要素にアクセスする
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(Q[:,0:2])
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Hint
スライス : の左側の数字を省略すると,最初からという意味になり,右側の数字を省略すると,最後までという意味になることを思い出しましょう.
【実習】 行列 \(Q=\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}\) の index 1の行をベクトルとして取り出す.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
print(Q[1,:])
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
行列Q の要素にアクセスする際,行と列の両方にインデックス値を指定すると,スカラー値が返ってきます.一方,行と列の両方にスライスを指定した場合は,行列(2次元配列)が返ってきます.また,行と列の片方をインデックス値,もう片方をスライスにすると,ベクトル(1次元配列)が返ってきます.
値を代入する処理も,ベクトルと同様に行えます. 複数の値を同時に代入することが可能です.
【実習】 行列 \(Q=\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}\) の index 1の行の値を34, 35, 36 に変更する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Q[1,:] = 34, 35, 36
print(Q)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
【実習】 行列 \(Q=\begin{bmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix}\) を行列 \(R\) にコピーする.
行列をコピーする処理もベクトルと同様にnp.copy()関数を用いて行います.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Q = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
#R = Q # Wrong
R = np.copy(Q)
Q[0,0] = 100
print(R)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.4. 応用的な操作や変形¶
3.4.1. ゼロ行列¶
要素がすべて0のベクトルを作るには,np.zeros() 関数にベクトルの要素数を渡します.
【実習】 要素数4のゼロベクトルを生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
d = np.zeros(4)
print(d)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
要素数がすべて0の行列を作るには,np.zeros() 関数に行列の shape(行と列の要素数を表すタプル)を渡します.タプルのカッコは省略できませんので注意しましょう.
【実習】 3行2列のゼロ行列を生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
E = np.zeros((3,2))
print(E)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
デフォルトでは,各要素は浮動小数点(float)型になります.
それ以外の型にするには,dtype を指定します.
【実習】 3行2列の整数型のゼロ行列を生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Z = np.zeros((3,2), dtype=int)
print(Z)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Hint
dtypeに指定可能な値については,NumPy User Guide Data typesをご覧ください.基本的には,np.int64のようにnp をつけて指定しますが,ユーザガイドによれば,int,bool,float,complexについてはnpを付けずに指定可能です.これらはそれぞれnp.int_,np.bool_,np.float_,np.complex_に変換されます.
すべての要素が1の行列を作るにはnp.zeros()の代わりにnp.ones()を使います.
【実習】 すべての要素の値が1であるような2行2列の行列を作成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
B = np.ones((2,2))
print(B)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.4.2. 単位行列¶
単位行列(対角成分が1それ以外が0の正方行列)を作るにはnp.identity()関数に単位行列の行数を渡します.dtype についてはnp.zeros()と同じ仕様です.
【実習】 3行3列の単位行列を作成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
I = np.identity(3)
print(I)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
3.4.3. 値を並べたベクトル¶
Pythonのfor文で使用するrangeと同様の仕様で,ベクトルを生成する関数として,np.arange()があります.
np.arange(n,m) と書くとn 以上 m 未満の連続した整数値からなるベクトルが生成されます.
【実習】 3以上8未満の連続した整数値からなるベクトルを生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
a = np.arange(3,8)
print(a)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Hint
arangeのつづりは英語の arrange とは異なりますので,注意しましょう.
np.arange(n,m) において先頭の数字nを省略し,np.arange(m) と書くと,0 以上 m 未満の連続した整数値からなるベクトルが生成されます.
【実習】 0以上8未満の連続した整数値からなるベクトルを生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
b = np.arange(8)
print(b)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
rangeと同様に一定間隔ごとに値を並べたベクトルを生成することもできます.
np.arange(n,m,s) と書くとn 以上 m 未満のの整数を間隔 s で取り出したベクトルが生成されます.
【実習】 0以上8未満の偶数値からなるベクトルを生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
e = np.arange(0,8,2)
print(e)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
np.arange() では,開始,終了の数値や間隔を浮動小数点数にすることができます.
【実習】 -2.0以上,3.0未満の数値を0.1間隔で取り出したベクトルを生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
x = np.arange(-2.0, 3.0, 0.1)
print(x)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
このようなベクトルは関数のグラフを描画する際によく使います. 関数 \(f(x)\) の描画は,\(x\) のそれぞれの値での \(f(x)\) の値を計算することにより行えます.
【実習】 \(f(x) = x^3 - x^2 - 2x\) を -2.0 以上,3.0 未満の範囲で描画する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import matplotlib.pyplot as plt
x = np.arange(-2.0, 3.0, 0.1)
f = x ** 3 - x ** 2 - 2 * x
print(f)
plt.plot(x, f)
plt.show()
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
ブロードキャストのおかげで,各\(x\)での\(f(x)\)の値を簡単に計算することができます.描画にはmatplotlibを使用しています.plot()が描画処理でshow()が画面に描画したものを表示する処理です.
等間隔で値を並べたベクトルを作る際,間隔を指定するのではなく,範囲と生成されるデータ数を指定することもできます.その場合には,np.linspace()関数使用します.np.linspace(p,q,n) と書くと,pからqまでの範囲をn等分してベクトルを生成します.
【実習】 np.linspace() を利用して,\(f(x) = x^3 - x^2 - 2x\) を -2.0 以上,3.0 未満の範囲で描画する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
x = np.linspace(-2.0, 3.0, 50)
f = x ** 3 - x ** 2 - 2 * x
print(x)
print(f)
plt.plot(x, f)
plt.show()
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
np.linspace() 関数のデフォルト設定では,終了位置の値もベクトルに含まれるようになっています.
3.4.4. ランダムな値を持つ行列¶
NumPyでは2019年7月にリリースされたver1.17.0から乱数の生成方式が変更になりました. 旧方式で乱数を生成する際はRandomStateと呼ばれるクラスを使用しますが,新方式で乱数を生成する際はGeneratorと呼ばれるクラスを使用します.
ここでは新方式を使う方法について説明します. 新方式の詳細についてはNumPy API Reference Random samplingをご覧ください.
乱数を生成する際は,まず,乱数生成器(Random Number Generator)を作ります.
rng = np.random.default_rng(12345)のように書くと rng という生成器が作られます.
以降では,rngという名前の生成器を使う前提で説明します.
上記において,12345の部分は乱数のシード(種)と呼ばれるもので,これを指定することで,毎回同じ乱数列が生成されるようになります.他の数字を指定することで,異なる乱数列が生成されるようになります. シードを指定しない場合は,引数をなしにします. 詳細は乱数生成器のAPI Referenceをご覧ください.
Note
再現性(後で実行しても同じ結果を得られる)が必要な場合は,シードを指定する必要があります.開発や実験の際は,再現性がある方が望ましいことが多いと思います.
乱数生成器から整数の乱数値を得るには,rng.integers()関数を使います.
rng.integers(a, b)のように書くと,a以上,b未満の整数乱数値を一つ得ることができます.
【実習】 0以上10未満の整数乱数を一つ生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
rng = np.random.default_rng(12345)
n = rng.integers(0,10)
print(n)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
整数乱数値を持つベクトルを生成するには,rng.integers(a, b, size=n)のようにベクトルの要素数nを指定します.
【実習】 0以上10未満の整数乱数5個からなるベクトルを生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
v = rng.integers(0,10, size=5)
print(v)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
整数乱数値を持つ行列を生成するには,rng.integers()のsize パラメータに行列のshape(行と列の数)を指定します
【実習】 0以上10未満の整数乱数値を持つ2行3列の行列を生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
W = rng.integers(0,10, size=(2,3))
print(W)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
ベクトルの値について要素間でシャッフルしたい場合は,rng.shuffle()関数を使います.
【実習】 ベクトル p = [1 3 4 5 6 10]の値をベクトル内でシャッフルする.)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
p = np.array([1, 3, 4, 5, 6, 10])
rng.shuffle(p)
print(p)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
乱数生成器から浮動小数点数の乱数値を得るには,rng.uniform()関数を使います.
rng.uniform(a, b, size=(n,m)) と書くと,a 以上b 未満の浮動小数点数が一様分布から生成され,n行m列の行列が作られます(a以上 b 未満のどの値も等確率で生成されます).
rng.integers()と同様に,sizeを指定しないと一つの乱数値が生成され,size に整数値を指定すると,その要素数のベクトルが生成されます.
【実習】 80以上100未満の浮動小数点数の乱数値を持つ2行3列の行列を生成する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
U = rng.uniform(80, 100, size=(2,3))
print(U)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
正規分布から生成される乱数値を得るには,rng.normal()関数を使います.
rng.normal(u, s, size=(n,m)) と書くと,平均値 u,標準偏差s の正規分布から乱数が生成され,n行m列の行列が作られます.
sizeについては,他と同様の仕様です.
【実習】 ある試験の得点分布が平均値80,標準偏差10の正規分布に従うと仮定して,40人の結果のサンプルをベクトルデータとして取得する.
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
N = rng.normal(80, 10, size=40)
print(N)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Hint
NumPyでは様々な分布から乱数を取得することができます.詳細はNumPy API Reference Random GeneratorのDistributionsを参照してください.
3.4.5. 行列の変形¶
行列の要素数を変えないまま,行と列の数を変更したり,ベクトルと行列の変換をしたりできます.
そのためには,ベクトルや行列(ndarray型のインスタンス)に対して,reshape()メソッドを呼びます.
d要素からなるベクトルvに対して,v.reshape(n,m)と書くと,vをn行m列に変換した行列が生成されます(vは変更されません).
一方,reshape(n)のように引数を一つにすると,ベクトルに変換されます.
【実習】 ベクトル \(w=\begin{bmatrix}0 & 1 & 2 & 3 & 4 & 5 \end{bmatrix}\) を変形して,行列 \(W=\begin{bmatrix}0 & 1 & 2 \\ 3 & 4 & 5 \end{bmatrix}\) を生成する
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
import numpy as np
w = np.arange(6)
W = w.reshape(2,3)
print(W)
#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#--#
Note
reshape()メソッドの引数の仕様を見ると,変形後の形shapeは一つの数値かタプルで指定されることになっているため,上記の変形処理はw.reshape((2,3))と引数をタプルにして呼ぶのが正しいように思われます.しかし,実はこのメソッドでは,タプルでなく,個別の引数として行列の形を指定することが許されています.つまり,w.reshape((2,3))のような2重カッコを使った書き方でなく,w.reshape(2,3)と書くことができます.
Note
終わりです.