일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 백준
- rnn
- 강의자료
- 홍콩과기대김성훈교수
- 딥러닝
- 스택
- 알고리즘
- tensorflow
- Natural Language Processing with PyTorch
- 정렬
- Hypothesis
- Deep learning
- 머신러닝
- DP
- MSE
- 파이토치
- 머신러닝 기초
- Python
- Softmax
- Cross entropy
- pytorch
- classifier
- BAEKJOON
- 파이썬
- DynamicProgramming
- 자연어처리
- AI
- 강의정리
- machine learning
- loss
- Today
- Total
개발자의시작
[Pytorch] 06-2 Softmax Classification Pytorch 본문
이 글은 모두를위한딥러닝 시즌2 https://github.com/deeplearningzerotoall/PyTorch 을 정리한 글입니다.
Softmax Classification 도 Logistic Regression의 연장선 상에 있는 것으로 볼 수 있다.
Softmax Classification을 위해 필요한 패키지들을 import 한다. 항상 똑같은 결과를 보장하기 위해서 torch.manual_seed(1)과 같이 고정된 시드를 부여한다.
Discrete Probability Distribution 이란 이산적인 확률 분포를 이른다. 확률분포에는 연속적인 확률 분포가 있고 이산적인 확률 분포가 있다. 가령 주사위를 던질 경우 1, 2, 3, 4, 5, 6 중 하나의 숫자를 얻을 수 있다. 1.5나 4.5 등의 어떤 중간 값이 나오지 않는다. 마찬가지로 가위 바위 보 도 마찬가지로 가위, 바위, 보 세 개중 하나만 낼 수 있다. Discrete Probability Distribution은 PMF(probability mass function)로 나타낼 수 있는데, 주사위의 PMF는 위 그림의 아래처럼 나타낼 수 있다. 또한 가위 바위 보의 경우도 나타낼 수 있는데, 주사위는 uniform distribution(연속 균등 분포)로 나타나지만 가위 바위 보의 경우 uniform distribution이 아닐 수 있다.
일반적으로 알고 있는 확률분포인 PDF(Probability Density Function)의 경우에는 왼쪽 그림과 같이 면적이 확률 값을 의미했다. 어떤 포인트 자체는 확률이 아니다. PDF 확률분포에서 어떤 값 x가 있을 때, P(X=x)의 확률을 알 수 없다. 반면 이산적인 확률 분포에서는 포인트를 통해 어떤 값을 구할 수 있다. 예를 들어 주사위를 던지는 사건 X가 6일 경우는 P(X=6)= 1/과 같이 나타낼 수 있다.
그래서 우리는 이산적인 확률 분포를 바탕으로 neural network 또는 machine learning을 수행하게 되는데, 예를 들어 가위바위보에서 상대방이 다음에 낼 것을 예측하는 머신러닝 프로그램을 짠다고 가정한다. 이전의 상대방이 낸 것을 바탕으로 다음에 상대방이 낼 것을 예측할 수 있을 것이다(완전히 랜덤이 아니라 사람마다 일정한 패턴이 있을 것이라 가정). 주어진 값에 대해 argmax( )의 결과 값은 (0, 0, 1)이 될 것이다. 하지만 softmax는 합쳐서 1이 되는 일종의 확률 값과 같이 나타내 준다.
Cross Entropy
Cross Entropy라고 하는 것은 두 개의 확률 분포가 주어졌을 때, 두 개의 확률 분포가 얼마나 비슷한지를 타나 낼 수 있는 수치이다. 위의 수식을 보면 두 개의 확률분포 P와 Q가 있다. 수식을 해석하면, 확률분포 P에서 x를 샘플링하고 샘플링한 x를 Q에 넣은 후에 log를 씌운 값의 평균으로 볼 수 있다. 그림은 이를 조금 더 직관적으로 나타낸 것이다. 예를 들어 맨 왼쪽에 있는 분포를 P, 다음을 각각 Q1, Q2라고 할 때, 여기서 샘플링을 하면 log()를 취하고 -를 취해줬기 때문에 Q1의 값이 Q2의 값보다 훨씬 작은 값이 된다(그림에서 우측 샘플링 기준). Cross Entropy를 최소화하도록 하면 Q2에서 Q1으로 갈 수 있을 것이고 계속해서 P에 다가갈 수 있을 것이다. 즉, Cross Entropy를 최소화하는 것은 모델의 확률 분포 함수를 점점 P에 근사하도록 하는 것이다.
Cross Entropy Loss는 위의 수식과 같이 나타낼 수 있다. y는 실제 정답 y이며 P(x)에 해당한다. ^y는 Q(x)이며 어떤 PΘ(x)와 같이 표현할 수 도 있다. torch.rand() 함수를 사용하여 (3, 5) 사이즈의 텐서 z를 생성한다. 그리고 이것은 required_grad=True를 통해 그래디언트 학습이 가능하다. 다음으로 z에 대해 F.softmax() 함수를 수행하고 dim=1을 통해 두 번째 차원(5)에 대해 softmax를 수행한다. 위 예는 랜덤 한 값을 사용한 실습이기 때문에 정해진 정답은 없지만, 코드를 살펴보면 5개의 class를 갖고 3개의 sample을 갖는다.
torch.zeros_like() 함수를 통해 |y_one_hot| 은 (3, 5) 사이즈의 0으로 채워진 벡터를 갖는다. scatter() 함수를 불러주는데, _가 붙어 있어 inplace연산을 수행한다(메모리를 새로 할당하지 않고 y_one_hot에 채워준다). scatter() 함수의 인자를 살펴보면, 첫 번째 인자는 dim=1에 대한 것을 의미하고, y.unsqueeze()는 dim 1에 대한 것, 마지막 인자는 채워줄 값을 의미한다.
y_one_hot과 Hypothesis의 사이즈는 갖고, dim=1에 대해 sum()을 수행하면 기존 (3, 5) 사이즈에서 (3, 1) 사이즈가 된다. mean() 함수를 통해 평균을 구해주면 scalar 값을 갖게 된다.
PyTorch에서는 위의 과정을 간략하게 할 수 있는 softmax함수를 제공하고 log_softmax 또한 제공한다.
#Low level에서 torch.log(F.softmax())는 F.log_softmax()로 간단하게 표현할 수 있다.
#High level에서 한 번 더 간단하게 NLL_Loss를 사용할 수 있다. NLL은 Negative Log Likelihood의 약자이다.
이 마저도 더 간편하게 할 수 있는데 F.cross_entropy를 사용하면 된다. F.cross_entropy 함수는 F.log_softmax() 함수와 F.nll_loss() 함수를 결합한 것으로 위를 보면 같은 결과를 출력한다.
그러면 이제 앞에서 봤던 Cross_entropy 손실 함수를 통해서 학습하는 과정을 살펴본다.
위와 같이 학습 데이터가 주어질 때 x_train은 (m, 4)의 크기를 갖는다(m개의 샘플과 4차원으로 이루어진 벡터). y_train은 m개의 값을 갖고 요약하면, 4차원의 어떤 벡터를 받아서 어떤 클래스인지 예측하도록 하는 것. 샘플의 개수는 m, 클래스의 개수는 3, 입력 벡터의 사이즈는 4가 된다.
모델은 두 개의 학습 파라미터 W와 b를 갖는다. 샘플의 개수는 m, 클래스의 개수는 3, 차원의 개수는 4이므로 4->3으로 가는 Linear Layer를 만든다(W= torch.zeros((4, 3), requires_grad=True). 실행 결과를 보면 cost가 점차 줄어들며 학습이 잘 되는 것을 확인할 수 있다.
F.cross_Entropy()를 사용하여 더 간단하게 표현할 수 있다. F.cross_entropy()는 실제 정답과 비교를 바로 수행하며 scatter 즉, one-hot 벡터를 만들어주는 과정을 생략하고 처리할 수 있다.
이것을 더 쉽게 실전에 가깝게 구현할 수 있다. nn.Module을 상속받아 SoftmaxClassifierModel() 클래스를 정의하여 사용할 수 있다.
Classification을 수행하기 위해서는 Cross_entropy를 사용해야 하고 softmax를 수행하기 마련이다. 이진 분류에서는 BCE(Binary Cross Entropy)와 sigmoid를 사용하고 다중 분류에서는 CE(Cross Entropy)와 softmax를 사용.
1
2
3
4
5
6
7
8
9
10
11
|
x_train = [[1, 2, 1, 1],
[2, 1, 3, 2],
[3, 1, 3, 4],
[4, 1, 5, 5],
[1, 7, 5, 5],
[1, 2, 5, 6],
[1, 6, 6, 6],
[1, 7, 7, 7]]
y_train = [2, 2, 2, 1, 1, 1, 0, 0]
x_train = torch.FloatTensor(x_train)
y_train = torch.LongTensor(y_train)
|
Training with Low-level Cross Entropy Loss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# 모델 초기화
W = torch.zeros((4, 3), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
# optimizer 설정
optimizer = optim.SGD([W, b], lr=0.1)
nb_epochs = 1000
for epoch in range(nb_epochs + 1):
# Cost 계산 (1)
hypothesis = F.softmax(x_train.matmul(W) + b, dim=1) # or .mm or @
y_one_hot = torch.zeros_like(hypothesis)
y_one_hot.scatter_(1, y_train.unsqueeze(1), 1)
cost = (y_one_hot * -torch.log(F.softmax(hypothesis, dim=1))).sum(dim=1).mean()
# cost로 H(x) 개선
optimizer.zero_grad()
cost.backward()
optimizer.step()
# 100번마다 로그 출력
if epoch % 100 == 0:
print('Epoch {:4d}/{} Cost: {:.6f}'.format(
epoch, nb_epochs, cost.item()
))
|
Training with F.cross_entropy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# 모델 초기화
W = torch.zeros((4, 3), requires_grad=True)
b = torch.zeros(1, requires_grad=True)
# optimizer 설정
optimizer = optim.SGD([W, b], lr=0.1)
nb_epochs = 1000
for epoch in range(nb_epochs + 1):
# Cost 계산 (2)
z = x_train.matmul(W) + b # or .mm or @
cost = F.cross_entropy(z, y_train)
# cost로 H(x) 개선
optimizer.zero_grad()
cost.backward()
optimizer.step()
# 100번마다 로그 출력
if epoch % 100 == 0:
print('Epoch {:4d}/{} Cost: {:.6f}'.format(
epoch, nb_epochs, cost.item()
))
|
High-level Implementation with nn.Module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class SoftmaxClassifierModel(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(4, 3) # Output이 3!
def forward(self, x):
return self.linear(x)
model = SoftmaxClassifierModel()
# optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=0.1)
nb_epochs = 1000
for epoch in range(nb_epochs + 1):
# H(x) 계산
prediction = model(x_train)
# cost 계산
cost = F.cross_entropy(prediction, y_train)
# cost로 H(x) 개선
optimizer.zero_grad()
cost.backward()
optimizer.step()
# 20번마다 로그 출력
if epoch % 100 == 0:
print('Epoch {:4d}/{} Cost: {:.6f}'.format(
epoch, nb_epochs, cost.item()
))
|
'머신러닝(machine learning)' 카테고리의 다른 글
[Pytorch] 07-2 MNIST Introduction (0) | 2022.01.14 |
---|---|
[Pytorch] 07-1 Tips (0) | 2021.12.30 |
[Pytorch] 06-1 Softmax Classification (0) | 2021.12.28 |
[Pytorch] 05-2 Logistic Regression 2 (0) | 2021.12.23 |
[Pytorch] 05-1 Logistic Regression (0) | 2021.12.08 |