파이토치 사용법 정리

WooSeongkyun·2023년 4월 28일
0

파이토치 사용법

1. 데이터 불러오기 / 전처리

  • 전처리 함수 transformers 정의
  • 불러오기 함수 CustomedDataset 정의
  • torch용으로 전처리하는 함수 DataLoader 정의

2. 신경망 정의

  • 신경망 제작/ 불러오기
  • 신경망 수정하기

3. optimizer 정의

  • 사용할 optimizer 정의
  • 파라미터 업데이트될 레이어 정하기

4. 평가

  • criterion (loss function) 정하기
  • loss외 평가요소(예: 정확도) 정하기
  • loss /기타 평가요소를 train 과 그 외로 나눠 계산하고 파라미터 업데이트하는 함수 정의하기

0. 기본설정하기(선택사항)

  • BATCH_SIZE, LR, EPOCH 등을 미리 설정한다

1. 데이터 불러오기

  1. 데이터 경로 읽기 함수
    • 데이터가 어디에 저장되어 있는지 각 데이터에 대한 경로를 읽는다
    • path_lst= glob.glob(root_path+(train|val)+'/*/*')를 통하여 데이터를 불러올 수 있다
  2. 전처리 함수
    • torchvision.transforms 혹은 albumentation.transforms를 활용한다
    • 왜 전처리를 하는가?
      - 각자 크기가 다른 이미지를 학습을 위해 동일한 크기로 변환
      - 데이터 증강 data augmentation을 통해 학습력을 높이려고
    • 만약 전처리할 경우 이미지 변형>텐서변환>Normalize 의 순을 거친다. 변형을 안하는 경우 transformers.ToTensor()만 시행해도 된다
  3. 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 #train or val 지정

    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 
        
  • 	- 예시2
#상속해주는 모듈 :torch.uitls.data.Dataset
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
  1. torch.utils.data.DataLoaderDataLoader 제작
    • 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에서 입력 데이터의 크기가 ihi _{h}, kernel_size=khk _{h},padding= php _{h}, stride= shs _{h} 인경우 출력 데이터의 크기는 oh=Floor(ih+2phkhsh+1)o _{h}=Floor(\displaystyle\frac{i _{h}+2p _{h}-k _{h}}{s _{h}}+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']
#파라미터의 크기 살펴보기 (in_channel,out_channel,kernal_size,kernal_size)의 크기를 갖는다
# for name, param in net.named_parameters():
#     print(name)
#     print(param.shape)
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

#params_to_update의 내용 살펴보기
print('----------------------')
print(params_to_update)

#최적화 기법 설정 4096 X 2 +2의 텐서
optimizer= optim.SGD(params=params_to_update , lr =0.001,momentum=0.9)

4. 평가

  • 다음과 같은 일을 각 에포크 마다 동시에 처리한다
    1. 손실함수값을 계산하고, backpropagation을 하고, 모델을 업데이트 한다
    2. 손실함수와 기타 평가 척도를 출력한다
  • optional
    - validation의 손실함수가 가장 작을때의 모델을 저장한다
    - 손실함수와 기타 평가 척도의 history를 저장한다
    - optimizer를 EPOCH마다 변하는 변수로 지정한다
profile
안녕하세요!

0개의 댓글