1. 데이터 로더(Data Loader)
- 데이터의 양이 많을 때 배치 단위로 학습하는 방법
손글씨 인식 모델 만들기 실습
1. 필요모듈 임포트
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
2. CPU -> GPU 변경
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)
# 결과값 => cuda
3. 데이터를 x_data, y_data에 담고 shape하기
digits = load_digits()
x_data = digits['data']
y_data = digits['target']
print(x_data.shape)
print(y_data.shape)
# 결과값 =>
# (1797, 64)
# (1797,)
4. 이미지 출력
fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(14, 8))
for i, ax in enumerate(axes.flatten()):
ax.imshow(x_data[i].reshape((8, 8)), cmap='gray')
ax.set_title(y_data[i])
ax.axis('off')
5. x_data, y_data를 tensor형식으로 변경 후 shape
x_data = torch.FloatTensor(x_data)
y_data = torch.LongTensor(y_data)
print(x_data.shape)
print(y_data.shape)
# 결과값 =>
# torch.Size([1797, 64])
# torch.Size([1797])
6. 데이터 분활
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([1437, 64]) torch.Size([1437])
# torch.Size([360, 64]) torch.Size([360])
7. 진행
loader = torch.utils.data.DataLoader(
dataset = list(zip(x_train, y_train)),
batch_size = 64,
shuffle = True
# drop_last=False, 마지막 짜투리를 버리는 옵션, 64개로 학습을 쪼개는데 1000/64를 하면 나머지 값을 버린다. (True면 안버리고 계산)
)
# 필요한 과정은 아님 시각화를 위해 아래에 코드 추가
# imgs = x_train, y_train = labels
# 차례대로 출력하는 iter함수 사용, 하나씩 가져오기 위해 next함수 사용
imgs, labels = next(iter(loader))
# imgs
# labels
fig, axes = plt.subplots(nrows=8, ncols=8, figsize=(14, 14))
for ax, img, label in zip(axes.flatten(), imgs, labels):
ax.imshow(img.reshape((8, 8)), cmap='gray')
ax.set_title(str(label))
ax.axis('off') #눈금자 없애기
8. 모델 생성 및 활용
# 모델 생성하기
model = nn.Sequential(
nn.Linear(64, 10) # 64개(batchsize가 아닌 8*8인 값을 넣는거다. 즉, nrows * ncols), 0~9까지 총 10개
)
optimizer = optim.Adam(model.parameters(), lr=0.01)
epochs = 50
for epoch in range(epochs + 1):
sum_losses = 0
sum_accs = 0
for x_batch, y_batch in loader:
y_pred = model(x_batch)
loss = nn.CrossEntropyLoss()(y_pred, y_batch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
sum_losses = sum_losses + loss
y_prob = nn.Softmax(1)(y_pred)
y_pred_index = torch.argmax(y_prob, axis=1)
acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100
sum_accs = sum_accs + acc
avg_loss = sum_losses / len(loader) # len(loader) loader안에 있으면 데이터의 계수는
avg_acc = sum_accs / len(loader)
print(f'Epoch {epoch:4d}/{epochs} Loss: {avg_loss:.6f} Accuracy: {avg_acc:.2f}%')
# 64개씩 쪼개서 다 돌린것이 에폭1임. 지금은 64번마다 기울기 업데이트가 되는것.
9. x_test의 10번째 값 출력
plt.imshow(x_test[10].reshape((8, 8)), cmap='gray')
print(y_test[10])
10. 테스트
y_pred = model(x_test)
y_pred[10]
# 결과값 =>
# tensor([ -6.9612, -1.1249, -9.0588, 1.1923, 0.3704, -6.8912, -11.5940,
# 14.5614, 0.6476, 5.4962], grad_fn=<SelectBackward0>)
11. 확률 구하기
y_prob = nn.Softmax(1)(y_pred)
y_prob[10]
# 결과값 =>
# tensor([4.4958e-10, 1.5398e-07, 5.5187e-11, 1.5625e-06, 6.8689e-07, 4.8218e-10,
# 4.3734e-12, 9.9988e-01, 9.0627e-07, 1.1561e-04],
# grad_fn=<SelectBackward0>)
# ------------------------------------------------
for i in range(10):
print(f'숫자 {i}일 확률: {y_prob[10][i]:.2f}')
# 결과값 =>
# 숫자 0일 확률: 0.00
# 숫자 1일 확률: 0.00
# 숫자 2일 확률: 0.00
# 숫자 3일 확률: 0.00
# 숫자 4일 확률: 0.00
# 숫자 5일 확률: 0.00
# 숫자 6일 확률: 0.00
# 숫자 7일 확률: 1.00
# 숫자 8일 확률: 0.00
# 숫자 9일 확률: 0.00
12. 최종 결과값
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}% 입니다')
# 결과값 => 테스트 정확도는 96.39% 입니다
'Study > 머신러닝과 딥러닝' 카테고리의 다른 글
[머신러닝과 딥러닝] 18. 비선형 활성화 함수 (0) | 2024.01.10 |
---|---|
[머신러닝과 딥러닝] 17. 딥러닝(AND, OR, XOR 게이트) (1) | 2024.01.10 |
[머신러닝과 딥러닝] 15. 파이토치로 구현한 논리회귀_2(경사하강법 + 와인 품종 예측) (1) | 2024.01.10 |
[머신러닝과 딥러닝] 15. 파이토치로 구현한 논리회귀_1 (0) | 2024.01.10 |
[머신러닝과 딥러닝] 14. 파이토치로 구현한 선형회귀_2(지면온도 예측) (0) | 2024.01.09 |