밑바닥부터 시작하는 딥러닝 1 | 신경망 학습
밑바닥부터 시작하는 딥러닝 1 Chapter 4 정리
책 정보 📖
- 책 제목: 밑바닥부터 시작하는 딥러닝 1
- 글쓴이: 사이토 고키
- 옮긴이: 개앞맵시
- 출판사: 한빛미디어
- 발행일: 2025년 01월 24일
- 챕터: Chapter 4. 신경망 학습
책소개
딥러닝 분야 부동의 베스트셀러! 머리로 이해하고 손으로 익히는 가장 쉬운 딥러닝 입문서 이 책은 딥러닝의 핵심 개념을 ‘밑바닥부터’ 구현해보며 기초를 한 걸음씩 탄탄하게 다질 수 있도록 도와주는 친절한 안내서입니다. 라이브러리나 프레임워크에 의존하지 않고 딥러닝의 기본 개념부터 이미지 인식에 활용되는 합성곱 신경망(CNN)까지 딥러닝의 원리를 체계적으로 설명합니다. 또한 복잡한 개념은 계산 그래프를 활용해 시각적으로 전달하여 누구나 쉽게 이해할 수 있습니다. 이 책은 딥러닝에 첫발을 내딛는 입문자는 물론이고 기초를 다시금 다지고 싶은 개발자와 연구자에게도 훌륭한 길잡이가 되어줄 것입니다.
주요 내용
신경망 학습: 데이터로부터 배우는 지능
지금까지 신경망의 구조와 순전파 과정을 살펴보았다. 하지만 가중치와 편향은 미리 주어진 값을 사용했다. 진정한 신경망의 힘은 학습에 있다. 훈련 데이터로부터 가중치 매개변수의 최적값을 자동으로 획득하는 것, 이것이 바로 신경망 학습의 핵심이다.
데이터에서 학습한다!
신경망 vs 퍼셉트론
신경망의 가장 큰 특징은 데이터를 보고 학습할 수 있다는 점이다. 퍼셉트론에서는 가중치 매개변수의 값을 사람이 수작업으로 설정해야 했지만, 신경망은 데이터를 보고 자동으로 결정한다.
퍼셉트론도 직선으로 분리할 수 있는 문제라면 데이터로부터 자동으로 학습이 가능하다. 선형 분리 가능 문제는 유한 번의 학습을 통해 풀 수 있다는 사실이 퍼셉트론 수렴 정리로 증명되었다. 하지만 비선형 문제는 불가능하다.
데이터 주도 학습의 혁명
머신러닝은 데이터가 생명이다. 데이터가 이끄는 접근 방식 덕분에 사람 중심 접근에서 벗어날 수 있었다.
전통적 접근 vs 머신러닝 접근:
- 사람: 경험과 직관을 단서로 시행착오를 거듭해 문제 해결
- 머신러닝: 사람의 개입을 최소화하고 수집한 데이터로부터 패턴을 찾으려 시도
신경망과 딥러닝은 사람의 개입을 더욱 배제할 수 있게 해주는 중요한 특성을 지녔다.
손글씨 ‘5’ 인식 문제로 보는 접근법 비교
1. 전통적 알고리즘 설계
- 사람이 밑바닥부터 규칙을 설계
- 복잡한 조건문과 예외 처리 필요
- 모든 경우를 예측하기 어려움
2. 머신러닝 접근
- 이미지에서 특징(SIFT, HOG 등) 추출
- 그 특징의 패턴을 머신러닝 기술(SVM, KNN 등)로 학습
- 특징: 입력 데이터에서 본질적인 데이터를 정확하게 추출할 수 있도록 설계된 변환기
3. 딥러닝 접근
- 신경망이 이미지에 포함된 중요한 특징까지도 스스로 학습
- 종단간 머신러닝(End-to-End Learning): 처음부터 끝까지 사람의 개입 없이 입력에서 출력까지 기계가 담당
신경망의 이점
- 범용성: 모든 문제를 같은 맥락에서 해결 가능
- 자율성: 주어진 데이터를 온전히 학습하고 패턴 발견을 시도
- 통합성: 모든 문제를 주어진 데이터 그대로를 입력 데이터로 활용해 ‘End-to-End’로 학습
훈련 데이터와 시험 데이터
머신러닝에서는 데이터를 훈련 데이터와 시험 데이터로 나누어 학습과 평가를 수행하는 것이 일반적이다.
데이터 분할의 목적
- 훈련 데이터: 최적의 매개변수를 찾기 위해 사용
- 시험 데이터: 훈련한 모델의 성능을 평가하기 위해 사용
왜 나누어야 할까?
범용 능력 때문이다. 범용 능력이란 아직 보지 못한 데이터(훈련 데이터에 포함되지 않는 데이터)로도 문제를 올바르게 풀어내는 능력을 말한다.
데이터 분할이 필요한 이유:
- 하나의 데이터셋으로만 학습과 평가를 수행하면 올바른 평가가 불가능
- 다른 데이터셋에서는 성능이 현저히 떨어질 수 있음
- 한 데이터셋에만 최적화된 상태를 과대적합(Overfitting)이라 함
과대적합을 피하는 것은 머신러닝의 중요한 과제 중 하나다.
손실 함수: 학습의 나침반
신경망 학습에서는 현재 상태를 ‘하나의 지표’로 표현한다. 이 지표를 가장 좋게 만들어주는 가중치 매개변수의 값을 탐색하는 것이 학습의 목표다.
손실 함수란?
손실 함수(Loss Function)는 신경망이 학습할 수 있도록 해주는 지표다. 일반적으로 얼마나 나쁜지를 나타내는 지표로, 손실 함수의 결괏값을 가장 작게 만드는 가중치 매개변수를 찾는 것이 학습의 목표다.
오차제곱합(Sum of Squares Error)
\[E = \frac{1}{2} \sum_{k} (y_k - t_k)^2\]- $y_k$: 신경망의 출력(신경망이 추정한 값)
- $t_k$: 정답 레이블
- $k$: 데이터의 차원 수
1
2
3
4
5
6
7
8
9
10
11
12
13
def sum_squares_error(y, t):
return 0.5 * np.sum((y - t)**2)
# 예시: 정답이 '2'인 경우
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0] # 원-핫 인코딩
# 올바른 예측
y1 = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
print(sum_squares_error(np.array(y1), np.array(t))) # 0.0975... (작은 오차)
# 틀린 예측
y2 = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
print(sum_squares_error(np.array(y2), np.array(t))) # 0.597... (큰 오차)
교차 엔트로피 오차(Cross Entropy Error)
\[E = -\sum_k(t_k \log y_k)\]교차 엔트로피 오차는 정답일 때의 출력이 전체 값을 정하게 된다. 정답이 아닌 나머지 모든 $t_k$가 0이므로 곱해도 0이 되어 결과에 영향이 없다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
def cross_entropy_error(y, t):
delta = 1e-7 # -INF를 방지하기 위한 작은 값
return -np.sum(t * np.log(y + delta))
# 예시: 정답이 '2'인 경우
t = [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]
# 올바른 예측
y1 = [0.1, 0.05, 0.6, 0.0, 0.05, 0.1, 0.0, 0.1, 0.0, 0.0]
print(cross_entropy_error(np.array(y1), np.array(t))) # 0.5108...
# 틀린 예측
y2 = [0.1, 0.05, 0.1, 0.0, 0.05, 0.1, 0.0, 0.6, 0.0, 0.0]
print(cross_entropy_error(np.array(y2), np.array(t))) # 2.3025...
미니배치 학습: 효율적인 학습 전략
전체 데이터에 대한 손실 함수
모든 훈련 데이터를 대상으로 손실 함수의 값을 구하려면 다음과 같이 계산한다:
\[E = -\frac{1}{N}\sum_n \sum_k(t_{nk} \log y_{nk})\]$\frac{1}{N}$은 정규화를 의미한다. N으로 나누어 ‘평균 손실 함수’를 구하면 데이터 개수와 관계없이 통일된 지표를 얻을 수 있다.
미니배치의 필요성
하지만 많은 데이터를 대상으로 일일이 손실 함수를 계산하는 것은 현실적이지 않다. 따라서 데이터 일부를 추려 전체의 ‘근사치’로 이용한다.
미니배치(Mini-batch): 훈련 데이터에서 일부만 골라 학습하는 방법
1
2
3
# 60,000개 중에서 무작위로 10개 선택
batch_indices = np.random.choice(60000, 10)
print(batch_indices) # [47867, 49395, 26794, 33627, 1169, 522, 942, 12, 22428, 4283]
배치용 교차 엔트로피 오차 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
def cross_entropy_error(y, t):
if y.ndim == 1: # 1차원이라면
t = t.reshape(1, t.size) # 데이터 형상을 (1, t.size)로 변경
y = y.reshape(1, y.size)
batch_size = y.shape[0]
# 원-핫 인코딩인 경우
# return -np.sum(t * np.log(y + 1e-7)) / batch_size
# 레이블 형태인 경우 (더 효율적)
return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size
# y[np.arange(batch_size), t]는 y[0,t[0]], y[1,t[1]], y[2,t[2]]...를 의미
왜 손실 함수를 사용할까?
‘정확도’라는 직관적인 지표를 놔두고 ‘손실 함수’라는 우회적인 방법을 선택하는 이유는 무엇일까?
미분의 역할
답은 미분 때문이다. 신경망 학습에서는 매개변수 값을 탐색할 때 매개변수의 미분(기울기)을 계산하고, 그 미분 값을 단서로 매개변수의 값을 서서히 갱신하는 과정을 반복한다.
미분의 의미: 가중치 매개변수의 값을 아주 조금 변화시켰을 때 손실 함수가 어떻게 변하는지를 나타낸다.
정확도 vs 손실 함수
정확도를 지표로 사용할 때의 문제:
- 미분 값이 대부분의 장소에서 0이 된다
- 매개변수가 변화하지 않아 학습이 진행되지 않는다
- 매개변수는 불연속적인 값으로 변하거나 일정하게 유지된다
손실 함수를 지표로 사용할 때의 장점:
- 연속적인 변화를 보인다
- 미분 값이 유의미하여 매개변수 갱신이 가능하다
- 활성화 함수로 계단 함수 대신 시그모이드 함수를 사용하는 이유와 동일하다
마무리
신경망 학습의 핵심은 데이터로부터 최적의 매개변수를 자동으로 찾는 것이다. 이를 위해 적절한 손실 함수를 설정하고, 미니배치를 통해 효율적으로 학습을 진행한다.
핵심 포인트:
- 데이터 주도 학습: 사람의 개입을 최소화하고 데이터가 이끄는 학습
- 손실 함수: 학습 진행을 위한 연속적인 지표
- 미니배치: 대용량 데이터를 효율적으로 처리하는 방법
- 과대적합 방지: 훈련/시험 데이터 분할의 중요성