Numpy20本ノック
この記事は今後更新する可能性があります。
0 はじめに・準備
Numpyは,Pythonにおいて数値計算を効率的に行うための拡張モジュールである。
ここでは,Numpyに慣れるための問題20問を紹介する。
準備として,Numpyをインポートしておこう。また,Matplotlibも一部問題で使うので,インポートしておく。
import numpy as np import matplotlib.pyplot as plt
1 行列の作成(1〜5本目)
ベクトル・行列を作成する
ノック1 次の行列・ベクトルを作成せよ。 \begin{gather} A=\begin{pmatrix} 1 & 4 & 2 \\ 8 & 5 & 7 \end{pmatrix}, \quad \boldsymbol a=\begin{pmatrix} 1 & 4 & 2 \end{pmatrix}, \quad \boldsymbol b=\begin{pmatrix} 8 \\ 5 \\ 7 \end{pmatrix} \end{gather}
【解答】
A = np.array([[1,4,2], [8,5,7]]) a = np.array([[1,4,2]]) b = np.array([[8],[5],[7]])
行列を「賢く」作る
ノック2 次の行列を「賢く」作成せよ。 \begin{gather} B=\begin{pmatrix} 1 & 3 & 5 \\ 7 & 9 & 11\\ 13 & 15 & 17 \end{pmatrix} \end{gather}
【解答】
B = np.arange(1, 18, 2).reshape(3,3)
補足 他にもnp.linspace
を用いる方法もある。
ゼロ行列・単位行列
ノック3 次の行列を「賢く」作成せよ。 \begin{gather} O=\begin{pmatrix} 0 & 0 & 0 \\ 0 & 0 & 0 \end{pmatrix}, \quad I=\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & 1 & 0 \end{pmatrix} \end{gather}
【解答】
O = np.zeros((2,3)) I = np.eye(3,4)
インデックス・スライシング
ノック4 ベクトル $\boldsymbol c$ を,標準正規分布に従う乱数を $100$ 個格納したものとして作成せよ。また, $\boldsymbol c$ のうち下記を取り出せ。
- 後ろ30行と,それ以外に $2$ 分割せよ。
- 逆順にせよ。
- 1〜7行目,1〜7列目までを取り出せ。
- 8〜10行目,8〜10列目までを取り出せ。
【解答】
c = np.random.randn(100) c[:-30] c[-30:] c[::-1] C = c.reshape(10,10) C[:-30,:-30] C[-30:,-30:]
補足 乱数生成のコードnp.random.randn
の詳細は,ノック11を参照のこと。
結合
ノック5 次の行列 $B, C$ を縦または横に結合せよ。 \begin{gather} B=\begin{pmatrix} 1 & 3 & 5 \\ 7 & 9 & 11\\ 13 & 15 & 17 \end{pmatrix}, \quad C=\begin{pmatrix} -1 & -3 & -5 \\ -7 & -9 & -11\\ -13 & -15 & -17 \end{pmatrix} \end{gather}
【解答】
B = np.arange(1, 18, 2).reshape(3,3) C = np.arange(-1, -18, -2).reshape(3,3) np.vstack((B,C)) #縦に結合 np.hstack((B,C)) #横に結合
1 基本的な行列演算(6〜10本目)
基本演算
ノック6 次の行列 $B, C$ の加算,減算,積算,アダマール積を計算せよ。 \begin{gather} B=\begin{pmatrix} 1 & 3 & 5 \\ 7 & 9 & 11\\ 13 & 15 & 17 \end{pmatrix}, \quad C=\begin{pmatrix} -1 & -3 & -5 \\ -7 & -9 & -11\\ -13 & -15 & -17 \end{pmatrix} \end{gather}
【解答】
B = np.arange(1, 18, 2).reshape(3,3) C = np.arange(-1, -18, -2).reshape(3,3) B + C #加算 B - C #減算 B @ C #積算 B * C #アダマール積
補足 行列の積は,他にもnp.matmul(A,B)
と書くことも多い。他にもnp.dot(A,B)
やA.dot(B)
のような書き方があるが,これはベクトルの内積計算のためにとっておき,行列の積としては(曖昧さ回避のため)用いないほうが良い。
転置・スカラー倍
ノック7 次の行列 $D$ の転置を取れ。またこれを利用して,行列 $D$ を対称行列と交代行列の和に分解せよ。 \begin{gather} D=\begin{pmatrix} 2 & 9 & 4 \\ 7 & 5 & 3\\ 6 & 1 & 8 \end{pmatrix} \end{gather}
【解答】
D = np.array([[2,9,4], [7,5,3], [6,1,8]]) D.T #転置 (D + D.T)/2 #対称行列 (D - D.T)/2 #交代行列
階数・行列式・逆行列
ノック8 次の行列 $D$ の階数,行列式と逆行列を計算せよ。 \begin{gather} D=\begin{pmatrix} 2 & 9 & 4 \\ 7 & 5 & 3\\ 6 & 1 & 8 \end{pmatrix} \end{gather}
【解答】
D = np.array([[2,9,4], [7,5,3], [6,1,8]]) rankD = np.linalg.matrix_rank(D) #階数 detD = np.linalg.det(D) #行列式 invD = np.linalg.inv(D) #逆行列
行列のトレース
ノック9 次の行列 $B, D$ について,計算により $\operatorname{tr}(BD)=\operatorname{tr}(DB)$ を確認せよ。 \begin{gather} B=\begin{pmatrix} 1 & 3 & 5 \\ 7 & 9 & 11\\ 13 & 15 & 17 \end{pmatrix}, \quad D=\begin{pmatrix} 2 & 9 & 4 \\ 7 & 5 & 3\\ 6 & 1 & 8 \end{pmatrix} \end{gather}
【解答】
np.trace(D * B) np.trace(B * D)
ユニバーサル関数
ノック10 次の行列 $E$ を数理的に作成し,$\rm sin, tan$ 関数で各成分を演算せよ。 \begin{gather} E=\begin{pmatrix} 0 & \pi \\ \pi/4 & \pi/6 \end{pmatrix} \end{gather}
【解答】
E = np.array([0, np.pi, np.pi/4, np.pi/6]).reshape(2,2) np.sin(E) np.tan(E)
3 機械学習への一歩(11〜20本目)
乱数生成
ノック11 各成分が下記の乱数分布に従う,$5$ 行 $20$ 列の行列を生成せよ。
- 標準正規分布
- 区間 $[0,1]$ の一様分布(実数範囲)
- 区間 $[5,10]$ の一様分布(整数範囲)
- 正規分布 $\mathcal N(5,5^2)$
- $0$ から $99$ までの数字をランダムに並べたもの。ただし重複は許さない
【解答】
np.random.seed(0) #乱数の種を指定(再現性を確保できる) np.random.randn(5,20) np.random.rand(5,20) np.random.randint(5,10,(5,20)) np.random.normal(5,5,(5, 20)) np.random.choice(100,(5, 20),replace=False)
乱数生成(一様分布)
ノック12 ノック11で作成した各行列に対し,下記を計算して結果の妥当性を確認せよ。
- 行列成分の全平均と標準偏差を計算せよ。
- Matplotlibを用いて全成分の値をヒストグラムに可視化せよ。
【解答】
# それぞれの行列(data1とする)に対して,下記を計算する np.mean(data1) #平均を確認 np.std(data1) #標準偏差を確認 data1_ = data1.reshape(1,1000)[0] #可視化するため,1列に並べる plt.hist(data1_, bins=30)
補足 他にも乱数の生成には,標準正規分布を作成するnp.random.randn
,一様分布を整数範囲で作成するnp.random.randint
がある。すべて覚えておこう。
リスト内包表記
ノック13 次の行列 $A$ を「賢く」作成せよ。 \begin{gather} A=\begin{pmatrix} 1 & 1 & 1 \\ 2 & 4 & \sqrt{2}\\ 3 & 9 & \sqrt{3}\\ \vdots & \vdots & \vdots\\ 10 & 100 & \sqrt{10}\\ \end{pmatrix} \end{gather}
【解答】
#[式 for 変数 in イテラブル]の形で書く np.array([[x,x**2,np.sqrt(x)] for x in range(1,11)])
ブロードキャスト
ノック14 前の行列 $A$(ノック13で作成)から,以下のベクトル $\boldsymbol x$ を縦に10個つなげた行列を除算せよ。 \begin{gather} \boldsymbol x=\begin{pmatrix} 1 & 2 & 3 \end{pmatrix} \end{gather}
【解答】
x = np.array([1,2,3]) A-x
合計
ノック15 前の行列 $A$(ノック13で作成)について,下記を計算せよ。
- すべての成分の合計値
- それぞれの行成分の合計値を,10行のベクトルにまとめたもの $\boldsymbol a_1$
- それぞれの列成分の合計値を,3行のベクトルにまとめたもの $\boldsymbol a_2$
【解答】
np.sum(A) #すべての合計 a_1 = np.sum(A, axis=1) #各行の合計 a_2 = np.sum(A, axis=0) #各列の合計
補足 axis
は変数とする軸を指定していることに注意。例えば,axis=0
であれば,行(1つ目の添字)を変数として和を取ることを示す。
補足 上記を用いると,ベクトルの内積は,np.dot(a,b)
やa.dot(b)
以外にもnp.sum(a * b)
という書き方ができる。
最小値の行番号を取得
ノック16 前の行列 $\boldsymbol a_1,\boldsymbol a_2$(ノック15で作成)について,値の最大・最小値と,そのときのインデックス( $0$ 始まりの行番号)を取り出せ。
【解答】
np.min(a_1) np.argmin(a_1) np.max(a_1) np.argmax(a_1) # a_2についても同じ
ランダムに行を抽出
ノック17 前の行列 $A$(ノック13で作成)についてランダムに $4$ つの行を取り出して, $4\times 3$ 行列を作れ。
【解答】
# np.random.choice(配列 or 整数, 選ぶ個数, replace=True or False) A[np.random.choice(10, 4, replace=False)]
条件にあった行をすべて抽出
ノック18 前の行列 $A$(ノック13で作成)について,$3$ 列目が $2$ 以下の行列をすべて抽出せよ。また,67に等しい成分があるか判定せよ。
【解答】
A[A[:,2] <= 2] np.any(A[:,:] == 67)
axisの意味
ノック19 次の $3$ 階テンソル $a_{ijk}$ を考える。各成分は以下のコード( $A$ )の通り。
- $i$ についての和 $b_{jk}=\sum_ia_{ijk}$ を行列 $B$ で表せ。
- $j$ についての和 $c_{ik}=\sum_ja_{ijk}$ を行列 $C$ で表せ。
- $k$ についての和 $d_{ij}=\sum_ka_{ijk}$ を行列 $D$ で表せ。
A = np.array([[[0, 1], [0, 1], [0, 1], [0, 1]], [[0, 1], [0, 1], [0, 1], [0, 1]], [[0, 1], [0, 1], [0, 1], [0, 1]]])
【解答】
np.sum(A, axis=0) np.sum(A, axis=1) np.sum(A, axis=2)
いびつなサイコロ
ノック20 いびつなサイコロがあり,それぞれ出る目の確率は以下のベクトル $\boldsymbol a$ で与えられている。この確率に従って,サイコロを10回振り,結果をベクトルに格納せよ。
\begin{gather} \boldsymbol a=\begin{pmatrix} 1/36 & 1/4 & 1/9 & 1/12 & 7/36 & 1/3 \end{pmatrix} \end{gather}【解答】
p = np.array([1/36 , 1/4 , 1/9 , 1/12 , 7/36 , 1/3]) np.random.choice([1,2,3,4,5,6], p=p, size=10)