밑바닥부터 시작하는 딥러닝 교재에서 미니배치로 학습할 시의 교차 엔트로피 오차 함수를 구현하면서, 이해되지 않았던 부분을 정리했다.
현재 데이터셋의 shape 은 train_x : (60000, 748) , train_y : (60000, 10) 이다.
미니배치 10의 사이즈로 학습하므로 한번 학습할 때의 학습, 평가 셋의 크기는 minibatch_train_x : (10, 784),
minibatch_train_y : (10, 10) 에 해당한다.
첫번째, 예측값과 레이블이 원 핫 인코딩으로 주어지는 경우
위와 같이 예측값 p 와 레이블 y 가 원 핫 인코딩의 shape으로 미니배치로 주어질 때 다음과 같이 구현할 수 있다.
# y, p 의 형태가 원 핫 인코딩인 경우
def cross_entropy(y, p) :
# 데이터가 1개만 존재하는 경우에도 계산가능하도록 reshape
if p.ndim == 1 :
p = p.reshape(1, p.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return - np.sum(y * np.log(p + le-7)) / batch_size
ndim == 1 인 경우를 체크하는 이유는 데이터가 1개만 존재하는 경우에도 데이터가 여러개 있을 때와 똑같이 계산할 수 있도록 reshape 해주는 과정이다.
예를 들어서, n번째 데이터 하나에 대한 예측 결과값 pn 이 [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ] 라고 한다면 reshape 을 통해
[[ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ]] 의 형태로 수정할 수 있다. 이는 예측해야할 데이터가 여러개 존재할 때의 넘파이 배열 형식, [[0번째 데이터의 원핫], [1번째 데이터의 원핫], .... ]과 같다.
두번째, 정답은 정수형태로 출력은 원 핫 인코딩으로 주어졌을 때
처음에 책 예제를 실행하려 할 때 자꾸 넘파이 배열 크기가 맞지 않아 어디서 에러가 나는지 오랫동안 찾았다. 정답과 출력의 형태가 모두 정수로 주어진다고 착각했던 것이 에러의 이유였다. 이 경우는 레이블은 [ 1, 3, 4, 5... ] 와 같은 정수 형태, 모델의 예측 값은 위 첫번째 방법과 같은 원 핫 인코딩으로 주어졌을 때 구현하는 방법이다.
# p 는 원 핫, y가 하나의 숫자로만 주어진 경우
def cross_entropy(y, p) :
if p.ndim == 1 :
p = p.reshape(1, p.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return - np.sum(np.log(p[np.arange(batch_size), y] + 1e-7)) / batch_size
앞서 했던 착각때문에 마지막 줄의 p[np.arange(batch_size), y] 가 제대로 실행되지 않았고, 이해하는데 시간이 오래 걸렸다.
이 식을 이해하기 위해 간단한 예시 데이터를 생성했다.
# y 정답 레이블, p 예측값
y = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
p = np.array([1, 0, 2])
예시 데이터를 3개만 생성했으므로 배치 사이즈는 y.shape[0] 인 3 이 될 것이다.
( 미니배치 개념을 적용한다면 무수히 많은 데이터 중, 3개의 데이터만 떼온 것이다. )
batch_size = y.shape[0]
이제 다음 식을 이해할 수 있었다.
y[np.arange(batch_size), p]
# 결과값 array([2, 4, 9])
# 참조
밑바닥부터 시작하는 딥러닝
'인공지능 > 이론 정리' 카테고리의 다른 글
신경망 학습 : 손실함수, 활성화함수, 파라미터 (0) | 2022.01.13 |
---|---|
편미분 그라디언트 함수 구현 - 기울기, 경사법 (0) | 2022.01.11 |
신경망 학습 (0) | 2022.01.09 |
밑바닥부터 시작하는 딥러닝 : MNIST 데이터 Google Colab 에서 로드하기 (0) | 2022.01.09 |
softmax 함수와 데이터 처리 및 학습 (0) | 2022.01.06 |