--- tags: general, numpy --- # はじめてのディープラーニング(分類) numpyを使った簡単な分類モデルになります。$-1 \leqq x \leqq 1$ 領域で$y(-1 \leqq y \leqq 1)$の値が$\sin{x \pi}$より大きいか小さいかを分類するモデルを構築します。 --- ### 0.1 ライブラリ ``` import numpy as np import matplotlib.pyplot as plt ``` ### モデル - 入力: ($x$, $y$) - 出力: $p = (p_{correct}, p_{wrong})$ 入力は、$-1 \leqq x \leqq 1$、$y(-1 \leqq y \leqq 1)$を0.1ずつ取った点の2次元$(x, y)$をランダムに入力しています。中間層は1層でノードは6つとします。活性化関数はsigmoid関数を使っています。出力層では、正解・不正解の確率を求めるために活性化関数にsoftmax関数を適用します。 また、損失関数は交差エントロピー関数、最適化アルゴリズムには確率的勾配降下法です。 ### 0.1 ハイパラメータ - $w$(重み):0.01 - $\eta$(学習率): 0.1 - $epoch$: 100 - $interval$: 10 ``` wb_width = 0.01 eta = 0.1 epoch = 101 interval = 10 ``` ### 0.2 入力データと正解データの準備 ```:qiita.rb X = np.arange(-1.0, 1.1, 0.1) Y = np.arange(-1.0, 1.1, 0.1) input_data = [] correct_data = [] for x in X: for y in Y: input_data.append([x, y]) if y < np.sin(np.pi * x): correct_data.append([0, 1]) else: correct_data.append([1, 0]) n_data = len(correct_data) input_data = np.array(input_data) correct_data = np.array(correct_data) ``` ## 1.1 中間層の構築 ``` class MiddleLayer: def __init__(self, n_upper, n): self.w = wb_width * np.random.rand(n_upper, n) self.b = wb_width * np.random.rand(n) def forward(self, x): self.x = x u = np.dot(x, self.w) + self.b self.y = 1 / (1 + np.exp(-u)) def backward(self, grad_y): delta = grad_y * (1 - self.y)*self.y self.grad_w = np.dot(self.x.T, delta) self.grad_b = np.sum(delta, axis=0) def update(self, eta): self.w -= eta * self.grad_w self.b -= eta * self.grad_b ``` ### 1.2 出力層の構築 ``` class OutputLayer: def __init__(self, n_upper, n): self.w = wb_width * np.random.randn(n_upper, n) self.b = wb_width * np.random.rand(n) def forward(self, x): self.x = x u = np.dot(x, self.w) + self.b self.y = np.exp(u) / np.sum(np.exp(u), axis=1, keepdims=True) def backward(self, t): delta = self.y - t self.grad_w = np.dot(self.x.T, delta) self.grad_b = np.sum(delta, axis=0) self.grad_x = np.dot(delta, self.w.T) def update(self, eta): self.w -= eta * self.grad_w self.b -= eta * self.grad_b ``` ### 1.3 モデルの宣言 ```classify.ipynb n_in = 2 n_mid = 6 n_out = 2 middle_layer = MiddleLayer(n_in, n_mid) output_layer = OutputLayer(n_mid, n_out) ``` ## 2.1 実装 ```classify.ipynb sin_data = np.sin(np.pi * X) for i in range(epoch): index_random = np.arange(n_data) np.random.shuffle(index_random) total_error = 0 x_1, y_1, x_2, y_2 = [], [], [], [] for idx in index_random: x = input_data[idx] t = correct_data[idx] middle_layer.forward(x.reshape(1, 2)) output_layer.forward(middle_layer.y) output_layer.backward(t.reshape(1, 2)) middle_layer.backward(output_layer.grad_x) middle_layer.update(eta) output_layer.update(eta) if i%interval == 0: y = output_layer.y.reshape(-1) total_error += - np.sum(t * np.log(y + 1e-7) ) if y [0] > y[1]: x_1.append(x[0]) y_1.append(x[1]) else: x_2.append(x[0]) y_2.append(x[1]) if i%interval == 0: plt.plot(X, sin_data, linestyle="dashed") plt.scatter(x_1, y_1, marker='+') plt.scatter(x_2, y_2, marker='x') plt.show() print(f"Epoch: {i} / {epoch}, Error: {total_error/n_data}") ``` https://github.com/jsakaguc/NCCEPOC/blob/main/general/classify.ipynb のclassify.ipynbで公開しています。