class Neuron(object):
"""
간단한 전방 전달 인공 뉴런.
Args:
num_inputs (int): 입력 값의 크기
activation_function (callable): 활성화 함수
Attributes:
W (ndarray): 각 입력에 대한 가중치
b (float): 편향값, 가중합에 더해짐.
activation_function (callable): 활성화 함수.
"""
def __init__(self, num_inputs, activation_function):
super().__init__()
# 랜덤값으로 가중치 벡터와 편향값을 초기화(1과 -1 사이)
self.W = np.random.uniform(size=num_inputs, low=-1., high=1.)
self.b = np.random.uniform(size=1, low=-1., high=1.)
self.activation_function = activation_function
def forward(self, x):
# 뉴런을 통해 입력 신호를 전달(입력 -> 가중합 -> 활성화 함수 -> 출력)
z = np.dot(x, self.W) + self.b
return self.activation_function(z)
[[0.37454012 0.95071431 0.73199394]]
[0.73235229 0.20223002 0.41614516]
[-0.95883101]
# 하나의 계층을 정의
class FullyConnectedLayer(object):
"""A simple fully-connected NN layer.
Args:
num_inputs (int): 입력 백터의 크기
layer_size (int): 출력 벡터의 크기
activation_function (callable): 활성화 함수
Attributes:
W (ndarray): 입력값에 대한 가중치
b (ndarray): 가중합에 더해질 편향값
size (int): 은닉층의 개수
activation_function (callable): 활성화 함수
"""
def __init__(self, num_inputs, layer_size, activation_function, derivated_activation_function=None):
super().__init__()
# 임의로 가중치와 편향을 초기화 (여기서는 정규 분포 사용)
self.W = np.random.standard_normal((num_inputs, layer_size))
self.b = np.random.standard_normal(layer_size)
self.size = layer_size
self.activation_function = activation_function
def forward(self, x):
"""계층을 통해 입력 신호를 전달"""
z = np.dot(x, self.W) + self.b
return self.activation_function(z)
np.random.seed(42)
x1 = np.random.uniform(-1, 1, 2).reshape(1, 2) # [[값1 값2 값3]]
x2 = np.random.uniform(-1, 1, 2).reshape(1, 2) # [[값1 값2 값3]]
relu_fn = lambda y: np.maximum(y, 0) # 활성화 함수 정의: ReLU
layer = FullyConnectedLayer(2, 3, relu_fn)
print(layer.W)
print(layer.b)
[[-0.23415337 -0.23413696 1.57921282]
[ 0.76743473 -0.46947439 0.54256004]]
[-0.46341769 -0.46572975 0.24196227]
[[0.28712364 0. 0.33478571]] [[0. 0. 1.08175419]]
[[0.28712364 0. 0.33478571]
[0. 0. 1.08175419]]
import numpy as np
from fully_connected_layer import FullyConnectedLayer # 완전연결계층(입력크기, 은닉층 개수)
def sigmoid(x): # x의 요소에 시그모이드 함수를 적용
return 1 / (1 + np.exp(-x)) # y
class SimpleNetwork(object):
"""간단한 완전 연결 신경망
Args:
num_inputs (int): 입력 벡터 크기 / 입력값 개수
num_outputs (int): 출력 벡터 크기
hidden_layers_sizes (list): 네트워크에 추가될 은닉 계층의 크기를 포함한 리스트
Attributes:
layers (list): 네트워크를 구성하는 계층 리스트
"""
def __init__(self, num_inputs, num_outputs, hidden_layers_sizes=(64, 32)):
super().__init__()
# 네트워크를 구성하는 계층 리스트를 구성
# 입력층, 은닉층([64, 32]), 출력층
layer_sizes = [num_inputs, *hidden_layers_sizes, num_outputs]
self.layers = [
FullyConnectedLayer(layer_sizes[i], layer_sizes[i + 1], sigmoid) # 각 계층을 완전연결계층으로 연결(입력, 출력, 활성화)
for i in range(len(layer_sizes) - 1)]
def forward(self, x):
"""입력벡터 'x'를 계층을 통해 전달"""
for layer in self.layers: # from the input layer to the output one
x = layer.forward(x)
return x
def predict(self, x):
"""'x'에 대응하는 출력을 계산하고 출력값이 가장 큰 인덱스를 반환"""
estimations = self.forward(x)
best_class = np.argmax(estimations)
return best_class
def evaluate_accuracy(self, X_val, y_val):
"""검증 데이터셋을 사용해 네트워크의 정확도를 평가"""
num_corrects = 0
for i in range(len(X_val)):
pred_class = self.predict(X_val[i])
if pred_class == y_val[i]:
num_corrects += 1
return num_corrects / len(X_val)
# MNIST images 분류를 위한 네트워크, 그 안에 크기가 64, 32 인 2개의 은닉 계층이 있음
mnist_classifier = SimpleNetwork(X_train.shape[1], num_classes, [64,32]) # 신경망(입력크기, 출력크기, 은닉층)
# 네트워크 정확도 평가
accuracy = mnist_classifier.evaluate_accuracy(X_test, y_test)
print("accuracy = {:.2f}%".format(accuracy * 100))
# out: accuracy = 12.06%
Leave a comment