본문 바로가기
파이토치

[딥러닝 파이토치 교과서] 합성곱 신경망2

by 나연하야 2023. 5. 28.

6.1 이미지 분류를 위한 신경망

6.1.1 LeNet-5

  • LeNet-5는 합성곱과 다운 샘플링(혹은 풀링)을 반복적으로 거치면서 마지막에 완전연결층에서 분류를 수행함

 

이미지 데이터 전처리

  • transforms.RandomResizedCrop: 입력 이미지를 주어진 크기로 조정
  • transforms.RandomHorizontalFlip: 이미지를 수평 반전
  • transforms.ToTensor: torchvision 메서드는 이미지를 읽을 때 파이썬 이미지 라이브러리인 PIL을 사용해서 이미지 범위가 [0, 255], 배열의 차원이 높이*너비*채널 수로 표현됨. 이후 효율적인 연산을 위해 torch.FloatTensor 배열로 바꾸는데 픽셀의 값의 범위는 [0, 1] 사이가 되고, 차원의 순서도 채널 수*높이*너비로 바꾸어야 함
  • transforms.Normalize: 각 채널별 평균과 표준편차에 맞는 정규화
  • __call__ 함수는 클래스를 호출할 수 있도록 하는 메서드임. __init__은 인스턴스 초기화를 위해 사용한다면 __call__은 인스턴스가 호출되었을 때 실행됨 -> '코드 6-2'를 보면 class 안에 이미 __init__이 사용되었음!

 

이미지 데이터셋을 불러온 후 훈련, 검증, 테스트로 분리

  • os.path.join: 경로와 파일명을 결합하거나 분할된 경로를 하나로 합치고 싶을 떄 사용함

 

테스트 데이터셋 이미지 확인 함수

  • os.path.normpath: 경로를 정규화함(./.. 등의 구분자 제거)

os.path 사용법: 파이썬 os.path 모듈 · Codelog (yeo0.github.io)

 

파이썬 os.path 모듈

파이썬 os.path 모듈

yeo0.github.io

  • split(os.sep): 경로를 / 혹은 \를 기준으로 분할할 떄 사용
    • 예를 들어, c:/temp/user/a.jpg라는 경로가 있을 때 split(os.sep)를 적용하면 ['c:', 'temp', 'user', 'a.jpg']로 분할되고, split(os.sep)[-2]는 'user'가 반환됨

 

이미지 데이터셋 클래스 정의

  • 데이터셋 크기가 클 수 있으므로 __init__에서 전체 데이터를 읽어오는 것이 아니라 경로만 저장해 놓고, __getitem__ 메서드에서 이미지를 읽어옴

 

데이터로더 정의

  • 파이토치의 데이터로더는 배치 관리를 담당함(한 번에 모든 데이터를 불러오면 메모리에 부담을 줄 수 있기 때문에 데이터를 그룹으로 쪼개서 조금씩 불러옴)

 

모델의 네트워크 클래스

  • super(LeNet, self).__init__() 사용 이유: nn.Module의 변수들을 상속받기 위해(사용하지 않으면 에러남)

[Pytorch] nn.module을 상속받을 때 super().__init__()을 하는 이유 — Hello World! (tistory.com)

 

[Pytorch] nn.module을 상속받을 때 super().__init__()을 하는 이유

파이토치에서 클래스로 Layer나 Model을 구현해주면 항상 생성자에서 super(class이름, self).__init__()을 입력해줍니다. 왜 이것을 입력해야 하는지 궁금하여 알아보았습니다. super().__init__()이 없다면? im

cnu-jinseop.tistory.com

 

옵티마이저와 손실 함수 정의

  • optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
    • 경사하강법으로 모멘텀 SGD를 사용함(SGD에 관성이 추가된 것으로 매번 기울기를 구하지만 가중치를 수정하기 전에 이전 수정 방향(+, -)을 참고하여 같은 방향으로 일정한 비율만 수정되게 하는 방법)
    • 첫 번째 파라미터로 경사하강법을 통해 업데이트하고자 하는 파라미터를 입력하며, 여기서는 가중치와 바이어스가 됨
    • 세 번째 파라미터는 흔들림을 줄여주는 매개변수임

 

모델의 파라미터와 손실 함수를 CPU에 할당

  • 모델의 파라미터와 손실 함수에 CPU나 GPU 할당해야함

 

모델 학습 함수 정의

  • optimizer.zero_grad(): 역전파 단계를 실행하기 전에 기울기(gradient)를 0으로 초기화
  • loss.backward(): 모델의 학습 가능한 모든 파라미터에 대해 기울기를 계산
  • optimizer.step(): 파라미터 갱신

 

모델 테스트를 위한 함수 정의

  • torch.unsqueeze: 텐서에 차원을 추가할 때 사용(차원이 추가될 위치도 설정할 수 있음)
  • F.softmax(outputs, dim=1)[:, 1].tolist()
    • F.softmax(outputs, dim=1): softmax를 적용하여 각 행의 합이 1이 되도록 함
    • [:, 1]: 모든 행에서 두 번째 칼럼을 가져옴

 

6.1.2 AlexNet

  • AlexNet은 합성곱층 총 다섯 개와 완전연결층 세 개로 구성되어 있으며, 맨 마지막 완전연결층은 카테고리 1000개를 분류하기 위해 소프트맥스 활성화함수를 사용하고 있음
  • 전체적으로 보면 GPU 두 개를 기반으로 한 병렬 구조인 점을 제외하면 LeNet-5와 크게 다르지 않음
  • GPU-1에서는 주로 컬러와 상관없는 정보를 추출하기 위한 커널이 학습되고, GPU-2에서는 주로 컬러와 관련된 정보를 추출하기 위한 커널이 학습됨

 

AlexNet 모델 네트워크 정의

  • nn.ReLU(inplace=True): inplace=True는 연산에 대한 결괏값을 새로운 변수에 저장하는 것이 아닌 기존 데이터를 대체하는 것을 의미함
  • AdaptiveAvgPool2d: AvgPool2d에서는 풀링에 대한 커닐 및 스트라이드 크기를 정의해야 함. 반면, AdaptiveAvgPool2d는 풀링 작업이 끝날 때 필요한 출력 크기를 정의함

 

6.1.3 VGGNet

  • 합성곱층의 파라미터 수를 줄이고 휸련 시간을 개선하려고 탄생함
  • 깊이의 영향만 최대한 확인하고자 합성곱층에서 사용하는 필터/커널의 크기를 가장 작은 3*3으로 고정함
  • VGG16에는 파라미터가 총 1억 3300만 개가 사용되며, 모든 합성곱 커널의 크기는 3*3, 최대 풀링 커널의 크기는 2*2, 스트라이드는 2임(64개의 224*224 특성맵이 생성됨)

 

필요한 라이브러리 호출

  • copy: 객체 복사를 위해 사용함
    • copy.copy(): 얇은 복사(shallow copy)
    • copy.deepcopy(): 깊은 복사(deep copy) -> 원래의 값은 그대로

 

VGG 계층 정의

  • assert c == 'M' or instance(c, init): c가 'M'이 아니거나 init가 아니라면 오류가 발생

 

VGG11 사전 훈련된 모델 정의

  • VGG 모델은 사전 훈련된 모델이므로 코드 한두 줄로 쉽게 사용할 수 있음
    • vgg11_bn은 VGG11 기본 모델에 배치 정규화가 적용된 모델을 사용하겠다는 의미
import torchvision.models as models
pretrained_model = models.vgg11_bn(pretrained=True)

 

테스트 데이터셋을 이용한 모델의 예측 확인 함수

  • y_prob.agrmax(1, keepdim=True): 가장 큰 값의 인덱스를 찾을 때 사용
    • 첫 번째 파라미터는 행(axis=0) 또는 열(axis=1) 중 어떤 것에 따라 가장 큰 값을 찾을지 설정
    • 두 번째 파라미터는 출력 텐서를 입력과 동일한 크기로 유지하겠다는 의미
  • torch.cat: 텐서를 연결할 때 사용

 

예측 중에서 정확하게 예측한 것을 추출

  • zip(): 여러 개의 리스트(혹은 튜플)을 합쳐서 새로운 튜플 타입으로 반환
a=[1, 2, 3]
b=['a', 'b', 'c']

for x, y in zip(a, b):
  print(x, y)
1 a
2 b
3 c
  • correct_examples.sort(reverse=True, key=lambda x: torch.max(x[2], dim=0).values)
    • sort를 통해 데이터를 정렬할 수 있는데 key 값을 가지고 정렬함
    • 람다는 일종의 함수(일반적으로 함수는 def 함수명()처럼 사용하지만 람다는 다음과 같이 함수명 없이 사용 가능하지만 저장된 변수가 없기 때문에 재사용이 불가능)

 

이미지 출력을 위한 전처리

  • 메서드에 _ 표시가 있다면(예를 들어 torch.clamp_()) 기존의 메모리 공간에 있는 값을 새로운 값으로 대체하겠다는 의미

 

모델이 정확하게 예측한 이미지 출력 함수

  • image.permute는 축을 변경할 때 사용(예를 들어, x.permute(1, 0)이면 차원 0과 1을 바꿈)

 

6.1.4 GoogLeNet

  • GoogLeNet은 주어진 하드웨어 자원을 최대한 효율적으로 이용하면서 학습 능력은 극대화할 수 있는 깊고 넓은 신경망
  • 깊고 넓은 신경망을 위해 인셉션 모듈을 추가함
    • 입셉션 모듈에서는 특징을 효율적으로 추출하기 위해 1*1, 3*3, 5*5의 합성곱 연산을 각각 수행함 -> 같은 물체라도 서로 다른 비율로 위치할 수 있으므로 여러 종류의 필터를 사용하여 학습하는 것이 효율적임!
    • 관련성이 높은 노드끼리만 연결하는 희소연결을 통해 연산량을 줄이고, 과적합을 해결함
    • 심층 신경망의 아키텍처에서 계층이 넓고(뉴런이 많고) 깊으면(계층이 많으면) 인식률을 좋아지지만, 과적합이나 기울기 소멸 문제를 비롯한 학습 시간 지연과 연산 속도 등의 문제가 있음 -> 인셉션을 통해 이와 같은 문제를 해결함

 

 

GoogleNet (인셉션 모듈/평균 풀링/보조 분류기)

구글넷은 2014년 이미지넷 인식 대회(ILSVRC14)에서 VGG를 이기고 우승한 알고리즘이다. 구글넷은 신경망 내부 컴퓨터 자원의 활용을 높이기 위해 계산량을 일정하게 유지하면서 신경망의 깊이와 폭

ardino.tistory.com

 

[DL] 1x1 convolution은 무엇이고 왜 사용할까?

convloution(합성곱)은 input 데이터에 필터를 적용해 원소별 계산(합성곱)을 수행하여 출력하는 방법입니다. convolution에 대한 자세한 설명은 링크에서 확인할 수 있습니다.

euneestella.github.io

 

6.1.5 ResNet

  • ResNet의 핵심은 깊어진 신경망을 효과적으로 학습하기 위해 레지듀얼 개념을 고안한 것(기울기 소멸 문제를 방지)
  • 일반적으로 신경망 깊이가 깊어질수록 딥러닝 성능은 좋아질 것 같지만, 실상은 그렇지 않았음

  • 기본 블록과 병목 블록
    • 아래의 ResNet34는 기본 블록을 사용하며, ResNet50은 병목 블록을 사용함(기본 블록의 경우 파라미터 수가 39.3516M인 반면 병목 블록의 경우는 6.9635M임)
    • ResNet50에서는 3*3 합성곱층 앞뒤로 1*1 합성곱층이 붚어 있는데, 1*1 합성곱층의 채널 수를 조절하면서 차원을 줄였다 늘리는 것이 가능하기 떄문에 파라미터 수를 줄임

  • 아이덴티티 매핑
    • 입력 x가 어떤 함수를 통과하더라도 다시 x라는 형태로 출력되도록 함
  • 다운샘플
    • 특성맵 크기를 줄이기 위한 것으로 풀링과 같은 역할을 함
    • 아이덴티티 매핑을 위해서는 입력 데이터의 크기와 출력 데이터의 크기가 동일해야 하는데 동일하지 않을 경우 다운샘플 기법을 활용함
    • 참고) 입력과 출력의 차원이 같은 것을 아이덴티티 블록이라고 하며, 입력 및 출력 차원이 동일하지 않고 입력의 차원을 출력에 맞추어 변경해야 하는 것을 프로젝션 숏컷 혹은 합성곱 블록이라고 함

 

6.2 객체 인식을 위한 신경망

  • 객체 인식 = 여러 가지 객체에 대한 분류 + 객체의 위치 정보를 파악하는 위치 검출
  • 1단계 객체 인식은 분류와 위치 검출을 동시에 행하는 방법이고, 2단계 객체 인식은 두 문제를 순차적으로 행하는 방법임

6.2.1 R-CNN

  • 예전의 객체 인식 알고리즘들은 슬라이딩 윈도우 방식(일정한 크기를 가지는 윈도우로 이미지의 모든 영역을 탐색하면서 객체를 검출해내는 방식)을 사용함
  • 현재는 선택적 탐색 알고리즘을 적용한 후보 영역을 많이 사용함
  • R-CNN은 이미지 분류를 수행하는 CNN과 이미지에서 객체가 있을 만한 영역을 제안해주는 후보 영역 알고리즘을 결합한 알고리즘

  • 선택적 탐색
    • 선택적 탐색은 객체 인식이나 검출을 위한 가능한 후보 영역을 알아내는 방법임
    • 선택적 탐색은 분할 방식을 이용하여 시드를 선정하고, 그 시드에 대한 완전 탐색을 적용함
      • 1단계. 초기 영역 생성: 각각의 객체가 영역 한 개에 할당될 수 있도록 많은 초기 영역을 생성함
      • 2단계. 작은 영역의 통합: 1단계에서 영역 여러 개로 나눈 것들을 비슷한 영역으로 통합함
      • 3단계. 후보 영역 생성: 2단계에서 통합된 이미지들을 기반으로 바운딩 박스 추출
  • 단점 -> 이러한 문제를 해결하기 위해 Fast R-CNN
    • 세 단계의 복잡한 학습 과정
    • 긴 학습 시간과 대용량 저장 공간
    • 객체 검출 속도 문제

6.2.2 공간 피라미드 풀링

  • 기존 CNN 구조들은 모두 완전연결층을 위해 입력 이미지를 고정된 크기로 자르거나 비율을 조정했음
  • 이렇게 하면 물체의 일부분이 잘리거나 본래의 생김새와 달라지는 문제점이 생겼으며, 이를 해결하기 위해 공간 피라미드 풀링을 도입함
  • 공간 피라미드 풀링은 입력 이미지의 크기에 관계업이 합성곱층을 통과시키고, 완전연결층에 전달되기 전에 특성 맵들을 동일한 크기로 조절해주는 풀링층을 적용하는 기법임

 

6.2.3 Fast R-CNN

  • R-CNN은 바운딩 박스마다 CNN을 돌리고, 분류를 위한 긴 학습 시간이 문제임
  •  Fast R-CNN은 R-CNN의 속도 문제를 개션하려고 RoI 풀링을 도입함
    • RoI 풀링은 크기가 다른 특성 맵의 영역마다 '스트라이드를 다르게' 최대 풀링을 적용하여 결괏값 크기를 동일하게 맞추는 방법임

 

6.2.4 Faster R-CNN

  • Fast R-CNN에 후보 영역 추출 네트워크를 추가한 것이 핵심임
    • 후보 영역 추출 네트워크는 특성 맵 N*N 크기의 작은 윈도우 영역을 입력으로 받고, 해당 영역에 객체의 존재 유무 판단을 위해 이진 분류를 수행하는 작은 네트워크를 생성함
    • 후보 영역 추출 네트워크는 이미지에 존재하는 객체들의 크기와 비율이 다양하기 때문에 고정된 N*N 크기의 입력만으로 다양한 크기와 비율의 이미지를 수용하기 어려운 단점이 있음 -> 이를 보완하기 위해 여러 크기와 비율의 레퍼런스 박스 k개를 미리 정의하고 각각의 슬라이딩 윈도우 위치마다 박스 k개를 출력하도록 설계함

 

6.3 이미지 분할을 위한 신경망

  • 이미지 분할은 신경망을 훈련시켜 이미지를 픽셀 단위로 분할하는 것
  • 즉, 이미지를 픽셀 단위로 분할하여 이미지에 포람된 객체를 추출함

 

6.3.1 완전 합성곱 네트워크

  • 완전연결층의 한계는 고정된 크기의 입력만 받아들이며(모든 입력 데이터의 크기가 동일해야 한다는 의미), 완전연결층을 거친 후에는 위치 정보가 사라진다는 것임 -> 이러한 문제를 해결하기 위해 완전연결층을 1*1 합성곱으로 대체하는 것이 완전 합성곱 네트워크

 

6.3.2 합성곱 & 역합성곱 네트워크

  • 완전 합성곱 네트워크의 단점 -> 이를 해결하기 위해 합성곱 & 역합성곱 네트워크 도입
    • 여러 단계의 합성곱층과 풀링층을 거치면서 해상도가 낮아짐
    • 낮아진 해상도를 복원하기 위해 업 샘플링 방식(최종 이미지의 크기가 입력 이미지의 크기와 같도록 하는 것)을 사용하기 때문에 이미지의 세부 정보들을 잃어버리는 문제가 발생함
  • 역합성곱은 CNN의 최종 출력 결과를 원래의 입력 이미지와 같은 크기로 만들고 싶을 때 사용
  • CNN에서 합성곱층은 합성곱을 사용하여 특성 맵 크기를 줄이지만 역합성곱은 특성 맵 크기를 증가시키는 방식으로 동작

 

6.3.3 U-Net

  • 바이오 메디컬 이미지 분할을 위한 합성곱 신경망
  • 특징
    • 속도가 빠름: 검증이 끝난 패치(이미지 인식 단위)는 건너뛰기 때문에 속도가 빠름
    • 트레이드오프에 빠지지 않음: 넓은 범위의 이미지를 인식하는 데 뛰어날 뿐만 아니라 지역화에도 우수함
      • U-Net은 수축 경로와 확장 경로로 구성되어 있음(수축 경로는 컨텍스트를 포착하며, 확장 경로는 특성 맵을 업 샘플링하고 수축 경로에서 포착한 특성 맵의 컨텍스트와 결합하여 정확한 지역화를 수행함)

 

6.3.4 PSPNet

  • 완전연결층의 한계를 극복하기 위해 피라미드 풀링 모듈을 추가했음

6.3.5 DeepLabv3/DeepLab3+

  • 완전연결층의 단점을 보완하기 위해 Atrous 합성곱을 사용하는 네트워크
    • Atrous 합성곱은 필터 내부에 빈 공간을 둔 채로 작동함(얼마나 많은 빈 공간을 가질지 결정하는 파라미터로 rate가 있음)
    • 보통 이미지 분할에서 높은 성능을 내려면 수용 영역의 크기가 중요한데, Atrous 합성곱을 활용하면 파라미터 수를 늘리지 않으면서 수용 영역을 크게 키울 수 있기 때문에 이미지 분할 분야에서 많이 사용함

 

출처: 서지영(2022). 딥러닝 파이토치 교과서. p245-p357.