파이토치 사용법
1. 데이터 불러오기 / 전처리
- 전처리 함수
transformers
정의
- 불러오기 함수
CustomedDataset
정의
torch
용으로 전처리하는 함수 DataLoader
정의
2. 신경망 정의
3. optimizer
정의
- 사용할
optimizer
정의
- 파라미터 업데이트될 레이어 정하기
4. 평가
criterion
(loss function) 정하기
- loss외 평가요소(예: 정확도) 정하기
loss
/기타 평가요소를 train
과 그 외로 나눠 계산하고 파라미터 업데이트하는 함수 정의하기
0. 기본설정하기(선택사항)
BATCH_SIZE, LR, EPOCH
등을 미리 설정한다
1. 데이터 불러오기
- 데이터 경로 읽기 함수
- 데이터가 어디에 저장되어 있는지 각 데이터에 대한 경로를 읽는다
path_lst= glob.glob(root_path+(train|val)+'/*/*')
를 통하여 데이터를 불러올 수 있다
- 전처리 함수
torchvision.transforms
혹은 albumentation.transforms
를 활용한다
- 왜 전처리를 하는가?
- 각자 크기가 다른 이미지를 학습을 위해 동일한 크기로 변환
- 데이터 증강 data augmentation을 통해 학습력을 높이려고
- 만약 전처리할 경우 이미지 변형>텐서변환>Normalize 의 순을 거친다. 변형을 안하는 경우
transformers.ToTensor()
만 시행해도 된다
CustomedDataset
함수
- 필수 3개 요소
- __init__()
: 한 배치의 데이터 X,Y
, 그리고 전처리함수 transforms
를 받거나 한 이미지의 경로와 전처리함수 transforms
를 입력받는다.
- __len__()
: 한 배치의 배치사이즈를 확인시켜준다
- __getitem__()
: 한 배치의 전처리후 독립변수X_transformed
와 종속변수Y
를 반환해준다
- 예시 1
class Dataset(data.Dataset):
def __init__(self,file_list, transform=None, phase='train'):
self.file_list= file_list
self.transform = transform
self.phase= phase
def __len__(self):
return len(self.file_list)
def __getitem__(self,index):
img_path= self.file_list[index]
img= Image.open(img_path)
img_transformed= self.transform(img,phase=self.phase)
"""
이미지 라벨을 파일 이름에서 추출하기
각자 컴퓨터마다 경로가 다르므로 1.컴퓨터가 변경하거나 2.데이터셋이 달라지는 경우
변경이 필요함
"""
if self.phase== "train":
label= img_path[86:90]
elif self.phase == 'val':
label= img_path[84:88]
if label== "ants":
label=0
elif label == "bees":
label=1
return img_transformed, label
class CustomedDataset(torch.utils.data.Dataset):
def __init__(self,X,Y,transform=None):
self.X= X
self.Y=Y
self.transform= transform
def __len__(self):
return self.X.shape[0]
def __getitem__(self,idx):
x= self.X[idx]
if self.transform is not None:
x=self.transform(x)
y= self.Y[idx]
return x,y
torch.utils.data.DataLoader
로 DataLoader
제작
Batch_size
는 미리 제작해야한다
dataloaders_dict= {'train':train_dataloader,'val':val_dataloader}
과 같이 딕셔너리형에 저장해서 활용할 수 있다
2. 신경망 제작
- 기존에 있는 신경망 활용
- torchvision.models.신경망이름(pretrained= T or F)
를 통하여 널리 알려진 신경망 구조 및 파라미터값을 불러올 수 있다
- 신경망 제작 필수 요소
- class NetName(nn.Module)
- 신경망 클래스는 nn.Module
로 부터 성질을 상속받아야만 한다
- __init__()
- 신경망을 이루는 레이어들을 작성한다
- nn.Sequential()
을 활용하면, 여러 레이어를 하나의 블록으로 묶을 수 있다. 완성된 블록은 입력값 X
하나만 받을 수 있다
- nn.ModuleList()
는 블록 내 레이어들이 서로 forward
로 연결되어 있지 않고, 다만 모델엔 등록되어 있는다.(그냥 list로 레이어를 담아주면 모델에 등록되지 않아 파라미터 접근이 불가능함.)
- 레이어
- nn.BatchNorm2d()
는 output_channel
에 맞춘다
- nn.Conv2d
에서 입력 데이터의 크기가 ih, kernel_size=
kh,padding=
ph, stride=
sh 인경우 출력 데이터의 크기는 oh=Floor(shih+2ph−kh+1)
- forward()
- 각 레이어 혹은 블록들을 서로 연결한다
- CNN
에서 fc
로 넘어간다면 x= torch.flatten(x,start_dim=1)
를 해준다
- 만약 신경망 구조가 복잡하다면
class BlockName(nn.Module)
로 여러개의 블록을 만들고, 최종 신경망 클래스에 블록 클래스를 불러오는 형식으로 제작한다
3. 옵티마이저 정의와 전이학습
- 모델구조 살펴보기
- net.eval()
혹은 net.train()
을 하면 모델 구조가 출력된다.
- 단 이것은 원래 신경망이 inference를 할것인지 훈련을 할 것인지 결정하는 함수임
- 모델 수정하기
- net.classifier[6]=nn.Linear(in_features=4096, out_features=2, bias=True)
와 같이 특정 레이어를 인덱싱하여 다른 레이어로 변환할 수 있다
- 각 목적에 맞게끔 사전훈련된 모델의 마지막 층과 그 인근 층의 구조만 수정시킬 수 있는데, 이를 전이학습이라고 한다
- 옵티마이저 설정하기
- 학습시킬 파라미터 설정하기
- 전체를 학습시키고자 한다면 optim.OptimizerName()
에 model.parameters()
라 지정하면 된다
- 다음과 같이 학습시키고자 하는 파라미터만을 따로 떼내 require_grad=True
로 하고, 나머지는 False
로 할 수 있다.
params_to_update= []
update_param_names= ['classifier.6.weight','classifier.6.bias']
for name, param in net.named_parameters():
if name in update_param_names:
param.required_grad= True
params_to_update.append(param)
print(name)
else:
param.requires_grad=False
print('----------------------')
print(params_to_update)
optimizer= optim.SGD(params=params_to_update , lr =0.001,momentum=0.9)
4. 평가
- 다음과 같은 일을 각 에포크 마다 동시에 처리한다
1. 손실함수값을 계산하고, backpropagation을 하고, 모델을 업데이트 한다
2. 손실함수와 기타 평가 척도를 출력한다
- optional
- validation의 손실함수가 가장 작을때의 모델을 저장한다
- 손실함수와 기타 평가 척도의 history를 저장한다
- optimizer를 EPOCH마다 변하는 변수로 지정한다