728x90
1. 포켓몬스터 149종 분류하기
🔻데이터셋 다운로드
# 데이터셋 다운로드
import os
os.environ['KAGGLE_USERNAME'] ='# username'
os.environ['KAGGLE_KEY'] = ' # key '
!kaggle datasets download -d thedagger/pokemon-generation-one
!kaggle datasets download -d hlrhegemony/pokemon-image-dataset
🔻압축해제 (리눅스 명령어)
# 받아온 데이터셋 압축해제하기 (리눅스 명령어)
!unzip -q pokemon-generation-one.zip -d ./train
!unzip -q pokemon-image-dataset.zip -d ./validation
🔻validation에서 train에 있는 디렉토리를 확인하여 없는 디렉토리는 제거 하기
# train : 149개, validation: 898개의 종류를 각각 가지고 있다.
# validation에서 train에 있는 디렉토리를 확인하여 없는 디렉토리는 제거 하기
import shutil
train_dir = "/content/train/dataset"
validation_dir = "/content/validation/images"
# train 디렉토리의 하위 디렉토리 목록 가져오기
train_subdirs = set(os.listdir(train_dir))
# validation 디렉토리의 하위 디렉토리 목록 가져오기
validation_subdirs = os.listdir(validation_dir)
# train에 없는 디렉토리 제거
for subdir in validation_subdirs:
subdir_path = os.path.join(validation_dir, subdir)
if not os.path.isdir(subdir_path) or subdir not in train_subdirs:
# 디렉토리가 아니거나 train에 없는 디렉토리인 경우 제거
print("Removing directory:", subdir_path)
shutil.rmtree(subdir_path)
🔻 validation에 없는 2종의 포켓몬 디렉토리를 추가로 만들기
common_subdirs = train_subdirs.intersection(validation_subdirs)
print(len(common_subdirs))
print(len(train_subdirs))
print(type(train_subdirs))
print(type(common_subdirs))
for subdir in train_subdirs:
if (subdir in common_subdirs) == False:
print(subdir)
👀validation에 존재 하지 않는 2종의 포켓몬은 ?
🔻 사용 모듈 추가하기
# 패키지 로드(import)
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
from torchvision import datasets, models, transforms
from torch.utils.data import DataLoader
🔻 GPU사용하기
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
🔻transforms.Compose를 사용하여 사이즈, Affine, RandomHrizontalFlip, ToTensor 변환등등등....
data_transforms = {
'train' : transforms.Compose([ # Compose 아래 내용을 한꺼번에 실행시켜라
transforms.Resize((224,224)), # 224,224사이즈로 변경 하기
transforms.RandomAffine(0, shear=10, scale=(0.8, 1.2)), # 랜덤하게 10개를 뽑아서 규모는 +-20%
transforms.RandomHorizontalFlip(), # 이미지 반전시킴
transforms.ToTensor() # 텐서 형태로 바꿔라
]),
'validation' : transforms.Compose([
transforms.Resize((224,224)),
transforms.ToTensor()
])
}
🔻데이터셋, 데이터로더 (bathch size를 32) 만들기
# 데이터셋, 데이터로더 (bathch size를 32) 만들기
image_datasets = {
'train' : datasets.ImageFolder('/content/train/dataset', data_transforms['train'], target_transform = target_transforms),
'validation' : datasets.ImageFolder('/content/validation/images', data_transforms['validation'], target_transform = target_transforms)
}
dataloaders = {
'train' : DataLoader(
image_datasets['train'],
batch_size = 32,
shuffle = True
),
'validation' : DataLoader(
image_datasets['validation'],
batch_size = 32,
shuffle = False
)
}
print(len(image_datasets['train']), len(image_datasets['validation']))
🗨 Farfetchd, MrMime 폴더가 생성만 되어있고 폴더내부에 사진이 없어 에러가 발생할것이다 !
두 폴더에 파오리와 마임맨 두 포켓몬의 사진을 넣어주어야 합니다.
🔻 Batch 만큼 이미지를 출력 합니다.
# 1개의 batch만큼 이미지를 출력
imgs, labels = next(iter(dataloaders['train']))
fig, axes = plt.subplots(4,8,figsize=(20,10))
for img, label, ax in zip(imgs, labels, axes.flatten()):
ax.set_title(label.item())
ax.imshow(img.permute(1,2,0))
ax.axis('off')
🔻위에서 뽑아낸 이미지와 라벨일 제대로 적용되어 있는지 확인을 해봅시다.
# 클래스 이름 확인하기
# image_datasets['train'].classes # 이름 전체뽑기
image_datasets['train'].classes[51]
Train의 클래스에 존재 하는 라벨로 포켓몬에 이름을 확인 하기
51번의 포켓몬은 영어 이름 "Haunter" 로 맞게 잘 나오네요
🔻사전 학습된 EfficientNetB4 모델 사용하기
# 사전 학습된 EfficientNetB4 모델 사용하기
model = models.efficientnet_b4(weights = 'IMAGENET1K_V1').to(device)
print(model)
🔻모델 만들기
# 모델 만들기
for param in model.parameters():
param.requires_grad = False
model.classifier = nn.Sequential(
nn.Linear(1792, 512),
nn.ReLU(),
nn.Linear(512, 149)
).to(device)
print(model)
🔻학습 시키기 ༼ つ ◕_◕ ༽つ[시간 오래 걸림]
# 학습시키기
optimizer = optim.Adam(model.classifier.parameters(), lr = 0.001)
epochs = 10
for epoch in range(epochs):
for phase in ['train', 'validation']:
if phase == 'train':
model.train()
else :
model.eval()
sum_losses = 0
sum_accs = 0
for x_batch, y_batch in dataloaders[phase]:
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
y_pred = model(x_batch)
loss = nn.CrossEntropyLoss()(y_pred, y_batch)
if phase == 'train':
optimizer.zero_grad()
loss.backward() #역전파
optimizer.step()#기울기초기화
# 배치단위 loss 저장
sum_losses = sum_losses + loss.item()
# 배치단위 정확도 저장
y_prob = nn.Softmax(1)(y_pred) # Softmax(1): Softmax 함수가 두 번째 차원(axis)에 대해 작동함.
# argmax(): 가장 큰 확률을 가지는 클래스의 인덱스를 추출
# axis=1: 두 번째 차원에서 최댓값을 찾음.
y_pred_index = torch.argmax(y_prob, axis=1)
acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100 # 백분율
# 정확도(acc): 실제레이블(y_batch)과 예측결과(y_pred_index)를 비교하여 예측된 데이터 포인트의
비율을 계산. 레이블과 예측 결과를 비교한 결과는 Boolean형태의 텐서임.
sum_accs = sum_accs + acc.item()
avg_loss = sum_losses / len(dataloaders[phase])
avg_acc = sum_accs / len(dataloaders[phase])
print(f'{phase:10s}: Epoch {epoch+1:4d}/{epochs}, Loss: {avg_loss:.4f}, Accuracy: {avg_acc:.2f}%')
🔻학습된 모델 저장하기
# 학습된 모델파일 저장하기
torch.save(model.state_dict(), 'model.h5')
🔻학습된 모델 불러오기 [불러와서 다시만들기]
# 빈 efficientnet_b4()모델 생성
model = models.efficientnet_b4().to(device)
# 모델 만들기
for param in model.parameters():
param.requires_grad = False
# 모델 수정하기
model.classifier = nn.Sequential(
nn.Linear(1792, 512),
nn.ReLU(),
nn.Linear(512, 149)
).to(device)
# 빈 모델에 저장된 모델 불러오기
model.load_state_dict(torch.load('model.h5'))
🔻이미지를 넣어 테스트 해보기
# 테스트(validation에 있는 2종의 포켓몬을 통해 분류 테스트 확률 출력해보기 )
# 테스트 해보기
from PIL import Image
# 학습용(train)말고 validation안에 있는 이미지를 사용한다.
img1 = Image.open('/content/validation/Squirtle/0.jpg')
img2 = Image.open('/content/validation/Mew/0.jpg')
# 어떤 사진인지 확인해보기(안해도 상관은 없음)
fig, axes = plt.subplots(1,2,figsize=(12,6))
axes[0].imshow(img1)
axes[0].axis('off')
axes[1].imshow(img2)
axes[1].axis('off')
plt.show()
🔻 테스트를 위한 이미지 사이즈 맞추기
# 테스트를 위해 사이즈 변경하기
img1_input = data_transforms['validation'](img1)
img2_input = data_transforms['validation'](img2)
print(img1_input.shape)
print(img2_input.shape)
test_batch = torch.stack([img1_input, img2_input])
test_batch = test_batch.to(device)
test_batch.shape
🔻예측
y_pred = model(test_batch)
y_pred
y_prod = nn.Softmax(1)(y_pred)
y_prod
probs, indices = torch.topk(y_prob, k=3, axis = -1)
probs = probs.cpu().data.numpy()
indices = indices.cpu().data.numpy()
print(probs)
print(indices)
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].set_title('{:.2f}% {}, {:.2f}% {}, {:.2f}% {}'.format(
probs[0, 0] * 100, image_datasets['validation'].classes[indices[0, 0]],
probs[0, 1] * 100, image_datasets['validation'].classes[indices[0, 1]],
probs[0, 2] * 100, image_datasets['validation'].classes[indices[0, 2]]
))
axes[0].imshow(img1)
axes[0].axis('off')
axes[1].set_title('{:.2f}% {}, {:.2f}% {}, {:.2f}% {}'.format(
probs[1, 0] * 100, image_datasets['validation'].classes[indices[1, 0]],
probs[1, 1] * 100, image_datasets['validation'].classes[indices[1, 1]],
probs[1, 2] * 100, image_datasets['validation'].classes[indices[1, 2]]
))
axes[1].imshow(img2)
axes[1].axis('off')
plt.show()
👀 살짝 과적합의 느낌이긴 합니다.....
728x90
'개발 > 머신러닝-딥러닝' 카테고리의 다른 글
2023.06.15 파이토치로 구현한 선형회귀 (0) | 2023.07.06 |
---|---|
2023.06.15 파이토치로 구현한 논리 회귀 (0) | 2023.07.06 |
2023.06.20 딥러닝의 전이학습(에일리언) (0) | 2023.06.21 |
2023.06.16 딥러닝의 CNN기초 (0) | 2023.06.20 |
2023.06.16 딥러닝의 활성화 함수 (1) | 2023.06.16 |
댓글