59doit
신경망 알고리즘 본문
반응형
신경망 알고리즘 벡터화하기
# 필요한 모듈 및 임포트
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split |
# breast cancer 데이터 활용
cancer = load_breast_cancer() x = cancer.data y = cancer.target x_train_all, x_test, y_train_all, y_test = train_test_split(x, y, stratify=y, test_size=0.2, random_state=42) x_train, x_val, y_train, y_val = train_test_split(x_train_all, y_train_all, stratify=y_train_all, test_size=0.2, random_state=42) |
# SingleLayer 신경망
class SingleLayer: def __init__(self, learning_rate=0.1, l1=0, l2=0): self.w = None # 가중치 self.b = None # 절편 self.losses = [] # 훈련 손실 self.val_losses = [] # 검증 손실 self.w_history = [] # 가중치 기록 self.lr = learning_rate # 학습률 self.l1 = l1 # L1 손실 하이퍼파라미터 self.l2 = l2 # L2 손실 하이퍼파라미터 def forpass(self, x): z = np.dot(x, self.w) + self.b # 선형 출력을 계산합니다. return z def backprop(self, x, err): m = len(x) w_grad = np.dot(x.T, err) / m # 가중치에 대한 그래디언트를 계산합니다. b_grad = np.sum(err) / m # 절편에 대한 그래디언트를 계산합니다. return w_grad, b_grad def activation(self, z): z = np.clip(z, -100, None) # 안전한 np.exp() 계산을 위해 a = 1 / (1 + np.exp(-z)) # 시그모이드 계산 return a def fit(self, x, y, epochs=100, x_val=None, y_val=None): y = y.reshape(-1, 1) # 타깃을 열 벡터로 바꿉니다. y_val = y_val.reshape(-1, 1) m = len(x) # 샘플 개수를 저장합니다. self.w = np.ones((x.shape[1], 1)) # 가중치를 초기화합니다. self.b = 0 # 절편을 초기화합니다. self.w_history.append(self.w.copy()) # 가중치를 기록합니다. # epochs만큼 반복합니다. for i in range(epochs): z = self.forpass(x) # 정방향 계산을 수행합니다. a = self.activation(z) # 활성화 함수를 적용합니다. err = -(y - a) # 오차를 계산합니다. # 오차를 역전파하여 그래디언트를 계산합니다. w_grad, b_grad = self.backprop(x, err) # 그래디언트에 페널티 항의 미분 값을 더합니다. w_grad += (self.l1 * np.sign(self.w) + self.l2 * self.w) / m # 가중치와 절편을 업데이트합니다. self.w -= self.lr * w_grad self.b -= self.lr * b_grad # 가중치를 기록합니다. self.w_history.append(self.w.copy()) # 안전한 로그 계산을 위해 클리핑합니다. a = np.clip(a, 1e-10, 1 - 1e-10) # 로그 손실과 규제 손실을 더하여 리스트에 추가합니다. loss = np.sum(-(y * np.log(a) + (1 - y) * np.log(1 - a))) self.losses.append((loss + self.reg_loss()) / m) # 검증 세트에 대한 손실을 계산합니다. self.update_val_loss(x_val, y_val) def predict(self, x): z = self.forpass(x) # 정방향 계산을 수행합니다. return z > 0 # 스텝 함수를 적용합니다. def score(self, x, y): # 예측과 타깃 열 벡터를 비교하여 True의 비율을 반환합니다. return np.mean(self.predict(x) == y.reshape(-1, 1)) def reg_loss(self): # 가중치에 규제를 적용합니다. return self.l1 * np.sum(np.abs(self.w)) + self.l2 / 2 * np.sum(self.w ** 2) def update_val_loss(self, x_val, y_val): z = self.forpass(x_val) # 정방향 계산을 수행합니다. a = self.activation(z) # 활성화 함수를 적용합니다. a = np.clip(a, 1e-10, 1 - 1e-10) # 출력 값을 클리핑합니다. # 로그 손실과 규제 손실을 더하여 리스트에 추가합니다. val_loss = np.sum(-(y_val * np.log(a) + (1 - y_val) * np.log(1 - a))) self.val_losses.append((val_loss + self.reg_loss()) / len(y_val)) |
# scaler
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaler.fit(x_train) x_train_scaled = scaler.transform(x_train) x_val_scaled = scaler.transform(x_val) |
# 학습하기
single_layer = SingleLayer(l2=0.01) single_layer.fit(x_train_scaled, y_train, x_val=x_val_scaled, y_val=y_val, epochs=10000) single_layer.score(x_val_scaled, y_val) |
# 0.978021978021978 |
# 시각화
# 시각화
# 시각화
w2 = [] w3 = [] for w in single_layer.w_history: w2.append(w[2]) w3.append(w[3]) plt.plot(w2, w3) plt.plot(w2[-1], w3[-1], 'ro') plt.xlabel('w[2]') plt.ylabel('w[3]') plt.show() |
반응형
Comments