01#
Feed-Forward-Neural Network
# coding: utf-8
import numpy as np
class Sigmoid:
def __init__(self):
self.params = []
def forward(self, x):
return 1 / (1 + np.exp(-x))
class Affine:
"""全結合層"""
def __init__(self, W, b):
self.params = [W, b]
def forward(self, x):
W, b = self.params
out = np.dot(x, W) + b
return out
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size):
I, H, O = input_size, hidden_size, output_size
# 重みとバイアスの初期化
W1 = np.random.randn(I, H)
b1 = np.random.randn(H)
W2 = np.random.randn(H, O)
b2 = np.random.randn(O)
# レイヤの生成
self.layers = [
Affine(W1, b1),
Sigmoid(),
Affine(W2, b2)
]
# すべての重みをリストにまとめる
self.params = []
for layer in self.layers:
self.params += layer.params
def predict(self, x):
for layer in self.layers:
x = layer.forward(x)
return x
x = np.random.randn(10, 2)
model = TwoLayerNet(2, 4, 3)
s = model.predict(x)
print(s)
[[-0.48752465 0.11518121 -1.04049482]
[-0.47713612 0.20101648 -0.98699504]
[ 0.26514357 1.13443041 -0.42999073]
[-0.54661483 -0.1807521 -1.19405482]
[-0.99211321 -0.88923083 -1.46939115]
[-0.49057396 0.23382003 -0.95806258]
[-0.06208114 0.83421739 -0.62555826]
[-0.85648298 -0.59869829 -1.40647367]
[ 0.37119061 1.51815419 -0.41863833]
[ 0.11372937 1.05944944 -0.53456558]]
逆伝播#
MatMul(行列積)#
\(xW\)の部分について。
\(x_i\)の微分
\[
\frac{\partial L}{\partial x_i}
= \sum_j \frac{\partial L}{\partial y_j} \frac{\partial y_j}{\partial x_i}
\]
は\(\frac{\partial y_j}{\partial x_i}=W_{ij}\)から
\[
\newcommand{\b}[1]{\boldsymbol{#1}}
\frac{\partial L}{\partial \b{x}}
= \frac{\partial L}{\partial \b{y}} \b{W}^T
\]
となる
class MatMul:
def __init__(self, W):
self.params = [W]
self.grads = [np.zeros_like(W)]
self.x = None
def forward(self, x):
W, = self.params
out = np.dot(x, W)
self.x = x
return out
def backward(self, dout):
W, = self.params
dx = np.dot(dout, W.T)
dW = np.dot(self.x.T, dout)
self.grads[0][...] = dW
return dx
NNet#
class MatMul:
def __init__(self, W):
self.params = [W]
self.grads = [np.zeros_like(W)]
self.x = None
def forward(self, x):
W, = self.params
out = np.dot(x, W)
self.x = x
return out
def backward(self, dout):
W, = self.params
dx = np.dot(dout, W.T)
dW = np.dot(self.x.T, dout)
self.grads[0][...] = dW
return dx
class Affine:
def __init__(self, W, b):
self.params = [W, b]
self.grads = [np.zeros_like(W), np.zeros_like(b)]
self.x = None
def forward(self, x):
W, b = self.params
out = np.dot(x, W) + b
self.x = x
return out
def backward(self, dout):
W, b = self.params
dx = np.dot(dout, W.T)
dW = np.dot(self.x.T, dout)
db = np.sum(dout, axis=0)
self.grads[0][...] = dW
self.grads[1][...] = db
return dx
class SoftmaxWithLoss:
def __init__(self):
self.params, self.grads = [], []
self.y = None # softmaxの出力
self.t = None # 教師ラベル
def forward(self, x, t):
self.t = t
self.y = softmax(x)
# 教師ラベルがone-hotベクトルの場合、正解のインデックスに変換
if self.t.size == self.y.size:
self.t = self.t.argmax(axis=1)
loss = cross_entropy_error(self.y, self.t)
return loss
def backward(self, dout=1):
batch_size = self.t.shape[0]
dx = self.y.copy()
dx[np.arange(batch_size), self.t] -= 1
dx *= dout
dx = dx / batch_size
return dx
class Sigmoid:
def __init__(self):
self.params, self.grads = [], []
self.out = None
def forward(self, x):
out = 1 / (1 + np.exp(-x))
self.out = out
return out
def backward(self, dout):
dx = dout * (1.0 - self.out) * self.out
return dx
class TwoLayerNet:
def __init__(self, input_size, hidden_size, output_size):
I, H, O = input_size, hidden_size, output_size
# 重みとバイアスの初期化
W1 = 0.01 * np.random.randn(I, H)
b1 = np.zeros(H)
W2 = 0.01 * np.random.randn(H, O)
b2 = np.zeros(O)
# レイヤの生成
self.layers = [
Affine(W1, b1),
Sigmoid(),
Affine(W2, b2)
]
self.loss_layer = SoftmaxWithLoss()
# すべての重みと勾配をリストにまとめる
self.params, self.grads = [], []
for layer in self.layers:
self.params += layer.params
self.grads += layer.grads
def predict(self, x):
for layer in self.layers:
x = layer.forward(x)
return x
def forward(self, x, t):
score = self.predict(x)
loss = self.loss_layer.forward(score, t)
return loss
def backward(self, dout=1):
dout = self.loss_layer.backward(dout)
for layer in reversed(self.layers):
dout = layer.backward(dout)
return dout
def spiral_data(seed=1984):
np.random.seed(seed)
N = 100 # クラスごとのサンプル数
DIM = 2 # データの要素数
CLS_NUM = 3 # クラス数
x = np.zeros((N*CLS_NUM, DIM))
t = np.zeros((N*CLS_NUM, CLS_NUM), dtype=np.int)
for j in range(CLS_NUM):
for i in range(N):#N*j, N*(j+1)):
rate = i / N
radius = 1.0*rate
theta = j*4.0 + 4.0*rate + np.random.randn()*0.2
ix = N*j + i
x[ix] = np.array([radius*np.sin(theta),
radius*np.cos(theta)]).flatten()
t[ix, j] = 1
return x, t
# ハイパーパラメータの設定
max_epoch = 300
batch_size = 30
hidden_size = 10
learning_rate = 1.0
x, t = spiral_data()
model = TwoLayerNet(input_size=2, hidden_size=hidden_size, output_size=3)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[5], line 30
27 hidden_size = 10
28 learning_rate = 1.0
---> 30 x, t = spiral_data()
31 model = TwoLayerNet(input_size=2, hidden_size=hidden_size, output_size=3)
Cell In[5], line 8, in spiral_data(seed)
5 CLS_NUM = 3 # クラス数
7 x = np.zeros((N*CLS_NUM, DIM))
----> 8 t = np.zeros((N*CLS_NUM, CLS_NUM), dtype=np.int)
10 for j in range(CLS_NUM):
11 for i in range(N):#N*j, N*(j+1)):
File ~/work/notes/notes/.venv/lib/python3.10/site-packages/numpy/__init__.py:324, in __getattr__(attr)
319 warnings.warn(
320 f"In the future `np.{attr}` will be defined as the "
321 "corresponding NumPy scalar.", FutureWarning, stacklevel=2)
323 if attr in __former_attrs__:
--> 324 raise AttributeError(__former_attrs__[attr])
326 if attr == 'testing':
327 import numpy.testing as testing
AttributeError: module 'numpy' has no attribute 'int'.
`np.int` was a deprecated alias for the builtin `int`. To avoid this error in existing code, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations