やさしい理系物理

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$ のうち下記を取り出せ。

  1. 後ろ30行と,それ以外に $2$ 分割せよ。
  2. 逆順にせよ。
また,行列 $C$ を,ベクトル $\boldsymbol c$ を $10\times10$ 行列に変形したものとして定義する。このうち,下記を取り出せ。
  1. 1〜7行目,1〜7列目までを取り出せ。
  2. 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$ 列の行列を生成せよ。

  1. 標準正規分布
  2. 区間 $[0,1]$ の一様分布(実数範囲)
  3. 区間 $[5,10]$ の一様分布(整数範囲)
  4. 正規分布 $\mathcal N(5,5^2)$
  5. $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で作成した各行列に対し,下記を計算して結果の妥当性を確認せよ。

  1. 行列成分の全平均と標準偏差を計算せよ。
  2. 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で作成)について,下記を計算せよ。

  1. すべての成分の合計値
  2. それぞれの行成分の合計値を,10行のベクトルにまとめたもの $\boldsymbol a_1$
  3. それぞれの列成分の合計値を,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$ )の通り。

  1. $i$ についての和 $b_{jk}=\sum_ia_{ijk}$ を行列 $B$ で表せ。
  2. $j$ についての和 $c_{ik}=\sum_ja_{ijk}$ を行列 $C$ で表せ。
  3. $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)

▲ To Top ▲