๐ก 1. ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ข
๋ฅ
1-1. ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ๋ฒ
- ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ(Vanilla Gradient Descent)
- ๋ฐ์ดํฐ์
์ ์ฒด๋ฅผ ๊ณ ๋ คํ์ฌ ์์คํจ์๋ฅผ ๊ณ์ฐ
- ํ ๋ฒ์ Epoch์ ๋ชจ๋ ํ๋ผ๋ฏธํฐ ์
๋ฐ์ดํธ๋ฅผ ๋จ ํ ๋ฒ๋ง ์ํ
- ํ๋ผ๋ฏธํฐ ์
๋ฐ์ดํธํ ๋ ํ ๋ฒ์ ์ ์ฒด ๋ฐ์ดํฐ์
์ ๊ณ ๋ คํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ธ ํ์ต ์ ๋ง์ ์๊ฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ๋ค๋ ๋จ์ ์ด ์์
1-2. ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ
- ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ(Stochastoc Gradient Descent)์ ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ด ๋ชจ๋ธ ํ์ต ์ ๋ง์ ์๊ฐ๊ณผ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํ๋ค๋ ๋จ์ ์ ๋ณด์ํ๊ธฐ ์ํด ์ ์๋ ๊ธฐ๋ฒ
- batch size๋ฅผ 1๋ก ์ค์ ํ์ฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์
๋ฐ์ดํธ ํ๊ธฐ ๋๋ฌธ์ ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ๋ฒ๋ณด๋ค ํจ์ฌ ๋น ๋ฅด๊ณ ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ก ํ์ต์ ์งํ
- ํ๋ผ๋ฏธํฐ ๊ฐ์ ์
๋ฐ์ดํธ ํญ์ด ๋ถ์์ ํ๊ธฐ ๋๋ฌธ์ ์ ํ๋๊ฐ ๋ฎ์ ๊ฒฝ์ฐ๊ฐ ์๊ธธ ์ ์์
1-3. ๋ฏธ๋ ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ๋ฒ
- ๋ฏธ๋ ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ๋ฒ(Mini-Batch Gradient Descent)์ Batch Size๋ฅผ ์ค์ ํ size๋ก ์ฌ์ฉ
- ๋ฐฐ์น ๊ฒฝ์ฌ ํ๊ฐ๋ฒ๋ณด๋ค ๋ชจ๋ธ ์๋๊ฐ ๋น ๋ฅด๊ณ , ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ๋ณด๋ค ์์ ์ ์ธ ์ฅ์ ์ด ์์
- ๋ฅ๋ฌ๋ ๋ถ์ผ์์ ๊ฐ์ฅ ๋ง์ด ํ์ฉ๋๋ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ
- ์ผ๋ฐ์ ์ผ๋ก Batch Size๋ฅผ 4, 8, 16, 32, 64, 128๊ณผ ๊ฐ์ด 2์ n์ ๊ณฑ์ ํด๋นํ๋ ๊ฐ์ผ๋ก ์ฌ์ฉํ๋๊ฒ ๊ด๋ก์
๐ก 2. ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ์ฌ๋ฌ๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ
2-1. SGD(ํ๋ฅ ์ ๊ฒฝ์ฌ ํ๊ฐ๋ฒ)
- ๋งค๊ฐ๋ณ์ ๊ฐ์ ์กฐ์ ์ ์ ์ฒด ๋ฐ์ดํฐ๊ฐ ์๋๋ผ ๋๋ค์ผ๋ก ์ ํํ ํ๋์ ๋ฐ์ดํฐ์ ๋ํด์๋ง ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ
2-2. ๋ชจ๋ฉํ
(Momentum)
- ๊ฒฝ์ฌ ํ๊ฐ๋ฒ์ ๋จ์ ์ ๋ณด์ํ๊ธฐ ์ํด ๋์
๋ ์๊ณ ๋ฆฌ์ฆ
- ๊ด์ฑ์ด๋ผ๋ ๋ฌผ๋ฆฌํ ๋ฒ์น์ ์์ฉํ ๋ฐฉ๋ฒ
- ์ ์ ์ ๊ธฐ์ธ๊ธฐ์ ํ ์์ ์ด์ ์ ์ ์ ์ ๊ธฐ์ธ๊ธฐ ๊ฐ์ ์ผ์ ํ ๋น์จ๋งํผ ๋ฐ์
- ์ด์ ๊ธฐ์ธ๊ธฐ์ ์ด๋ ํ๊ท ์ ์ฌ์ฉํ์ฌ ํ์ฌ ๊ธฐ์ธ๊ธฐ๋ฅผ ์
๋ฐ์ดํธ
- ๊ฐ์๋๋ฅผ ์ ๊ณตํ์ฌ, ๊ฒฝ์ฌ ํ๊ฐ๋ฒ๋ณด๋ค ๋น ๋ฅด๊ฒ ์ต์๊ฐ์ ๋๋ฌํ ์ ์์
2-3. ์๋ค๊ทธ๋ผ๋(Adagrad)
- ๋ชจ๋ ๋งค๊ฐ๋ณ์์ ๋์ผํ ํ์ต๋ฅ (lr)์ ์ ์ฉํ๋ ๊ฒ์ ๋นํจ์จ์ ์ด๋ค๋ผ๋ ์๊ฐ์์ ๋ง๋ค์ด์ง ํ์ต ๋ฐฉ๋ฒ
- ์ฒ์์๋ ํฌ๊ฒ ํ์ตํ๋ค๊ฐ ์กฐ๊ธ์ฉ ์๊ฒ ํ์ต์ํด
- ๊ฐ ํ๋ผ๋ฏธํฐ์ ๋ง์ถคํ ํ์ต๋ฅ ์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ
- ํฌ์ํ ๋ฐ์ดํฐ์์ ์ ๋ฆฌํจ
- ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ํ์ต๋ฅ ์ด ๊ณ์ ๊ฐ์ํ์ฌ ํ์ต์ ๋ฉ์ถ ์ ์์
2-4. ์๋ด(Adam)
- ๋ชจ๋ฉํ
+ ์๋ค๊ทธ๋ผ๋
- ๊ฐ ๋งค๊ฐ๋ณ์์ ๋ํด ์ ์ํ ํ์ต๋ฅ ์ ์ ์ฉํ๋ฉฐ, ๊ณผ๊ฑฐ์ ๊ธฐ์ธ๊ธฐ ์ ๋ณด๋ฅผ ํ์ฉํด ํ์ฌ์ ํ์ต๋ฅ ์ ์กฐ์
- AdamW: Adam์ ๋ณํ์ผ๋ก L2์ ๊ทํ(๊ฐ์ค์น ๊ฐ์ )๋ฅผ ๋ณ๋๋ก ์ฒ๋ฆฌํ์ฌ ๋ ๋์ ์ผ๋ฐํ ์ฑ๋ฅ์ ์ ๊ณต, L2 ์ ๊ทํ๊ฐ ํ์ต๋ฅ ์กฐ์ ๊ณผ ์์ฌ ๋ถ์์ ํ ํ์ต์ ์ด๋ํ ์ ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ
๐ก 3. ์์ธ ํ์ข
์์ธกํ๊ธฐ
- sklearn.datasets.load_wine: ์ดํ๋ฆฌ์์ ๊ฐ์ ์ง์ญ์์ ์ฌ๋ฐฐ๋ ์ธ๊ฐ์ง ๋ค๋ฅธ ํ์ข
์ผ๋ก ๋ง๋ ์์ธ์ ํํ์ ์ผ๋ก ๋ถ์ํ ๊ฒฐ๊ณผ์ ๋ํ ๋ฐ์ดํฐ์
- 13๊ฐ์ ์ฑ๋ถ์ ๋ถ์ํ์ฌ ์ด๋ค ์์ธ์ธ์ง ๊ตฌ๋ณํ๋ ๋ชจ๋ธ์ ๊ตฌ์ถ
- ๋ฐ์ดํฐ๋ฅผ ์์ ํ train ๋ฐ์ดํฐ๋ฅผ 80%, test ๋ฐ์ดํฐ๋ฅผ 20%๋ก ํ์ฌ ์ฌ์ฉ
- Adam์ ์ฌ์ฉ
- optimizer = optim.Adam(model.parameters(), lr=0.01)
- ํ
์คํธ ๋ฐ์ดํฐ์ 0๋ฒ ์ธ๋ฑ์ค๊ฐ ์ด๋ค ์์ธ์ธ์ง ์์๋ณด์. ์ ํ๋๋ฅผ ์ถ๋ ฅ
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
x_data, y_data = load_wine(return_X_y=True, as_frame=True)
x_data = torch.FloatTensor(x_data.values)
y_data = torch.LongTensor(y_data.values)
print(x_data.shape)
print(y_data.shape)
> torch.Size([178, 13])
> torch.Size([178])
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=2024)
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
torch.Size([142, 13]) torch.Size([142])
torch.Size([36, 13]) torch.Size([36])
model = nn.Sequential(
nn.Linear(13, 3)
)
optimizer = optim.Adam(model.parameters(), lr=0.01)
epochs = 1000
for epoch in range(epochs + 1):
y_pred = model(x_train)
loss = nn.CrossEntropyLoss()(y_pred, y_train)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 100 == 0:
y_prob = nn.Softmax(1)(y_pred)
y_pred_index = torch.argmax(y_prob, axis=1)
y_train_index = y_train
accuracy = (y_pred_index == y_train_index).float().sum() / len(y_train) * 100
print(f'Epoch {epoch:4d}/{epochs} Loss:{loss: .6f} Accuracy: {accuracy: .2f}%')
Epoch 0/1000 Loss: 100.665215 Accuracy: 25.35%
Epoch 100/1000 Loss: 0.302390 Accuracy: 89.44%
Epoch 200/1000 Loss: 0.197123 Accuracy: 92.25%
Epoch 300/1000 Loss: 0.158662 Accuracy: 94.37%
Epoch 400/1000 Loss: 0.137645 Accuracy: 95.77%
Epoch 500/1000 Loss: 0.123086 Accuracy: 97.18%
Epoch 600/1000 Loss: 0.111958 Accuracy: 98.59%
Epoch 700/1000 Loss: 0.102981 Accuracy: 98.59%
Epoch 800/1000 Loss: 0.095471 Accuracy: 98.59%
Epoch 900/1000 Loss: 0.089016 Accuracy: 98.59%
Epoch 1000/1000 Loss: 0.083348 Accuracy: 98.59%
y_pred = model(x_test)
y_pred[:5]
> tensor([[-28.7244, -30.6228, -22.7633],
[-51.6261, -58.9351, -60.1704],
[-17.1980, -12.4382, -12.0121],
[-54.0891, -59.6118, -59.6391],
[-30.0164, -31.9313, -35.4247]], grad_fn=<SliceBackward0>)
y_prob = nn.Softmax(1)(y_pred)
y_prob[:5]
> tensor([[2.5695e-03, 3.8493e-04, 9.9705e-01],
[9.9914e-01, 6.6892e-04, 1.9448e-04],
[3.3733e-03, 3.9373e-01, 6.0290e-01],
[9.9218e-01, 3.9641e-03, 3.8571e-03],
[8.6818e-01, 1.2793e-01, 3.8885e-03]], grad_fn=<SliceBackward0>)
print(f'0๋ฒ ํ์ข
์ผ ํ๋ฅ : {y_prob[0][0]:.2f}')
print(f'1๋ฒ ํ์ข
์ผ ํ๋ฅ : {y_prob[0][1]:.2f}')
print(f'2๋ฒ ํ์ข
์ผ ํ๋ฅ : {y_prob[0][2]:.2f}')
> 0๋ฒ ํ์ข
์ผ ํ๋ฅ : 0.00
> 1๋ฒ ํ์ข
์ผ ํ๋ฅ : 0.00
> 2๋ฒ ํ์ข
์ผ ํ๋ฅ : 1.00
y_pred_index = torch.argmax(y_prob, axis=1)
accuracy = (y_test == y_pred_index).float().sum() / len(y_test) * 100
print(f'ํ
์คํธ ์ ํ๋๋ {accuracy: .2f}% ์
๋๋ค!')
> ํ
์คํธ ์ ํ๋๋ 94.44% ์
๋๋ค!