[DEEP LEARNIG with Python] 05장. 머신 러닝의 기본 요소 - 1

ByungJik_Oh·2025년 5월 25일
post-thumbnail

📖 05장. 머신 러닝의 기본 요소

🗝️ 핵심내용

  • 머신 러닝의 근본 문제인 일반화와 최적화 사이의 긴장 관계 이해하기
  • 머신 러닝 모델의 평가 방법
  • 훈련 성능 향상을 위한 모범 사례
  • 일반화 성능 향상을 위한 모범 사례

📑 일반화: 머신 러닝의 목표

머신러닝의 근본적인 이슈는 최적화와 일반화의 줄다리기이다.

  • 최적화(optimization) : 가능한 훈련 데이터에서 최고의 성능을 얻으려고 모델을 조정하는 과정
  • 일반화(generalization) : 훈련된 모델이 이전에 본 적 없는 데이터에서 얼마나 잘 수행되는지를 의미

모델은 훈련 데이터에만 맞출 수 있기 때문에 너무 잘 맞으면 과대적합이 시작되고 일반화 성능은 나빠진다.

과소적합과 과대적합

훈련 초기에 최적화와 일반화는 상호 연관되어있다. 훈련 데이터의 손실이 낮아질수록 테스트 데이터의 손실도 낮아지는데 이를 모델이 과소적합(underfitting)되었다고 말한다.

하지만 훈련 데이터에서 훈련을 특정 횟수만큼 반복하고 난 후에는 일반화 성능이 더 이상 높아지지 않으며 검증 세트의 성능이 멈추고 감소되기 시작한다. 즉, 모델이 과대적합(overfitting)되기 시작한다.

이는 훈련 데이터에 특화된 패턴을 학습하기 시작했다는 의미이며, 과대적합은 데이터에 잡음, 불확실성, 드문 특성이 포함되어 있을 때 발생할 확률이 높다.

  • 잡읍 섞인 훈련 데이터 : 실제 데이터셋에는 잘못된 입력이 있는 경우가 흔한데, 모델을 이런 이상치에 맞추려고 하면 일반화 성능이 감소한다.
  • 불확실한 특성 : 문제에 불확실성과 모호성이 있다면 깔끔한 데이터라도 잡음이 있을 수 있다.
  • 드문 특성과 가짜 상관관계 : 전혀 관계가 없지만 매우 드물게 나타나는 특성이 데이터에 존재한다면 이 특성에 매우 높은 가중치를 부여해서 잘못된 판단을 할 수 있게한다.

MNIST 데이터셋을 이용하여 예를 들어보자.

# MNIST에서 백색 잡음 픽셀과 0픽셀 추가하기
from tensorflow.keras.datasets import mnist
import numpy as np

(train_images, train_labels), _ = mnist.load_data()
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
train_images_with_noise_channels = np.concatenate(
    [train_images, np.random.random((len(train_images), 784))],
    axis=1)
train_images_with_zeros_channels = np.concatenate(
    [train_images, np.zeros((len(train_images), 784))], axis=1)

기존 데이터의 784차원에 백색 잡음인 784개의 차원을 연결한 데이터와 모두 0인 784개의 차원을 연결하여 데이터의 절반이 잡음과 0인 데이터를 만든다. 이때 0과 같은 의미 없는 특성의 연결은 기존 정보에 전혀 영향을 미치지 않는다.

# 백색 잡음과 0을 추가한 MNIST 데이터에서 모델 훈련하기
from tensorflow import keras
from tensorflow.keras import layers

def get_model():
    model = keras.Sequential([
        layers.Dense(512, activation='relu'),
        layers.Dense(10, activation='softmax')
    ])
    model.compile(optimizer='rmsprop',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    return model

model = get_model()
history = model.fit(
    train_images, train_labels,
    epochs=10,
    batch_size=128,
    validation_split=0.2
)

model = get_model()
history_noise = model.fit(
    train_images_with_noise_channels, train_labels,
    epochs=10,
    batch_size=128,
    validation_split=0.2
)

model = get_model()
history_zeros = model.fit(
    train_images_with_zeros_channels, train_labels,
    epochs=10,
    batch_size=128,
    validation_split=0.2
)

이제 기존 데이터에 잡음을 추가하였으니 학습을 시키고, 정확도를 비교해보자.

# 검증 정확도 비교 그래프 그리기
import matplotlib.pyplot as plt

val_acc = history.history['accuracy']
val_acc_noise = history_noise.history['val_accuracy']
val_acc_zeros = history_zeros.history['val_accuracy']
epochs = range(1, 11)
plt.plot(epochs, val_acc, 'r',
         label='Validation accuracy')
plt.plot(epochs, val_acc_noise, 'g',
         label='Validation accuracy with noise channels')
plt.plot(epochs, val_acc_zeros, 'b',
         label='Validation accuracy with zeros channels')
plt.title('Effect of noise channels on validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

위 그래프에서 볼 수 있듯이 모두 동일한 정보를 가진 데이터지만 잡음 여부에 따라 정확도가 달라지는 것을 볼 수 있는데, 이는 가짜 상관관계의 영향으로 인한 과대적합이 발생하였기 때문이다.

이처럼 잡음은 반드시 과대적합을 발생시키므로 특성 선택(feature selection)을 통해 모델에 유익한 특성을 수행하는 것이 일반적이다.

이는 일반적으로 각 특성과 레이블 사이의 상호 의존 정보(mutual information)처럼 특성이 얼마나 유익한지 유용성 점수를 계산하여 일정 임계값을 넘긴 특성만 사용하게 된다.

딥러닝에서 일반화의 본질

매니폴드 가설(manifold hypothesis)은 실제 세상의 모든 데이터가 고차원 공간에 있는 저차원 매니폴드에 놓여있다고 가정한다.

  • 머신러닝 모델은 비교적 간단하고, 저차원이며, 매우 구조적인 부분 공간 (잠재 매니폴드(latent manifold)만 학습하면 된다.
  • 매니폴드 중 하나 안에서 두 입력 사이를 보간(interpolation)하는 것이 항상 가능하다.

샘플 사이를 보간하는 능력은 딥러닝에서 일반화를 이해하는 열쇠이다. 보간을 이용해서 빈 곳을 채울 수 있기 때문에 데이터를 보간할 수 있다면 이전에 본 적 없는 포인트를 해당 매니폴드에서 가까이 놓인 다른 포인트와 연결하여 이해할 수 있다.

하지만 보간이 일반화의 전부는 아닌데, 보간은 이전에 본 것과 매우 가까운 것을 이해(지역 일반화(local generalization))하는데 도움을 줄 수 있을 뿐이기 때문이다.

딥러닝이 작동하는 이유

딥러닝 모델은 근본적으로 매우 고차원의 매끄럽고 연속적인 곡선이다.

딥러닝은 본질적으로 크고 복잡한 곡선(매니폴드)을 선택하여 훈련 데이터 포인트에 맞을 때까지 파라미터를 점진적으로 조정(보간)하는 것이다.

이를 위해선 특성이 유익하고, 잡음이 적을 수록 잘 일반화할 수 있으므로 데이터 큐레이션(data curation)특성 공학(feature engineering)은 필수적이다.

또한, 곡선을 맞추는 것이기 때문에 이를 잘 수행하기 위해선 '조밀한 샘플링' 또한 매우 중요하다.

결론적으로 딥러닝 모델을 향상시키는 가장 좋은 방법은 더 좋고, 더 많은 데이터에서 훈련하는 것이다.


📑 머신 러닝 모델 평가

  • 훈련 세트 : 모델을 훈련할 때 사용하는 데이터 세트
  • 검증 세트 : 모델의 성능을 평가하여 설정(하이퍼 파라미터, hyperparameter) 튜닝을 수행하기 위한 데이터 세트
  • 테스트 세트 : 모델의 최종 성능을 평가하기 위한 데이터 세트

이때 검증 세트의 경우 모델의 최적의 하이퍼 파라미터를 찾기위해 사용되는데, 이러한 과정 또한 학습이라고 볼 수 있다. 따라서 계속해서 검증 세트에 맞춰 튜닝을 진행하면 검증 세트로 모델을 직접 학습시키지 않더라도 검증 세트에 과대적합될 수 있는데, 이를 정보 누설(information leak)라고 한다.

또한 완전히 새로운 데이터에 대한 모델의 성능을 평가할 때 테스트 세트를 사용하므로, 학습 과정에서 테스트 세트에 대한 어떤 정보도 얻어서는 안된다.

이렇게 데이터를 3가지 데이터 세트로 나누는 것은 간단해 보일 수도 있지만, 데이터가 적을 때는 몇가지 고급 기법을 사용하면 도움이 된다.

  • 단순 홀드아웃 검증 : 단순히 3가지 데이터 세트로 나누는 방법으로, 단순하지만 한가지 단점이 있다. 바로 데이터가 적을 때는 검증 세트와 테스트 데이터 세트의 샘플이 너무 적어 주어진 전체 데이터를 통계적으로 대표하지 못할 수도 있다는 점이다.
  • K-겹 교차 검증 : 데이터를 동일한 크기를 가진 K개의 분할로 나눈 뒤, 각 분할에 대해 평가하고 이렇게 얻은 K개의 점수의 평균으로 평가하는 방법이다. 이는 모델의 성능이 데이터 분할에 따라 편차가 클 때 도움이 된다.
  • 셔플링을 사용한 반복 K-겹 교차 검증 : K-겹 교차 검증을 여러번 적용하되, K개의 분할로 나누기 전 매번 데이터를 무작위로 섞는 방법이다.

상식 수준의 기준점 넘기

딥러닝 모델 훈련은 매니폴드 학습 과정을 관찰할 수 없고 유일한 피드백은 보이지 않는 검증 지표 뿐이다.

따라서 상식 수준의 기준점을 설정하는 것이 중요하다.

예를 들어, MNIST 숫자 분류 예제라면 랜덤한 분류기의 성능인 0.1보다 높은 검증 정확도, IMDB 예제에서는 마찬가지로 0.5보다 높은 검증 정확도가 될 수 있다. 또한, 로이터 예제에서는 클래스가 불균형하므로 0.18~0.19 근처가 될 수 있다. 마지막으로 90%의 샘플이 0, 10%의 샘플이 1인 이진 분류 문제라면 최소한 0.9보다 검증 정확도를 가지는 모델을 만드는 것이 목표가 될 수 있다.

모델 평가에 대해 유념해야 할 점

  1. 대표성 있는 데이터 : 훈련 세트와 테스트 세트가 주어진 데이터에 대한 대표성이 있어야 한다.

    만약 분할한 데이터 세트에서 훈련 데이터 세트엔 0~7의 숫자만, 테스트 데이터 세트엔 8~9의 숫자만 담겨 있다면 각각의 데이터 세트는 전체 데이터 세트에 대한 대표성이 사라지게 된다. 따라서 데이터 세트를 나누기 전에 무작위로 섞거나, 데이터 세트를 분할할 때 train_test_split() 함수가 가지고 있는 stratify 매개변수를 사용하여 이를 해소할 수 있다.

  2. 시간의 방향 : 과거로부터 미래를 예측하려고 한다면 데이터를 분할하기 전에 무작위로 섞어서는 안된다.

    무작위로 섞게되면 미래의 정보가 훈련 세트에 섞일 수 있으므로, 이때는 훈련 세트에 있는 데이터보다 테스트 세트에 있는 모든 데이터가 미래의 것이어야 한다.

  3. 데이터 중복 : 한 데이터 셋에 어떤 데이터 포인트가 중복된다면 데이터를 분할한 후 동일한 데이터 포인트가 훈련 세트와 테스트 세트 모두에 포함될 수 있다.

    이러한 경우 훈련 세트의 일부로 테스트를 하는 상황이 발생할 수 있으므로 미리 중복되는 데이터가 존재하는지 확인하는 작업이 필요하다.


🔗 출처

https://www.gilbut.co.kr/book/view?bookcode=BN003496


profile
精進 "정성을 기울여 노력하고 매진한다"

0개의 댓글