본문 바로가기

딥러닝 학습

5장 훈련 노하우 배우기 (1)

반응형

5-1 검증 세트를 나누고 전처리 과정 배우기

- 테스트 세트로 모델 튜닝

로지스틱 회귀로 모델 훈련하고 평가

1) cancer 데이터 세트를 읽어 들여 훈련 세트와 테스트 세트로 나눔

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
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)

 

2) SGDClassifier 클래스를 이용하여 로지스틱 회귀 모델 훈련

from sklearn.linear_model import SGDClassifier
sgd = SGDClassifier(loss = 'log', random_state=42)
sgd.fit(x_train_all, y_train_all)
sgd.score(x_test, y_test)


##출력: sgd.score(x_test, y_test)

※ 서포트 벡터 머신으로 모델 훈련하고 평가

from sklearn.linear_model import SGDClassifier
sgd = SGDClassifier(loss='hinge', random_state = 42)
sgd.fit(x_train_all, y_train_all)
sgd.score(x_test, y_test)


##출력: 0.9385964912280702

테스트 세트로 모델을 튜닝하면 '테스트 세트에 대해서만 좋은 성능을 보여주는 모델'이 되어 일반화 성능(generalization performance)이 왜곡된다.

 

- 검증 세트 준비

1. 데이터 세트 준비하기

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
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)

 

2. 검증 세트 분할하기

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)
print(len(x_train), len(x_val))

##출력: 364 91

 

3. 검증 세트 사용해 모델 평가하기

sgd = SGDClassifier(loss='log', random_state=42)
sgd.fit(x_train, y_train)
sgd.score(x_val, y_val)


##출력: 0.6923076923076923
반응형

- 스케일을 조정하지 않고 모델 훈련

1. 훈련 데이터 준비하고 스케일 비교

import matplotlib.pyplot as plt

print(cancer.feature_names[[2,3]])
plt.boxplot(x_train[:, 2:4])
plt.xlabel('feature')
plt.ylabel('value')
plt.show()

2. 가중치를 기록할 변수와 학습률 파라미터 추가

def __init__(self, learning_rate=0.1):
  self.w = None
  self.b = None
  self.losses = []
  self.w_history = []
  self.lr = learning_rate

 

3. 가중치 기록하고 업데이트 양 조절

import numpy as np

def fit(self, x, y, epochs=100, x_val=None, y_val=None):
        self.w = np.ones(x.shape[1])               # 가중치를 초기화합니다.
        self.b = 0                                 # 절편을 초기화합니다.
        self.w_history.append(self.w.copy())       # 가중치를 기록합니다.
        np.random.seed(42)                         # 랜덤 시드를 지정합니다.
        for i in range(epochs):                    # epochs만큼 반복합니다.
            loss = 0
            # 인덱스를 섞습니다
            indexes = np.random.permutation(np.arange(len(x)))
            for i in indexes:                      # 모든 샘플에 대해 반복합니다
                z = self.forpass(x[i])             # 정방향 계산
                a = self.activation(z)             # 활성화 함수 적용
                err = -(y[i] - a)                  # 오차 계산
                w_grad, b_grad = self.backprop(x[i], err) # 역방향 계산
                # 그래디언트에서 페널티 항의 미분 값을 더합니다
                w_grad += self.l1 * np.sign(self.w) + self.l2 * self.w
                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 += -(y[i]*np.log(a)+(1-y[i])*np.log(1-a))
            # 에포크마다 평균 손실을 저장합니다
            self.losses.append(loss/len(y) + self.reg_loss())

 

4. 모델 훈련하고 평가

layer1 = SingleLayer()
layer1.fit(x_train, y_train)
layer1.score(x_val, y_val)


##출력: 0.9120879120879121

 

5. 최종적으로 결정된 가중치 표시

w2 = []
w3 = []
for w in layer1.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()

 

- 스케일을 조정해 모델 훈련

1. 넘파이로 표준화 구현하기

train_mean = np.mean(x_train, axis=0)
train_std = np.std(x_train, axis=0)
x_train_scaled = (x_train - train_mean) / train_std

 

2. 모델 훈련하기

layer2 = SingleLayer()
layer2.fit(x_train_scaled, y_train)
w2 = []
w3 = []
for w in layer2.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()

3. 모델 성능 평가하기

layer2.score(x_val, y_val)


##출력: 0.37362637362637363

 

4. 표준화 전처리 적용

val_mean = np.mean(x_val, axis=0)
val_std = np.std(x_val, axis=0)
x_val_scaled = (x_val - val_mean) / val_std
layer2.score(x_val_scaled, y_val)


##출력: 0.967032967032967

 

- 스케일을 조정한 다음 실수하기 쉬운 함정

'훈련 세트와 검증 세트가 다른 비율로 스케일이 조정된 경우'

1. 원본 훈련 세트와 검증 세트로 산점도 그리기

plt.plot(x_train[:50, 0], x_train[:50, 1], 'bo')
plt.plot(x_val[:50, 0], x_val[:50, 1], 'ro')
plt.xlabel('feature 1')
plt.ylabel('feature 2')
plt.legend(['train set', 'val. set'])
plt.show()

2. 전처리한 훈련 세트와 검증 세트로 산점도 그리기

plt.plot(x_train_scaled[:50, 0], x_train_scaled[:50, 1], 'bo')
plt.plot(x_val_scaled[:50, 0], x_val_scaled[:50, 1], 'ro')
plt.xlabel('feature 1')
plt.ylabel('feature 2')
plt.legend(['train set', 'val. set'])
plt.show()

3. 올바르게 검증 세트 전처리하기

x_val_scaled = (x_val - train_mean) / train_std

plt.plot(x_train_scaled[:50, 0], x_train_scaled[:50, 1], 'bo')
plt.plot(x_val_scaled[:50, 0], x_val_scaled[:50, 1], 'ro')
plt.xlabel('feature 1')
plt.ylabel('feature 2')
plt.legend(['train set', 'val. set'])
plt.show()

4. 모델 평가하기

layer2.score(x_val_scaled, y_val)


##출력: 0.967032967032967

 

 

 

 

※ 해당 내용은 <Do it! 딥러닝 입문>의 내용을 토대로 학습하며 정리한 내용입니다.

반응형