실습 · 연습문제 2개
Kahan 보정 합 kahan-sum
float32 배열의 원소를 앞에서부터 하나씩 더하면, 합이 커질수록 작은 원소의 아래쪽 자릿수가 반올림으로 사라진다. Kahan 보정 합(compensated summation)은 덧셈마다 잃은 부분을 보정 변수 에 모아 다음 덧셈에서 되돌려 준다.
는 이번 덧셈에서 실제로 더해진 양이고, 여기서 를 빼면 반올림으로 잃은 부분(의 음수)이 남는다.
함수 kahan_sum(a)를 완성한다.
a는 1차원 float32 배열이다. 모든 중간 계산을 float32로 한다(np.float32(0)에서 시작하고 원소를 float64로 바꾸지 않는다).- 반환값은 float32 스칼라다.
np.sum,math.fsum을 쓰지 않는다.
테스트는 float64로 계산한 합과 비교해, 순서대로 더한 합보다 오차가 크게 작은지 확인한다.
주의: 보정 식 c = (t - s) - y를 대수적으로 정리하면 0이 된다. 수학적으로 같은 식이 부동소수점에서는 다르다는 것이 이 알고리즘의 핵심이다.
안정한 log-softmax stable-log-softmax
분류 모델의 cross-entropy는 logits 의 log-softmax
를 쓴다. 정의대로 np.log(np.exp(z) / np.exp(z).sum())을 계산하면 logits가 크면 exp가 overflow해 nan이, 작으면 underflow해 -inf가 나온다.
함수 log_softmax(z, axis=-1)를 완성한다.
z는 임의 shape의 배열이고,axis방향으로 log-softmax를 계산한다. 반환 shape은z와 같다.z = [1000, 1001, 1002]나z = [-1000, 0]처럼 큰 값·작은 값이 섞여도nan이나inf없이 정확한 값을 내야 한다.scipy.special.logsumexp를 쓰지 않고numpy만으로 구현한다.
힌트: 모든 에서 같은 상수 을 빼도 log-softmax는 변하지 않는다. 로 고르면 지수의 인자가 모두 0 이하가 된다. 축을 유지하려면 keepdims=True를 쓴다.