일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- VSCode
- Python 특징
- BOXPLOT
- namedtuple
- ndarray
- groupby
- 정규분포 MLE
- 최대가능도 추정법
- Array operations
- Comparisons
- type hints
- Python
- seaborn
- Numpy data I/O
- 딥러닝
- dtype
- 카테고리분포 MLE
- pivot table
- Operation function
- 부스트캠프 AI테크
- linalg
- scatter
- Python 유래
- subplot
- Numpy
- python 문법
- boolean & fancy index
- 표집분포
- unstack
- 가능도
- Today
- Total
또르르's 개발 Story
[13-2] Colab에서 DataSet 다루기 (강아지 DataSet) 본문
1️⃣ 설정
아래 모듈들을 import 합니다.
import tarfile
import os
import shutil
import glob
import numpy as np
import matplotlib.pyplot as plt
from torch import nn, optim
from torch.autograd import Variable
colab에서는 모듈과 데이터를 저장할 수 있는 디스크도 제공하기 때문에 os module을 사용하여 현재 위치를 알 수 있습니다.
>>> os.getcwd() # os 현재 위치
'/content'
강아지 image를 보여주는 imshow 함수를 작성합니다. (나중에 tensor image를 보여줄 때 사용)
def imshow(image, ax=None, title=None, normalize=True):
"""Imshow for Tensor."""
if ax is None:
fig, ax = plt.subplots()
image = image.numpy().transpose((1, 2, 0))
if normalize:
mean = np.array([0.485, 0.456, 0.406])
std = np.array([0.229, 0.224, 0.225])
image = std * image + mean
image = np.clip(image, 0, 1)
ax.imshow(image)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.tick_params(axis='both', length=0)
ax.set_xticklabels('')
ax.set_yticklabels('')
return ax
2️⃣ 데이터 처리
1) 다운로드 & 압축 풀기
!wget 명령어를 사용해 colab disk에 다운로드합니다.
!wget http://vision.stanford.edu/aditya86/ImageNetDogs/images.tar
# 현재 directory 기준으로 tar파일을 다운로드(colab이 실행되는 곳에 다운로드)
/Images라는 폴더를 만들어줍니다.
TARGET_PATH = "Images" # images.tar는 images 폴더에 사진이 들어가기 때문에
if os.path.exists(TARGET_PATH): # 만약 dir 이름이 있다면 삭제
shutil.rmtree(TARGET_PATH)
tar file의 압축을 풉니다.
fname = "images.tar" # tar 파일의 압축을 푸는 것
tar = tarfile.open(fname, "r:tar")
tar.extractall()
tar.close()
tar file을 푼 후, 이미지 개수를 확인할 수 있습니다.
>>> len(os.listdir(TARGET_PATH))
120
Image file에 들어가 있던 파일들은 모두 '-'가 들어가 있어서 이름을 다시 수정합니다.
for dir_name in os.listdir(TARGET_PATH): # jpg이름에는 '-'가 들어가 있는데 이름을 다시 수정
breed_name = dir_name.split("-")[-1].lower()
source_dir = os.path.join(TARGET_PATH, dir_name)
target_dir = os.path.join(TARGET_PATH, breed_name)
shutil.move(source_dir, target_dir)
/로 구분된 강아지 이름을 나눠서 dataset list에 넣습니다.
dataset = []
for filepath in glob.iglob(f'{TARGET_PATH}/**/*.jpg', recursive=True): #image 폴더에 있는 모든 jpg파일
breed_name = filepath.split("/")[1] # 강아지이름만
dataset.append([filepath, breed_name])
dataset = np.array(dataset)
>>> print(dataset)
[['Images/sealyham_terrier/n02095889_1445.jpg' 'sealyham_terrier']
['Images/sealyham_terrier/n02095889_673.jpg' 'sealyham_terrier']
['Images/sealyham_terrier/n02095889_5212.jpg' 'sealyham_terrier']
...
['Images/rhodesian_ridgeback/n02087394_10014.jpg' 'rhodesian_ridgeback']
['Images/rhodesian_ridgeback/n02087394_531.jpg' 'rhodesian_ridgeback']
['Images/rhodesian_ridgeback/n02087394_3673.jpg' 'rhodesian_ridgeback']]
2) Train data와 Test data로 나누기
Sklearn module을 사용해서 나눕니다.
from sklearn.model_selection import train_test_split # 학습 데이터와 test data로 나눔
train_image, test_image, train_target, test_target = train_test_split(dataset[:,0], dataset[:,1], stratify=dataset[:,1])
Train image shape을 확인해보면 아래와 같습니다.
>>> train_image.shape
(15435,)
>>> test_image
array(['Images/beagle/n02088364_17474.jpg',
'Images/otterhound/n02091635_4175.jpg',
'Images/schipperke/n02104365_3587.jpg', ...,
'Images/coated_retriever/n02099429_1465.jpg',
'Images/norfolk_terrier/n02094114_2394.jpg',
'Images/coated_wheaten_terrier/n02098105_3609.jpg'], dtype='<U74')
pandas로 강아지 종의 비율들을 확인해볼 수 있습니다.
import pandas as pd
pd.Series(train_target).value_counts() / len(train_target) # train data의 강아지 비율들
coated_retriever 0.014707
maltese_dog 0.012245
afghan_hound 0.011597
scottish_deerhound 0.011273
irish_wolfhound 0.010625
...
golden_retriever 0.007256
groenendael 0.007256
welsh_springer_spaniel 0.007256
pekinese 0.007256
redbone 0.007191
Length: 119, dtype: float64
import pandas as pd
pd.Series(test_target).value_counts() / len(test_target)
coated_retriever 0.014772
maltese_dog 0.012245
afghan_hound 0.011662
scottish_deerhound 0.011273
samoyed 0.010690
...
dhole 0.007191
pekinese 0.007191
eskimo_dog 0.007191
affenpinscher 0.007191
border_collie 0.007191
Length: 119, dtype: float64
Train data와 Test data를 편하게 사용하기 위해서는 Image 폴더에 있는 전체 data를 train data folder와 test data folder로 나눠야 합니다.
DATA_PATH = "dataset" # train folder와 test folder를 나눠서 사용
if os.path.exists(DATA_PATH):
shutil.rmtree(DATA_PATH)
if not os.path.exists(DATA_PATH):
os.mkdir(DATA_PATH)
os.makedirs(os.path.join(DATA_PATH, "train"))
os.makedirs(os.path.join(DATA_PATH, "test"))
for breed_name in set(test_target):
os.makedirs(os.path.join(DATA_PATH, "train", breed_name))
os.makedirs(os.path.join(DATA_PATH, "test", breed_name))
import shutil
for filepath, taregt_dir in zip(train_image.tolist(), train_target.tolist()):
filename = filepath.split("/")[-1]
source_path = filepath
target_dir = os.path.join(DATA_PATH, "train", taregt_dir, filename)
shutil.copy(source_path, target_dir)
for filepath, taregt_dir in zip(test_image.tolist(), test_target.tolist()):
filename = filepath.split("/")[-1]
source_path = filepath
target_dir = os.path.join(DATA_PATH, "test", taregt_dir, filename)
shutil.copy(source_path, target_dir)
3) Image 출력하기
target_dir에 있는 image를 열어보면 하나가 출력됩니다.
from PIL import Image
im = Image.open(target_dir)
im
또는, 랜덤으로 10개를 출력하기 위해 matplotlib.image를 불러와서 사용이 가능합니다.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
def process(filename: str=None) -> None:
"""
View multiple images stored in files, stacking vertically
Arguments:
filename: str - path to filename containing image
"""
image = mpimg.imread(filename)
# <something gets done here>
plt.figure()
plt.imshow(image)
idx = np.random.choice(len(dataset), 10)
images = dataset[:, 0][idx]
for file in images:
process(file)
print(dataset[:, 1][idx])
3️⃣ Data augumentation
Data augumentation은 모델의 학습능률을 올리기 위해 데이터를 자르고, 붙이고, 변형하는 방식으로 데이터를 늘리는 방법입니다.
# data 뻥튀기 data augumentation
from torchvision import datasets, transforms, models
# TODO: Define transforms for the training data and testing data
train_transforms = transforms.Compose([transforms.RandomRotation(30), # image rotation
transforms.RandomResizedCrop(224), # resize
transforms.RandomHorizontalFlip(), # 수평으로 만듦
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
test_transforms = transforms.Compose([transforms.Resize(255), # test할 때는 center에서 224*224 모델로 만듦
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
DATASET_PATH = "dataset"
# Pass transforms in here, then run the next cell to see how the transforms look
train_data = datasets.ImageFolder(DATASET_PATH + '/train', transform=train_transforms)
# pytorch에서 datasets.imageFolder을 하면 자동으로 폴더 안에 있는 image와 label을 잡아줌(위의 transforms를 폴더 안 jpg에 적용)
test_data = datasets.ImageFolder(DATASET_PATH + '/test', transform=test_transforms)
따라서 train_data와 test_data를 보면 Transform이 어떻게 되는지를 볼 수 있습니다.
>>> train_data
Dataset ImageFolder
Number of datapoints: 15435
Root location: dataset/train
StandardTransform
Transform: Compose(
RandomRotation(degrees=[-30.0, 30.0], resample=False, expand=False)
RandomResizedCrop(size=(224, 224), scale=(0.08, 1.0), ratio=(0.75, 1.3333), interpolation=PIL.Image.BILINEAR)
RandomHorizontalFlip(p=0.5)
ToTensor()
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
)
>>> test_data
Dataset ImageFolder
Number of datapoints: 5145
Root location: dataset/test
StandardTransform
Transform: Compose(
Resize(size=255, interpolation=PIL.Image.BILINEAR)
CenterCrop(size=(224, 224))
ToTensor()
Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
)
4️⃣ DataLoader
PyTorch에서는 DataLoader를 사용해서 data를 generation 할 수 있습니다.
import torch
train_loader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True)
# dataLoader는 iterator 형태로 불러옴
test_loader = torch.utils.data.DataLoader(train_data, batch_size=32, shuffle=True)
iter()함수를 사용해서 4개의 image를 불러올 수 있습니다.
data_iter = iter(test_loader)
images, labels = next(data_iter)
fig, axes = plt.subplots(figsize=(10,4), ncols=4)
for ii in range(4):
ax = axes[ii]
imshow(images[ii], ax=ax, normalize=True) # 여기서 imshow는 위에서 선언한 imshow함수
'부스트캠프 AI 테크 U stage > 실습' 카테고리의 다른 글
[14-2] LSTM using PyTorch (0) | 2021.02.04 |
---|---|
[13-3] Google Image Data 다운로드 (0) | 2021.02.04 |
[13-1] CNN using PyTorch (0) | 2021.02.04 |
[12-2] Optimizers using PyTorch (0) | 2021.02.03 |
[11-3] MLP using PyTorch (0) | 2021.02.02 |