728x90
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
# 아이리스 데이터셋 로드
iris_data = datasets.load_iris()
input_data = iris_data.data
correct = iris_data.target
n_data = len(correct)
# 입력 데이터 정규화
ave_input = np.average(input_data, axis=0)
std_input = np.std(input_data, axis=0)
input_data = (input_data - ave_input) / std_input
# 정답 데이터를 원-핫 인코딩으로 변환
correct_data = np.zeros((n_data, 3))
for i in range(n_data):
correct_data[i, correct[i]] = 1.0
# 학습용, 테스트용 데이터 분할
index = np.arange(n_data)
index_train = index[index % 2 == 0]
index_test = index[index % 2 != 0]
input_train = input_data[index_train, :]
correct_train = correct_data[index_train, :]
input_test = input_data[index_test, :]
correct_test = correct_data[index_test, :]
n_train = input_train.shape[0]
n_test = input_test.shape[0]
# 네트워크 매개변수 설정
n_in = 4
n_mid = 25
n_out = 3
wb_width = 0.1
eta = 0.01 # 초기 학습률
epoch = 1000
interval = 100
dropout_ratio = 0.5 # 드롭아웃 비율
# 기본 레이어 클래스 정의 (아다그라드 적용)
class BaseLayer:
def __init__(self, n_upper, n):
self.w = wb_width * np.random.randn(n_upper, n)
self.b = wb_width * np.random.randn(n)
self.h_w = np.zeros((n_upper, n)) + 1e-8
self.h_b = np.zeros(n) + 1e-8
def update(self, eta):
self.h_w += self.grad_w * self.grad_w
self.w -= eta / np.sqrt(self.h_w) * self.grad_w
self.h_b += self.grad_b * self.grad_b
self.b -= eta / np.sqrt(self.h_b) * self.grad_b
# 중간 레이어 클래스 정의 (아다그라드 및 드롭아웃 적용)
class MiddleLayer(BaseLayer):
def __init__(self, n_upper, n, dropout_ratio):
super().__init__(n_upper, n)
self.dropout_ratio = dropout_ratio
self.dropout_mask = None
def forward(self, x, train_flg=True):
self.x = x
self.u = np.dot(x, self.w) + self.b
self.y = np.where(self.u <= 0, 0, self.u) # ReLU 활성화 함수
# 드롭아웃 적용 (훈련 시에만)
if train_flg:
self.dropout_mask = np.random.rand(*self.y.shape) > self.dropout_ratio
self.y *= self.dropout_mask
else:
self.y *= 1.0 - self.dropout_ratio # 테스트 시 드롭아웃 비율에 따라 스케일링
def backward(self, grad_y):
# 드롭아웃 적용 (드롭아웃된 뉴런은 역전파하지 않음)
if self.dropout_mask is not None:
grad_y *= self.dropout_mask
delta = grad_y * np.where(self.u <= 0, 0, 1) # ReLU 미분
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)
# 출력 레이어 클래스 정의 (아다그라드 적용)
class OutputLayer(BaseLayer):
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)
# 레이어 생성 (드롭아웃 비율 추가)
middle_layer_1 = MiddleLayer(n_in, n_mid, dropout_ratio)
middle_layer_2 = MiddleLayer(n_mid, n_mid, dropout_ratio)
output_layer = OutputLayer(n_mid, n_out)
# 순전파 함수 정의
def forward_propagation(x, train_flg=True):
middle_layer_1.forward(x, train_flg)
middle_layer_2.forward(middle_layer_1.y, train_flg)
output_layer.forward(middle_layer_2.y)
# 역전파 함수 정의
def backpropagation(t):
output_layer.backward(t)
middle_layer_2.backward(output_layer.grad_x)
middle_layer_1.backward(middle_layer_2.grad_x)
# 오류 계산 함수 (교차 엔트로피)
def get_error(t, batch_size):
return -np.sum(t * np.log(output_layer.y + 1e-7)) / batch_size
# 학습 루프
train_error_x = []
train_error_y = []
test_error_x = []
test_error_y = []
for i in range(epoch):
# 학습 오류 계산
forward_propagation(input_train, train_flg=True)
error_train = get_error(correct_train, n_train)
# 테스트 오류 계산
forward_propagation(input_test, train_flg=False)
error_test = get_error(correct_test, n_test)
train_error_x.append(i)
train_error_y.append(error_train)
test_error_x.append(i)
test_error_y.append(error_test)
if i % interval == 0:
print("에포크:", str(i) + "/" + str(epoch),
"훈련 오류:", str(error_train),
"테스트 오류:", str(error_test))
# 학습 데이터 섞기
index_random = np.arange(n_train)
np.random.shuffle(index_random)
# 미니배치 아다그라드 적용
for j in range(n_train):
x = input_train[index_random[j], :].reshape(1, -1)
t = correct_train[index_random[j], :].reshape(1, -1)
forward_propagation(x, train_flg=True) # 드롭아웃 적용
backpropagation(t)
middle_layer_1.update(eta)
middle_layer_2.update(eta)
output_layer.update(eta)
# 오류 그래프 그리기
plt.plot(train_error_x, train_error_y, label="Train")
plt.plot(test_error_x, test_error_y, label="Test")
plt.legend()
plt.xlabel("에포크")
plt.ylabel("오류")
plt.show()
# 정확도 계산
forward_propagation(input_train, train_flg=False)
count_train = np.sum(np.argmax(output_layer.y, axis=1) == np.argmax(correct_train, axis=1))
forward_propagation(input_test, train_flg=False)
count_test = np.sum(np.argmax(output_layer.y, axis=1) == np.argmax(correct_test, axis=1))
print("훈련 정확도:", str(count_train / n_train * 100) + "%",
"테스트 정확도:", str(count_test / n_test * 100) + "%")

728x90
'AI(Artificial Intelligence)' 카테고리의 다른 글
| python embedding + vector store for LLM (0) | 2024.09.01 |
|---|---|
| python character recognition (2) | 2024.08.28 |
| classification - GSD + dropout ( 분류 - 확률적 경사하강법 + 드랍아웃 ) (0) | 2024.08.21 |
| classification - adagrad ( 분류 - 아다그라드 ) (0) | 2024.08.21 |
| classification - Stochastic Gradient Descent (분류 - 확률적경사하강법) (0) | 2024.08.21 |