소프트맥스 함수: 머신러닝 분류의 일꾼
이 글에서는 Python에서 Softmax 함수를 구현하는 방법과 이를 효과적으로 활용하는 방법을 배경과 맥락과 함께 살펴봅니다. 이 글은 AI 번역본입니다. 오역이 있으면 댓글로 알려 주세요.
Created on September 12|Last edited on September 12
Comment
소개
그 소프트맥스 함수 은/는 머신 러닝 전반에 걸쳐 널리 사용됩니다. 결국 분류 문제에서 사실상의 기본 활성화 층이기 때문입니다. 이러한 소프트맥스 층은 모델이 오직 하나의 선택에 집중하도록 만들며, 마치 하나의 선택지만을 고르는 것처럼 동작합니다. argmax 연속이고 미분 가능한 함수입니다. 또한 CrossEntropy 함수를 다음의 경우에 볼록하게 만듭니다. 항들은 선형적이거나(혹은 충분히 규칙적이거나) 합니다.
이 글에서는 소프트맥스 함수가 무엇인지, 머신 러닝에서 어떻게 사용되는지, 그리고 Python에서 어떻게 구현하는지를 살펴봅니다. 다음 내용을 다룹니다:
목차
시작해 봅시다!
나의 소프트맥스 여정
소프트맥스 함수와의 인연은 교통경제학과 도시계획 전공으로 석사와 박사 과정을 밟던 시절로 거슬러 올라갑니다. 이 분야에서는 이를 소프트맥스라고 부르지는 않지만, 소비자 행동을 모형화할 때 두는 가정들의 자연스러운 결과로 동일한 형태가 나타납니다. 사실, 이에 대한 기초를 설명한 장을 제 …에 정리해 두었습니다. 박사 학위 논문(34쪽 참조).
💡
미시경제학적 맥락에서는, 소비자가 지각하는 효용 함수의 오차항에 대한 가정으로부터 소프트맥스 함수가 도출됩니다. 자세한 내용은 생략하면, 오차를 사용자 j가 지각하는 효용(또는 비용)을 측정할 때 오차가 특정 분포를 따른다고 가정하면, 그 사용자가 선택지 j를 선택할 확률을 계산하면 다음과 같습니다:
사용자는 다른 대안보다 효용이 더 크다고 지각하면 j를 선택합니다. “다른 선택지들보다 당신을 더 만족하게 만든다면 X를 살 것이다.”
그 과정에 이르는 구체적인 이유는, 두 개의 검벨 분포 오차의 차이가 로지스틱 분포를 따른다는 사실에서 비롯됩니다:
그래서 그 이름이 나온 것입니다 Logits 소프트맥스 함수에 입력되는 항들을 부를 때!
💡
로지스틱 분포에는 여기서 다루지 않을 다른 유용한 성질들도 있으며, 미시경제학에서 매우 사랑받는 일꾼 같은 도구이기도 합니다.
머신러닝에서 소프트맥스를 어떻게 활용할까요?
머신러닝 모델로 분류 문제를 풀 때, 주어진 입력에 대해 하나의 대안을 선택할 수 있는 모델을 원하는 경우가 많습니다:
- 이것은 고양이인가요, 개인가요?
- 이 문장은 긍정적인가요, 부정적인가요?
- 이건 어떤 견종인가요?
- 이 영화에 1부터 5까지 점수를 매겨 주세요
이런 문제들은 모두 ML로 풀 수 있습니다. 우리가 원하는 것은 주어진 선택지 중 하나를 고르는 모델인데, 여기서 Softmax가 어떻게 도움이 될까요?
예시 사례
일반적으로 ML 모델은 실수(float) 값을 출력합니다. 우리는 이를 점수라고 부릅니다. 예를 들어, 한 강아지 사진이 어떤 견종인지 결정하고 싶다고 해봅시다. 단순화를 위해 가능한 견종이 10가지라고 가정하겠습니다. 우리는 여러 층으로 구성된 신경망을 만들고, 마지막 층에서 각 견종마다 하나씩 총 10개의 점수를 출력하게 될 것입니다.
가장 간단한 방법은 점수가 가장 높은 항목을 고르는 것입니다. 끝입니다 — 우리가 예측하려는 견종은 바로 그것이죠. 이는 다음으로 수행할 수 있습니다 argmax 함수로, 점수가 가장 높은 견종을 반환합니다.
이 접근 방식의 문제는, 그… argmax 함수는 미분 가능하지 않아서 이 활성 함수를 사용하면 모델을 학습시킬 수 없습니다 😭
💡
좋아요, 실용적인 예시로 시작해 봅시다. 먼저 견종부터 정리해 보겠습니다:
0: Beagles1: Golden Retrievers.2: German Shepherd Dogs.3: Poodles.4: Bulldogs.5: Rottweilers.6: Beagles.7: Dachshunds.8: German Shorthaired Pointers.9: Rottweilers.
그리고 이제 입력 이미지입니다:

점수는 다음과 같습니다:
scores = [6, 2, 3, 10, 5, 1, 7, 8, 9, 4]
그러면 “선택”은 최댓값인 10으로 결정되고, 모델은 “푸들”을 예측해야 합니다. 이제 소프트맥스를 계산해 봅시다:
from math import expdef softmax(x: list):exp_x = [exp(xi) for xi in x]return [ex/sum(exp_x) for ex in exp_x]for i, x in enumerate(softmax(scores)):print(f"{i}: {x:2.2f}")# output# 0: 0.01# 1: 0.00# 2: 0.00# 3: 0.63. <--- clearly this one is higher than all the others =)# 4: 0.00# 5: 0.00# 6: 0.03# 7: 0.09# 8: 0.23# 9: 0.00
소프트맥스 함수는 모델이 반드시 하나를 선택하도록 만들며, 음의 로그 우도 손실(NLLLoss)과 결합될 때 여러 유용한 성질을 가능하게 합니다. 이 조합은 결국 교차 엔트로피 함수로 이어집니다.
소프트맥스의 상대적 차이에 대한 불변성
점수에 일정한 값을, 예를 들어 100을 더한 뒤 확률을 다시 계산하면 어떻게 될까요?
scores = [6, 2, 3, 10, 5, 1, 7, 8, 9, 4] + 100for i, x in enumerate(softmax(scores)):print(f"{i}: {x:2.2f}")# output# 0: 0.01# 1: 0.00# 2: 0.00# 3: 0.63. <--- Same as before =)# 4: 0.00# 5: 0.00# 6: 0.03# 7: 0.09# 8: 0.23# 9: 0.00
이전과 완전히 같은 값이 나옵니다! 여기서 실제로 일어나는 일은 로지스틱 분포가 대안들 사이의 차이만 인식하고, 척도는 무시하기 때문입니다!
NumPy와 PyTorch에서 구현하기
소프트맥스 함수는 NumPy 같은 배열 기반 라이브러리에서 간단히 구현할 수 있습니다.
import numpy as npscores = np.array([1,2,3,4])def softmax(scores: np.array):exp_scores = np.exp(scores)return exp_scores / exp_scores.sum()softmax(scores)> array([0.0320586 , 0.08714432, 0.23688282, 0.64391426])
import torchscores = torch.tensor([1,2,3,4])scores.softmax(). # or torch.softmax(scores)> torch.tensor([0.0320586 , 0.08714432, 0.23688282, 0.64391426])
소프트맥스 함수를 써야 할까요, 말아야 할까요?
사실, 신경망을 학습할 때는 당신은 … 해야 합니다 아니요 소프트맥스 함수를 쓰세요! 점수를 출력하는 네트워크를 만들고, 그 점수를 그대로 교차 엔트로피 손실에 입력하세요. 왜일까요? 교차 엔트로피에는 이미 Softmax 함수가 내장되어 있기 때문입니다. 이에 대해 자세히 설명한 글을 작성했습니다. PyTorch 그리고 Keras:
결론
이 작은 함수는 우리의 ML 여정에서 매우 유용하지만, 사실 올바른 사용법은 아예 사용하지 않는 것입니다 🤣. 소프트맥스 함수에는 다른 활용처도 있습니다. 예를 들어, “트랜스포머레이어에서 토큰 간 주의(attention) 메커니즘을 계산하는 데 사용되지만, 그것은 다른 글에서 다루겠습니다.
Add a comment