데이터에서 학습한다!
- 신경망의 특징은 데이터를 통해 가중치 매개변수의 값을 자동으로 결정한다는 점이다.
- 데이터 주도 학습
- 기계학습은 데이터가 생명이다. 데이터에서 답을 찾고 패턴을 찾는다.
- 보통 어떤 문제를 해결하려 할 때 사람은 이런저런 규칙성을 생각하고 프로그램을 만들려고 한다. 기계학습에서는 모아진 데이터로부터 규칙을 찾아내는 역할을 기계가 담당한다.
- 이미지에서 특징(Feature)을 추출하고 그 특징의 패턴을 기계학습 기술로 학습하는 방법이 있다. 여기서 말하는 특징은 입력 데이터(이미지)에서 본질적인 데이터(중요한 데이터)를 추출할 수 있도록 설계된 변환기를 가리킨다.
- 이미지의 특징은 보통 벡터로 기술하고, 컴퓨터 비전 분야에서는 SIFT, SURF, HOG등의 특징을 많이 사용한다.
- 이런 특징을 사용하여 이미지 데이터를 벡터로 변환하고 변환된 벡터를 가지고 지도 학습 방식의 대표 분류 기법인 SVM, KNN 등으로 학습할 수 있다.
- 규칙을 사람이 만드는 방식에서 기계가 데이터로부터 배우는 방식으로의 패러다임 변환
- 훈련 데이터와 시험 데이터
- 기계학습 문제는 데이터를 훈련 데이터와 시험 데이터로 나눠서 수행한다.
- 훈련 데이터를 활용하여 최적의 매개변수를 찾고 시험 데이터를 사용하여 앞서 훈련한 모델의 성능을 평가한다.
- 우리가 원하는 것은 범용적으로 사용할 수 있는 모델이기 때문에 범용 능력을 평가하기 위해서는 훈련 데이터와 시험 데이터를 분리하는 것이 필요하다.
- 범용 능력은 아직 보지 못한 데이터로도 문제를 올바르게 풀어내는 능력이다.
손실함수
- 손실 함수(Loss Function)은 신경망 성능의 ‘나쁨’을 나타내는 지표로, 현재의 신경망이 훈련 데이터를 얼마나 잘 처리하지 못하느냐를 나타난다.
- 평균 제곱 오차(Mean Squared Error)
- 가장 많이 쓰이는 손실함수는 평균 제곱 오차이다.
- n은 class 갯수, y_i는 신경망의 출력, t_i는 정답 레이블
- 1/2를 곱해줄 수도 있음
- 교차 엔트로피 오차(cross entropy error)
- t_k는 정답에 해당하는 인덱스의 원소만 1이고 나머지는 0이다(one-hot encoding)
- 따라서 실질적으로 정답일 때의 \(\log_e y_k\) 의 값을 자연로그를 계산하게 된다.
- 앞에 마이너스가 붙은 이유는 log 함수가 마이너스 값이기 때문에..
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t*np.log(y+delta))
t = [0, 0, 1]
y = [0.1, 0.5, 0.4]
cross_entropy_error(np.array(y), np.array(t)) # 0.9162
- 미니배치 학습
- 총 합을 배치 N으로 나눠준다
- 데이터가 너무 많은 경우, 일일이 손실함수를 구하는 것이 현실적이지 않을 수 있다.
- 이런 경우 일부 데이터를 추려 전체의 ‘근사치’로 이용할 수 있다. 이 일부를 미니배치(mini-batch)라고 한다.
- 왜 손실함수를 설정하는가?
- 우리는 정확도를 올리는 것이 목적인데 왜 손실 함수의 값이라는 우회적인 방법을 채택한 것일까?
- 신경망 학습에서는 최적의 매개변수를 탐색할 때 손실 함수의 값을 가능한 한 작게 하는 매개변수를 찾는다.
- 이때 매개변수의 미분을 계산하고, 그 미분 값을 단서로 매개변수의 값을 서서히 갱신하는 과정을 반복한다.
- 정확도를 지표로 하게 되면 대부분의 장소에서 0이 되기 때문에 미분이 불가능하다.
- 내 생각에 정확도를 미분 가능한 함수로 정의하는게 어렵다는 걸로 설명하는게 더 좋을 것 같은..?
- 따라서 미분이 가능한 손실 함수를 정의하고 미분을 통해 매개변수의 값을 조정한다.
- 또한 활성화 함수를 계단 함수로 할 경우, 계단 함수의 미분은 대부분의 장소에서 0이다.
- 정확도는 매개변수의 미소한 변화에는 거의 반응을 보이지 않고, 반응이 있더라도 그 값이 불연속적으로 갑자기 변화한다. 계단 함수를 활성화 함수로 사용하지 않는 이유
경사법(경사 하강법)
- 신경망의 최적의 매개변수는 손실 함수가 최솟값이 될 때의 매개변수 값이다
- 매개변수 공간이 광대하여 어디가 최솟값이 되는 지는 짐작할 수 없다.
- 이런 상황에서 기울기를 잘 이용해 함수의 최솟값을 찾으려는 것이 경사법이다.
- 주의할 점은 각 지점에서 함수의 값을 낮추는 방안을 제시하는 지표가 기울기이지만, 기울기가 가리키는 곳에 정말 함수의 최솟값이 있는지는 보장할 수 없다(안장점 또는 고원 등의 이유)
- 경사법은 현 위치에서 기울어진 방향으로 일정 거리만큼 이동한다.
- 그리고 그 위치에서 마찬가지로 기울기를 구하고 또 그 기울어진 방향으로 나아가기를 반복한다.
- 경사법을 수식으로 나타내면,
- \(\eta\)는 학습률(learning rate)로서, 한 번의 학습으로 얼마만큼 학습해야 할지, 즉 매개변수 값을 얼마나 갱신하느냐를 정하는 것이다.
학습 알고리즘 구현하기
- 미니배치: 훈련 데이터 중 일부를 무작위로 가져온다.
- 기울기 산출: 미니배치의 손실 함수 값을 줄이기 위해 각 가중치 매개변수의 기울기를 구한다. 기울기는 손실 함수의 값을 가장 작게 하는 방향을 제시한다.
- 매개변수 갱신: 가중치 매개변수를 기울기 방향으로 아주 조금 갱신한다
- 1~단계를 반복한다
- 데이터를 미니배치로 무작위로 선정하기 때문에 확률적 경사하강법(stochastic gradient descent, SGD)라고 부른다.
# coding: utf-8
%cd /content/drive/MyDrive/deep-learning-from-scratch/ch04
import sys, os
sys.path.append('/content/drive/MyDrive/deep-learning-from-scratch/') # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from two_layer_net import TwoLayerNet
# 데이터 읽기
(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, one_hot_label=True)
network = TwoLayerNet(input_size=784, hidden_size=50, output_size=10)
# 하이퍼파라미터
iters_num = 10000 # 반복 횟수를 적절히 설정한다.
train_size = x_train.shape[0]
batch_size = 100 # 미니배치 크기
learning_rate = 0.1
train_loss_list = []
train_acc_list = []
test_acc_list = []
# 1에폭당 반복 수
iter_per_epoch = max(train_size / batch_size, 1)
for i in range(iters_num):
# 미니배치 획득
batch_mask = np.random.choice(train_size, batch_size)
x_batch = x_train[batch_mask]
t_batch = t_train[batch_mask]
# 기울기 계산
#grad = network.numerical_gradient(x_batch, t_batch)
grad = network.gradient(x_batch, t_batch)
# 매개변수 갱신
for key in ('W1', 'b1', 'W2', 'b2'):
network.params[key] -= learning_rate * grad[key]
# 학습 경과 기록
loss = network.loss(x_batch, t_batch)
train_loss_list.append(loss)
# 1에폭당 정확도 계산
if i % iter_per_epoch == 0:
train_acc = network.accuracy(x_train, t_train)
test_acc = network.accuracy(x_test, t_test)
train_acc_list.append(train_acc)
test_acc_list.append(test_acc)
print("train acc, test acc | " + str(train_acc) + ", " + str(test_acc))
# 그래프 그리기
markers = {'train': 'o', 'test': 's'}
x = np.arange(len(train_acc_list))
plt.plot(x, train_acc_list, label='train acc')
plt.plot(x, test_acc_list, label='test acc', linestyle='--')
plt.xlabel("epochs")
plt.ylabel("accuracy")
plt.ylim(0, 1.0)
plt.legend(loc='lower right')
plt.show()
정리
- 기계학습에서 사용하는 데이터셋은 훈련 데이터와 시험 데이터로 나눠 사용한다.
- 훈련 데이터로 학습한 모델의 범용 능력을 시험 데이터로 평가한다.
- 신경만 학습은 손실 함수를 지표로, 손실 함수의 값이 작아지는 방향으로 가중치 매개변수를 갱신한다.
- 가중치 매개변수를 갱신할 때는 가중치 매개변수의 기울기를 이용하고, 기울어진 방향으로 가중치의 값을 갱신하는 작업을 반복한다.
- 아주 작은 값을 주었을 때의 차분으로 미분하는 것을 수치 미분이라고 한다.
- 수치 미분을 이용해 가중치 매개변수의 기울기를 구할 수 있다.