728x90
반응형
Softmax와 Log-Softmax 함수 설명 및 구현 분석
딥러닝에서 분류(Classification) 문제를 해결할 때 자주 사용되는 Softmax 함수와 Log-Softmax 함수를 구현하고, 이를 분석해보겠습니다.
1. Softmax 함수란?
개념
Softmax 함수는 주어진 입력 벡터(점수, logits)를 확률 분포로 변환하는 함수입니다.
출력 벡터의 각 요소는 0과 1 사이의 값을 가지며, 모든 요소의 합이 1이 됩니다.
이를 통해 입력값을 확률적인 해석이 가능하도록 변환할 수 있습니다.
수식으로 표현하면 다음과 같습니다.
$$S_i= \frac{e^{x_i}}{\sum_{j} e^{x_j}}$$
여기서:
- $x_i$는 입력 점수 (logit)
- $S_i$는 Softmax로 변환된 확률 값
- 분자는 해당 점수의 지수 함수 적용 값
- 분모는 모든 점수의 지수 값의 총합
Python 구현
import numpy as np
import math
def softmax(scores: list) -> np.ndarray:
answer = np.zeros(len(scores)) # 결과 저장 배열
total = sum([math.exp(score) for score in scores]) # 지수 함수 값들의 합
for i in range(len(scores)):
answer[i] = math.exp(scores[i]) / total # Softmax 계산
return np.array(answer)
# 테스트
print(softmax([1, 2, 3]))
print(sum(softmax([1, 2, 3]))) # 확률 분포이므로 합은 1
설명
- math.exp(score)를 사용하여 각 점수에 대해 지수 함수를 적용합니다.
- total 변수에 모든 점수의 지수 값을 더한 값을 저장합니다.
- 최종적으로 각 요소를 지수 값의 총합으로 나누어 확률 분포로 변환합니다.
- Softmax 함수의 결과는 확률 분포이므로 모든 값의 합이 1이 됩니다.
2. Log-Softmax 함수란?
개념
Log-Softmax 함수는 Softmax 함수를 변형한 함수로, 로그를 적용하여 안정적인 확률 값을 계산하는 방식입니다.
Softmax 함수에서 직접 로그를 적용하면 수치적으로 불안정한 값이 나올 수 있는데,
이를 방지하기 위해 Softmax 계산 과정에서 로그를 먼저 취하는 방법을 사용합니다.
수식은 다음과 같습니다.
$$logS_i = x_i - \max(x) - \log \sum_{j} e^{x_j - \max(x)}$$
여기서:
- max(x)를 빼주는 것은 **수치적 안정성(numerical stability)**을 위한 것입니다.
- 직접 Softmax 후 로그를 취하는 것보다 더 안전한 방식입니다.
Python 구현
def log_softmax(scores: list) -> np.ndarray:
answer = np.zeros(len(scores)) # 결과 저장 배열
max_score = max(scores) # 안정성을 위한 최대값
total = sum([math.exp(score - max_score) for score in scores]) # 정규화된 지수 값들의 합
for i in range(len(scores)):
answer[i] = scores[i] - max_score - np.log(total) # Log-Softmax 변환
return np.array(answer)
# 테스트
print(log_softmax([1, 2, 3]))
print(sum(log_softmax([1, 2, 3]))) # 합이 0에 가까운 값이 됨
설명
- 먼저 max(scores)를 계산하여 가장 큰 값을 찾습니다.
- 모든 점수에서 max(scores)를 빼고 지수 함수를 적용하여 오버플로우(overflow) 방지를 합니다.
- 이후 로그를 적용하여 Log-Softmax 변환을 수행합니다.
- 결과 값들의 합은 0에 가까운 값을 가집니다.
3. Softmax vs Log-Softmax 비교
항목 | Softmax | Log-Softmax |
출력 값의 범위 | (0,1) | (−∞,0] |
합의 값 | 1 | 0 |
계산 방식 | 확률 분포로 변환 | 확률 값에 로그 적용 |
수치 안정성 | 다소 불안정 (오버플로우 가능) | 상대적으로 안정적 |
사용 예시 | 분류 확률 계산 | 크로스 엔트로피 손실 계산 |
4. 딥러닝에서의 활용
- Softmax 함수
- 딥러닝에서 마지막 출력층(출력 레이어)에 사용됨
- 분류 문제에서 다중 클래스 확률을 얻기 위해 활용됨
- torch.nn.Softmax() 또는 tensorflow.nn.softmax()로 쉽게 사용 가능
- Log-Softmax 함수
- 크로스 엔트로피 손실(CrossEntropyLoss)을 계산할 때 사용됨
- Log를 적용하면 곱셈 연산이 덧셈 연산으로 변환되어 계산 효율성이 증가
- torch.nn.LogSoftmax()로 사용 가능
- Log-Softmax와 NLLLoss(negative log likelihood loss)를 함께 쓰면 CrossEntropyLoss와 동일한 효과를 가짐
5. 개선할 수 있는 점
위 코드에서는 math.exp()를 사용하여 개별적으로 Softmax와 Log-Softmax를 계산했는데,
NumPy의 벡터 연산을 활용하면 성능을 더 최적화할 수 있습니다.
최적화된 코드
def softmax(scores: list) -> np.ndarray:
scores = np.array(scores)
exp_scores = np.exp(scores - np.max(scores)) # 수치 안정성을 위해 최대값을 빼줌
return exp_scores / np.sum(exp_scores)
def log_softmax(scores: list) -> np.ndarray:
scores = np.array(scores)
max_score = np.max(scores)
return scores - max_score - np.log(np.sum(np.exp(scores - max_score)))
- np.exp(scores - np.max(scores)): 최대값을 빼서 안정성을 확보
- np.sum()을 사용하여 한 번에 연산 처리하여 효율성 증가
6. 결론
- Softmax는 확률 분포를 얻을 때 유용하며, Log-Softmax는 크로스 엔트로피 손실을 계산할 때 안정적인 방식으로 활용됩니다.
- 직접 구현할 수도 있지만, 딥러닝 라이브러리(PyTorch, TensorFlow)에서 제공하는 함수를 사용하면 더욱 효율적입니다.
- 수치 안정성을 고려하여 max(scores)를 빼주는 것이 중요한 최적화 기법입니다.
728x90
반응형
'Language-LAB > Python' 카테고리의 다른 글
One-hot Encoding 구현 (0) | 2025.02.11 |
---|---|
range 와 np.arange() (1) | 2025.02.10 |
[Pytorch] 2 (0) | 2023.08.30 |
[pytorch] 1 (0) | 2023.08.30 |