import numpy as np
# 시그모이드 함수 정의
def sigmoid(x):
return 1 / (1 + np.exp(-x))
x = np.random.randn(10, 2) # 10의 샘플 데이터, 데이터 한개에 입력이 2개 들억마
W1 = np.random.randn(2, 4)
b1 = np.random.randn(4)
W2 = np.random.randn(4, 3)
b2 = np.random.randn(3)
h = np.matmul(x, W1) + b1
a = sigmoid(h)
s = np.matmul(a, W2) + b2
여기서 의 형상은 (10,2)이다. 2차원 데이터 10개가 미니배치로 처리된다는 뜻이다. 그리고 최종 출력인 의 형상은 (10,3)이 된다.
즉, 각 데이터는 3차원 데이터로 변환 되었다는 뜻이다. (10개의 데이터)
x
array([[-0.39959216, -1.26027167],
[-0.13697825, -0.2312922 ],
[ 0.13345798, -1.28692136],
[ 0.62518337, 0.37462177],
[-1.84475205, 0.37937758],
[-0.32832423, -0.17646416],
[ 1.46191943, 0.51041203],
[ 0.04261429, -0.46560677],
[-1.94713215, 0.54752009],
[ 0.7493157 , -0.76367089]])
s
array([[ 0.72186119, -1.01256548, -1.10551936],
[ 0.47398161, -0.48646988, -0.65897571],
[ 0.52016285, -0.80258435, -1.11434382],
[ 0.21748565, -0.08393493, -0.51858371],
[ 0.99902309, -0.93415585, -0.43569061],
[ 0.53207949, -0.53726852, -0.63283426],
[ 0.05121435, 0.11233593, -0.59398933],
[ 0.44128334, -0.50703545, -0.75716494],
[ 1.00661807, -0.91473425, -0.37854799],
[ 0.24762023, -0.37328523, -0.90560412]])
이렇게 신경망은 3차원 데이터를 출력한다. 따라서 각 차원의 값을 이용하여 3개의 클래스 분류를 할 수 있다. 이 경우, 출력된 3차원 벡터의 각 차원은 각 클래스에 대응하는 점수(score)가 된다.
1번째 클래스일 확률 | 2번째 클래스일 확률 | 3번째 클래스일 확률 |
---|---|---|
-1.16618845 | 1.83387914 | 1.21169264 |
신경망의 계층(Layer)를 구현 해보자.
순전파(Forward Propagation): 입력층에서 출력층으로 향하는 전파
역전파(Backward Propagatoin): 데이터(기울기)를 순전파와 반대 방향으로 전달
여기서는 각 계층을 모두 클래스 형태로 구현 할 것입니다. 본 포스팅에서는 계층을 구현할 때 다음과 같은 구현 규칙을 따르겠습니다.
params: 가중치와 편향 같은 매개변수를 저장
grads: params에 저장된 각 매개변수에 대응하여, 해당 매개변수의 기울기를 보관
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.matmul(x, W) + b
return out
Affine 계층이 초기화 될때 무조건 가중치과 편향을 입력 받아 params 리스트에 저장한다. foward를 진행 할때 이 params에서 가중치와 편향을 가져와서 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)
# Layer Class 저장
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(input_size = 2, hidden_size = 4, output_size = 3)
s = model.predict(x)
s
array([[-2.74807127, -0.70833847, 0.13451208],
[-2.65646907, -0.69859353, 0.14993761],
[-2.5864815 , -0.88469718, 0.04788455],
[-1.52908705, -1.26782452, -0.00661778],
[-1.67642691, -1.04623033, 0.08542495],
[-1.91460404, -0.95817067, 0.09925629],
[-2.5885 , -0.37993438, 0.37490405],
[-2.2228201 , -0.93142298, 0.07506297],
[-2.91104053, -0.88898108, -0.00955292],
[-2.42675602, -0.90774917, 0.05919498]])
아까와 동일하게 클래스틀 통해 3개의 클래스의 값을 얻을 수 있다.