본문 바로가기
IT 지식/인공지능_딥러닝

[논문] AlexNet

by 이민우 2021. 2. 27.
728x90
반응형

출처 : papers.nips.cc/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf

 

 

 

 

0. Abstract

Abstract of AlexNet

 

 ImageNet LSVRC-2010 대회에서 1000개의 클래스의 120만 고해상도 이미지를 분류를 위해 깊은 dnn을 훈련했다. 이 대회에서 테스트 데이터로 37.5%와 17.0%로 1등과 5등의 오류율을 달성했다.

 신경망은 6천만 개의 파라미터와 650,000 개의 뉴런, 몇몇은 3개의 max 풀링층과 연결된 5개의 합성곱층, 그리고 마지막은 softmax인 3개의 완전연결 층으로 구성되었다.

 학습을 빠르게 하기 위해 비 포화 뉴런과 GPU를 사용했으며, 오버피팅을 줄이기 위해 완전연결층에 최근 개발된 드롭아웃을 적용했다.

 해당 모델은 ILSVRC-2012 대회에서 이 모델의 변형을 사용해 15.3%의 오류율을 달성해 우승을 차지했다.

 

 

1. Introduction

Introduction of AlexNet

 성능 향상을 위해 더 큰 데이터셋을 모으고, 더 강력하게 모델을 학습시켰고, 오버피팅을 방지하기 위해 더 나은 기술들을 사용했다.

 

 최근까지의 데이터 셋 라벨들은 수 만개의 이미지 정도로 상대적으로 작았다. 이런 사이즈의 데이터셋들은 간단한 인식 작업을 잘 사용할 수 있었다. 하지만 실제 데이터셋들은 많은 변동성을 나타내기에, 이들을 인식하기 위해서는 훨씬 더 큰 훈련 셋을 사용해야 한다.

 

 수백만개의 이미지 속에서 수천 개의 객체들을 배우시 위해서는 더 큰 학습 능력을 가진 모델이 필요하다. CNN은 깊이와 폭을 변경하여 용량을 제어할 수 있고, 이미지의 특성 (통계의 정상성 및 픽셀 종속성의 국소성)에 대해 정확한 가정이 가능하다.

 

 하지만 CNN은 고해상도 이미지에 사용하기에 비용이 많이 들었다. 하지만 다행히 최신 GPU는 2D 합성곱의 최적화된 구현과 함께 큰 규모의 CNN의 훈련도 가능하며, ImageNet과 같은 최신 데이터셋은 심한 과적합 없이 모델을 교육할 수 있는 충불한 라벨이 포함되어 있다.

 

 해당 논문은 ILSVRC-2010, 2012 대회에서 현재까지 가장 큰 신경망을 학습시켰고, 가장 좋은 결과를 달성했다.

 2D 컨볼루션에 최적화된 GPU 구현과 CNN을 학습시키기 위해 내재된 다른 모든 작업들을 작성해놓았다.

 네트워크는 성능 향상 및 학습 시간 단축을 위한 특이한 기능들을 탑재했고, 이는 섹션 3에 작성했다. 또한 과적합 방지를 위해서도 여러 기술들을 사용했고, 섹션 4에 작성되어있다.

 네트워크는 5개의 합성곱층과 3개의 완전연결층을 포함하고 있으며, 만약 컨볼루션 레이어를 제거하면 성능이 저하되는 점을 들어 이 깊이가 중요한 것으로 판단된다.

 

 네트워크의 크기는 당시 GPU에서 사용할 수 있는 메모리 양과 교육 가능산 히간에 의해 제한되었다. 저자는 GTX 580 3GB GPU 두 개를 사용해 5~6일간 학습을 시켰으며, 더 빠른 GPU와 더 큰 데이터 셋을 사용할 수 있다면 결과는 개선될 수 있다.

 

 

요약

 변동성이 크고 라벨이 많은 이미지를 분류하는 모델의 학습을 위해 CNN을 사용했다. 학습에는 GPU를 사용했으며, 성능 향상과 학습 시간 단축을 이루어냈고, 과적합을 방지하기 위해 여러 기술들을 도입했다.

 네트워크는 5개의 합성곱층과 3개의 완전연결층으로 구성했다.

 

 

2. The Dataset

The Dataset of AlexNet

 ImageNet은 약 22,000개의 라벨에 1,500만 개 이상의 고해상도 이미지 데이터 셋이다. ILSVRC는 1,000개의 라벨에 1,000개의 이미지가 있는 ImageNet의 서브셋을 활용한다.

 

 ILSVRC-2010은 테스트 셋 라벨들을 사용할 수 있는 유일한 ILSVRC이기에, 대부분의 실험이 여기서 이루어졌다. 또한 ILSVRC-2012에도 참여했기에 섹션 6에서 결과를 보고해놓았다.

 

 ImageNet은 해상도 이미지가 고정되어 있지 않다. 하지만 해당 모델은 일정한 입력 치수를 요구한다. 그렇기에 해당 모델은 이미지를 256 * 256의 해상도로 고정해놓았다. 직사각형의 이미지가 주어질 경우 짧은 면의 길이를 256이 되도록 이미지의 스케일을 조정한 후 중앙을 기준으로 256*256이 되도록 사진을 잘라준다.

 이외의 전처리 작업은 하지 않았으나, 학습 셋의 각 픽셀에서 평균 값을 빼주는 방법을 통해 RGB 픽셀들을 학습시켰다.

 

 

요약

 ImageNet의 서브셋을 활용한 ILSVRC-2010의 테스트 셋을 데이터셋으로 사용했다.
 입력 이미지에 대해 두 가지 전처리 과정을 포함했다.
  -256*256으로 이미지 크롭
  -학습 셋의 각 픽셀에서 데이터셋의 픽셀 평균을 뺐다.

여기서 2번 과정은 정규화를 통해 raw RGB 픽셀들을 학습시켜 일반화 성능의 향상을 위해 구성되었다.

 

 

3. The Architecures

 5개의 합성곱과 3개의 완전연결층, 총합 9개의 레이어로 구성되어 있다. 섹션 3.1~3.4는 중요도 순으로 정렬되어 있다. 가장 중요한 것이 첫 번째이다.

 

 

3.1. ReLU Nonlinearity

 경사 하강법의 관점에서 기존의 포화 비선형성 함수는 (tanh 함수)는 비포화 비선형성 함수인 max(0, x)보다 느리다.

 ReLU를 사용하는 깊은 CNN은 tanh을 사용하는 것보다 몇 배는 빠르다. 이는 그림 1에 나와있고, 4층 CNN으로 CIFAR-10 데이터셋을 학습했을 때 25%의 훈련 오류에 도달하는 데 필요한 학습 횟수를 나타냈다.

 기존의 포화 뉴런 모델을 사용하면 이러한 거대한 신경망을 학습시킬 수 없음을 보여준다.

 

 Jarrettet al은 비선형성 함수 tanh이 Caltech-101 데이터셋에 잘 작동한다고 했다. 하지만 이 데이터셋은 우선 과적합을 방지하는 것에 초점을 두었고, 이들이 관찰하는 효과는 저자가 ReLU를 사용하여 가속화하는 것과는 다르다.

 

 빠른 학습은 큰 데이터셋을 학습하는 큰 모델의 성능에 중요한 영향을 가진다.

 

 

요약

 큰 데이터셋을 학습하는 큰 모델의 성능에 빠른 학습 속도는 중요한 영향을 가진다.
 그런 측면에서 ReLU 함수는 기존의 tahn 함수보다 훨씬 빠른 속도를 보였다.

*saturating nonlinearities : 경사도 소실를 유발할 수 있는 비선형성 활성화 함수

 

3.2. Training on Multiple GPUs

하나의 GTX 580 GPU는 3GB의 메모리를 가지는데, 이는 네트워크가 학습할 수 있는 최대 사이즈를 제한한다. 그리고 120만 개의 트레이닝 예제는 네트워크를 학습시키기에 충분하나, 하나의 GPU에 맞추기 어렵다.

 그래서 저자는 네트워크를 2개의 GPU에 나누었다. 최신 GPU들은 다른 GPU의 메모리에서 직접 읽고 쓸 수 있기 때문에 병렬 처리에 적합하다.

 저자는 커널(노드)을 절반으로 나누어 각 GPU에 넣어 병렬 처리를 했는데, 하나의 트릭을 추가했다. GPU가 특정 계층에만 통신한다는 것이다. 예를 들어 3층의 커널은 2층의 모든 커널들에서만 입력을 받지만, 4층의 커널은 같은 커널맵의 3층 커널에서만 입력을 받는다. (Figure 2를 보면 이해됨.)

 연결 패턴을 선택하는 것은 교차 선택의 문제이지만, 계산량이 허용하는 부분까지 통신량을 정밀하게 조정할 수 있다.

 

 그 결과 아키텍처는 columnar CNN과 유사하다. 단, 열이 독립적이지 않다는 점은 제외한다.

 이 체계는 하나의 GPU에서 커널을 절반으로 한 모델의 학습 결과보다 top-1, 5 오류율이 1.7%와 1.2%를 줄였다. 또한 두 개의 GPU 넷은 한 개의 GPU 넷보다 교육 시간이 약간 적게 소요된다.

 

 

요약

 두 개의 GPU를 병렬로 연결하여 사용했다.

 

3.3. Local Response Normalization

 ReLU는 포화 상태를 방지하기 위해 입력 정규화가 필요하지 않다. 최소 몇몇 데이터 셋들이 괜찮은 입력을 ReLU에 제공하면 뉴런들은 학습을 한다. 그러나 국소 정규화 계획은 일반화에 도움이 되지 않는다.

 

 위의 식에서 합계는 동일한 공간 위치에서 n개의 인접 커널 맵을 통해 실행되며, N은 계층의 총 커널 수이다.

 커널 맵의 순서는 임의적이며 훈련을 시작하기 전에 결정된다.

 이러한 종류의 반응 정규화는 실제 뉴런에서 발견되는 유형에서 영감을 받은 lateral inhibition의 형태를 통해 다른 커널을 사용해 계산한 뉴런 출력 간 큰 활동을 위한 경쟁을 유발한다.

 k, n, a, b는 유효화 집합을 사용해 값이 결정되는 하이퍼 파라미터이다. k=2, n=6, a=10^(-4), b=0.75

 저자는 특정 계층에서 ReLU 비선형성을 적용한 후 이 정규화를 적용했다.

 

 이 전략은 Jarrett의 국소 대비 정규화 계획과 유사하나, 평균 활동을 빼지 않았기에 Brightness Normalization이라고 부른다.

 반응 정규화는 top1, 5의 오류율을 1.4와 1.2% 줄였다.

 또한 CIFAR-10 데이터 셋에 대해 이 체계의 효과를 검증했고, 4층 CNN은 정규화가 없을 때는 13%, 정규화와 함께했을 때는 11%의 오류율을 보였다.

 

 

요약

 ReLU는 정규화가 필요가 없다. 하지만 특정 필터의 한 픽셀의 가중치가 높으면 영향을 받은 특징맵은 자연스럽게
 그 수치가 높을 수 있다. 그래서 필터의 정규화가 필요하다.

 첫 번째, 두 번째 합성곱의 결과에 ReLU를 수행했고, response normalization을 수행했다.

*sigmoid, tanh의 경우에는 경사도가 포화 되는 구간이 존재해 오버피팅을 피하기 위해 정규화를 한다.
*하지만 ReLU는 굳이 정규화가 필요 없다. 하지만 입력에 비례하여 출력이 그대로 증가가 된다. 여러 특징맵의 결과를 정규화를 시키면 생물학적 뉴런에서의 lateral inhibition과 같은 효과를 얻어 일반화 관점에서 더 좋다.
*lateral inhibition : 강한 자극이 주변에 약한 자극으로 전달되는 것을 막는 효과

 

3.4. Overlapping Pooling

 CNN의 풀링 레이어는 동일한 커널 맵에서 인접 뉴런 그룹의 출력을 요약한다. 하지만 기존의 풀링 유닛들은 중복된 이웃의 정보를 저장하지 않았다. 정확하게는 z*z 풀링 유닛을 사용할 때 s=z를 사용한 방식이 기존의 풀링이었다.

 하지만 s=z가 아닌 z 미만으로 설정하면 중복 풀링을 얻을 수 있다. 이는 s=2 와 s=3을 저자가 사용하는 이유이다.

 이 전략은 top-1, 5 에러율을 0.4, 0.3 만큼 감소시켰다.

 일반적으로 Overlapping 풀링을 한 것이 과적합되기 힘들다는 것을 학습 중에 발견했다.

 

 

요약

 Pooling 범위를 중복시켜 특징맵을 풀링할 때 요약 정보를 중첩하여 저장했다.
 이런 방식은 에러율과 과적합에 빠질 가능성을 줄여주었다.

 

3.5. Overall Architecture

 네트워크에는 8개의 층이 포함되었다. 앞의 5개의 층은 합성곱층이고, 나머지 3개는 완전연결층이다. 마지막 완전연결층은 softmax를 통해 1,000개의 분류 라벨에 대한 분포를 생성한다.

 이 네트워크는 다항 로지스틱 회귀를 최대화한다. 즉 예측 분포 하에서 올바른 라벨의 로그 확률 예측을 최대화한다.

 

 

 2, 4, 5 층의 합성곱층은 동일한 GPU 내의 이전 계층의 커널 맵에만 연결된다. 하지만 3 층의 합성곱층은 2층의 모든 커널 맵에 연결되어있다.

 완전연결층의 뉴런은 이전 층의 모든 뉴런들과 연결되어있다.

 반응 정규화 레이어는 1, 2 합성곱층 뒤에 있다. Max 풀링 레이어는 다섯 번째 합성곱층과 반응 정규화 레이어 뒤에 존재한다.

 ReLU 함수는 모든 합성곱 및 완전연결 계층의 출력에 적용된다.

 

 

 첫 번째 합성곱층은 224*224*3 입력을 받아 11*11*3 크기의 96개의 커널을 4 픽셀의 보폭으로 움직여 필터링한다.

 두 번째 합성곱층은 5*5*48의 256 커널로 필터링을 한다.

 세 번째, 네 번째, 다섯 번째 합성곱층은 어떠한 풀링이나 표준화 레이어 없이 연결되어 있다.

 세 번째 합성곱층은 두 번째 합성곱층들의 출력을 받아 3*3*256의 384 커널을 적용한다.

 네 번째 합성곱층은 3*3*192 크기의 384개의 커널을 가지며, 다섯 번째 합성곱층은 3*3*192 크기의 256 커널을 가진다.

 

 

 

요약

1 : 227*227*3 => 11*11*3, 96 => 55*55, 96 => ReLU, LRN, Pool => 27*27, 96 
2 : 27*27, 96 => 5*5*48. 256 => 27*27, 256 => ReLU, LRN, Pool => 13*13, 256
                    여기부터 패딩적용
3 : 13*13, 256 => 3*3*256, 384 => 13*13, 384 => ReLU
4 : 13*13, 384 => 3*3*192, 384 => 13*13, 384 => ReLU
5 : 13*13, 384 => 3*3*192, 256 => 13*13, 256 => ReLU, Pool => 6*6, 256
6 : 6*6, 256 => Flatten => 9216 => 4096 뉴런 => ReLU
7 : 4096 뉴런 => ReLU
8 : 1000 뉴런 softmax

*첫 번째 합성곱층의 224는 오타. 227이다.
*256 => 227로 입력값이 바뀌는 이유는 데이터 증강을 위함이다.

 

 

4. Reducing Overfitting

 AlexNet의 아키텍처는 6천만 개의 매개 변수를 가지고 있다. 과적합 없이 이러한 매개 변수를 학습하는 것은 불충분하다.

 

 

4.1. Data Augementation

 과적합을 줄이는 일반적이고 쉬운 방법은 레이블 보존 변환을 상요해 데이터 셋을 인위적으로 확장하는 것이다.

 저자는 두 가지 다른 형태의 데이터 증강을 채택했는데, 두 형태 모두 변환된 이미지를 거의 계산하지 않고 원본 이미지에서 생산할 수 있는 방식이라 변환된 이미지를 디스크에 저장하지 않았다.

 저자는 구현을 통해 GPU가 이미지를 학습하는 동안 CPU에서 파이썬 코드로 변환된 이미지를 생성했다. 따라서 이러한 데이터 증강은 계산적으로 자유롭다.

 

 첫 번째 데이터 증강 방법은 이미지 변환과 수평 반사이다.

 저자는 256*256 이미지에서 무작위로 224*224 패치와 이들의 수평 반사를 추출해 학습에 사용했다.

 이 방법은 상호의존성이 높지만 훈련 설정의 크기를 2048배까지 증가시켰고, 과적합으로 인해 더 작은 네트워크를 사용했어야 할 상황을 막아주었다.

 테스트가 진행되는 동안 네트워크는 5개의 224*224 패치 (네 개의 코너 패치와 중앙 패치)를 추출하고, 이들을 뒤집은 5개의 이미지, 총 10개의 이미지를 추출하고 softmax 레이어에 의한 예측을 평균화함으로써 예측을 진행한다.

 

 두 번째 데이터 증강은 훈련 이미지에서 RGB 채널의 강도를 변경하는 방법이다.

 구체적으로 저자는 ImageNet 데이터 셋 전체에 RGB 픽셀 값 집합에 대한 PCA를 수행했다. 그리고 평균이 0, 표준 편차가 0.1인 가우시안 분포에서 얻은 랜덤 변수와 PCA의 결과를 곱해 각 이미지에 추가했다.

 이 전략은 원본 이미지의 중요한 특징, 즉 조명의 강도와 색상의 변화에 대한 물체 정체성의 불변성을 대략적으로 포착한다. 이 체계는 top-1의 오류율을 1% 이상 감소시켰다.

 

 

요약

 오버 피팅을 막기 위해 데이터의 양을 늘렸다. 데이터 증강은 GPU가 학습을 하는 동안 CPU가 수행했다.
 첫 번째 방법은 원본 이미지에서 224*224의 이미지를 얻어 뒤집는 방법이다.
 두 번째 방법은 원본 이미지의 RGB 값을 변경하는 방법이다.
 이러한 방법은 테스트 셋의 크기를 늘려주었고 오류율을 감소시켜주었다.

+PCA Color Augementation : 데이터 셋의 색상(RGB)를 임의로 바꾸는 것.
+그냥 바꾸는 게 아니라 PCA를 통해 이미지의 특성은 유지하고 RGB 컬러 값을 이동 및 변경한다.

 

 

4.2. Dropout

 다양한 모델의 예측을 결합하는 것은 테스트 오류를 줄이는데 좋다. 하지만 훈련에 며칠이 소요되는 대형 신경망에는 적합하지 않다. 하지만 모델 조합에 효과적인 방법이 존재한다.

 Dropout이라 불리는 기술은 각각의 히든 뉴런의 출력을 0.5 확률로 영점화하는 설정으로 구성한다. 이런 식으로 빠진 뉴런들은 forward에 기여하지 않고, 마찬가지로 역전파에도 참여하지 않는다.

 이 기술은 뉴런이 특정한 다른 뉴런의 존재에 의존할 수 없게 해 뉴런의 복잡한 공동 적응을 감소시킨다. 따라서 다른 뉴런의 다양한 무작위 부분 집합과 함께 보다 유용하고 강력한 특징을 학습하게 한다.

 테스트에는 모든 뉴런을 사용하지만 출력에 0.5를 곱한다. 이것은 지수적으로 많은 드롭아웃 네트워크에 의해 생성된 예측 분포의 기하학적 평균을 내는데 합리적인 근사치이다.

 

 그림 2의 처음 두 개의 완전연결층에서 드롭아웃을 사용했다. 드롭아웃이 없으면 AlexNet은 과적합을 보이지만, 드롭아웃은 수렴에 필요한 반복 횟수를 대략 두 배로 증가시켰다.

 

 

요약

 여러 모델을 묶는 방법은 과적합 방지에 좋지만 큰 네트워크에는 비효율적이다.
 그에 반해 드롭 아웃은 모델 조합에 효과적이다. 0.5의 확률을 적용하면 확률에 따라 완전연결층의 뉴런들이 OUTPUT으로 0을 출력한다.

 이렇게 드랍된 뉴런들은 forward에 기여하지 않고 역전파에도 참여하지 않는다.
 출력값에는 드롭아웃을 사용하지 않지만 출력에 0.5를 곱해주어야 한다.

 

 

5. Details of learning

 저자는 배치 사이즈를 127로, 모멘텀을 0.9로, weight decay는 0.0005로 조정했다.

 적은 양의 weight decay가 모델의 학습에 중요하다. weight decay는 단순한 정규화가 아니라 모델의 훈련 오류를 감소시킨다.

 

 표준 편차가 0.01인 제로 평균 가우시안 분포에서 각 계층의 가중치를 초기화했다. 두 번째, 네 번째, 다섯 번째 합성곱층과 완전연결층에서 뉴런 편향을 상수 1로 초기화했다.

 이 초기화는 ReLU에 양의 입력을 제공해 학습의 초기 단계를 가속화한다.

 상수 0으로 나머지 층에서 뉴런 편향을 초기화했다.

 

 모든 계층에 동일한 학습률을 사용했고, 훈련 내내 수동으로 조정했다.

 휴리스틱은 유효성 검사 오류율이 현재 학습 속도로 햐상되지 않을 때 학습 속도를 10으로 나누는 방식을 사용했다.

 학습률은 0.01에서 초기화되었으며, 종료 전에 세 번 감소되었다.

 120만 개의 이미지 훈련 셋을 통해 90번의 훈련을 진행했는데, 두 개의 GPU에서 5~6일이 소요되었다.

 

요약

적은 양의 weight decay는 모델의 훈련 오류를 감소시킨다.
학습률은 0.01에서 시작해 수동으로 조절하며 세 번 1/10으로 감소시켰다.

*weight decay : 오버피팅 방지를 위한 방법. 학습된 모델의 복잡도를 줄이기 위해 가중치가 너무 큰 값을 가지지 않도록 손실 함수에 가중치가 커질 때에 대한 패널티 항목을 넣어주는 것. 대표적으로 L1, L2 규제가 있다.

 

 

6. Results

 

 

6.1. Qualitative Evaluations

그림 3은 네트워크의 두 데이터 연결 계층에서 학습한 컨볼루션 커널이다. 다양한 색 부분 뿐 아니라 빈도와 방향 선택 커널을 네트워크가 학습했다.

 GPU1의 커널은 대부분 색에 구애받지 않는 반면, GPU2의 커널은 대부분 색에 따라 다르다. 이러한 종류의 특징은 매 실행 중에 발생하며, 특정 무작위 가중치 초기화와는 무관했다.

 

 그림 4는 네트워크의 학습을 정성적으로 평가한다. 진드기에서 볼 수 있듯 중앙에서 벗어난 물체도 인식하며, 고양이 종의 일부만 표범으로 분류하며 대부분은 타당한 결과를 내놓았다. 하지만 일부는 사진의 의도된 초점에 대해 모호성이 존재한다.

 

 네트워크의 시각적 지식을 조사하는 다른 방법은 4096차원의 은닉층에서 이미지에 의해 유도된 기능 활성화를 고려하는 것이다.

 두 개의 이미지가 작은 유클리드 분리를 통해 특징 활성화 벡터를 생성하는 경우 신경망의 높은 수준이 유사하다고 간주할 수 있다.

 그림 4는 테스트 셋의 이미지 5개와 이 측정에 따라 각 이미지와 유사한 교육 셋의 이미지 6개를 보여준다. 픽셀 수준에서 검색된 학습 이미지는 일반적으로 첫 번째 열의 쿼리 이미지와 l2에서 다르지 않다. 예를 들어 개와 코끼리 이미지는 다양한 포즈를 취할 수 있다.

 

 두 4096 차원의 실제 값 벡터 사이의 유클리드 거리를 사용한 유사성 계산은 비효율적이다. 하지만 이러한 벡터를 짧은 이진 코드로 압축하는 등 자동 인코더를 훈련시키면 효율적일 수 있다.

 원시 픽셀에 인코더를 적용하면 비슷한 이미지 뿐 아니라 비슷한 패턴, 예를 들어 비슷한 보서리를 가진 이미지까지 유사성을 찾게 되는데, 이 방식은 이미지 라벨을 사용하지 않는 원시 픽셀에 자동 인코더를 적용하는 것보다 훨씬 더 나은 이미지 검색 방법이 생성될 수 있다.

 

 

요약

 커널들이 학습을 통해 각각 색에 구애받는 커널과, 색에 구애받지 않는 커널이 만들어졌다.
 은닉층에서의 이미지 분류는 기존의 이미지 검색 방법보다 훨씬 좋은 검색 방법이 될 수 있는 여지가 있다.

 

7. Discussion

 이 결과는 크고 깊은 CNN이 지도학습을 통해 매우 어려운 데이터 셋에서 기록적인 결과를 달성할 수 있음을 보여주었다.

 단일 합성곱층이 제거되면 네트워크 성능이 저하되는 점도 눈에 띈다. 예를 들어 중간 계층 제거시 네트워크의 상위 1개 성능에서 약 2%의 손실이 발생했다. 따라서 깊이는 결과를 얻기 위해 매우 중요하다.

 

 실험의 단순화를 위해 비지도된 사전학습을 진행하지 않았다. 비디오 시퀀스에 크고 깊은 CNN을 사용하고 싶다.

 

요약

합성곱층의 수가 줄어들면 성능도 저하된다.
네트워크의 깊이는 결과를 위해 매우 중요하다.

 

 

 

 

 

 

구현

# AlexNet 구현

import torch
import torch.nn as nn
from torchvision import datasets, transforms

devices = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print(devices)

#transforms : 이미지 데이터를 로딩할 때 모듈의 입력값으로 사용할 수 있도록 변환한다.
transform = transforms.Compose([
    transforms.Resize(256),
    transforms.RandomCrop(227),
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

#Tran and Test set 로딩
#데이터는 CIFAR10 사용
trainset = datasets.CIFAR10('~/.data', download=True, train=True, transform=transform)
trainset = torch.utils.data.DataLoader(trainset, batch_size=256, shuffle=True)
testset = datasets.CIFAR10('~/.data', download=True, train=False, transform=transform)
testset = torch.utils.data.DataLoader(testset, batch_size=256, shuffle=True)


#모델 구축
class AlexNet(nn.Module) :
    def __init__(self, input_size = 227, num_classes = 10) :
        super(AlexNet, self).__init__()
        
        self.cnnLayer = nn.Sequential(
            #1st Conv : conv, relu, lrm, pool
            nn.Conv2d(in_channels = 3, out_channels = 96, kernel_size = 11, padding = 0, stride = 4), #227->55
            nn.ReLU(inplace = True),
            nn.LocalResponseNorm(size = 5, alpha=0.0001, beta = 0.75, k = 2), #식에서 사이즈, a, b(베타), k 지정
            nn.MaxPool2d(kernel_size = 3, stride = 2), #55->27
            
            #2nc Conv : conv, relu, lrm, pool
            #패딩이 숫자인데, 2이면 앞 뒤로 4가 추가되어 커널을 5로 줘도 사이즈가 유지됨.
            nn.Conv2d(in_channels = 96, out_channels = 256, kernel_size = 5, padding = 2, stride = 1), #27->27
            nn.ReLU(inplace = True),
            nn.LocalResponseNorm(size = 5, alpha=0.0001, beta = 0.75, k = 2),
            nn.MaxPool2d(kernel_size = 3, stride = 2), #13
            
            #3rd Conv : conv, relu
            nn.Conv2d(in_channels = 256, out_channels = 384, kernel_size = 3, padding = 1, stride = 1), #27->27
            nn.ReLU(inplace = True),
            
            #4th Conv : conv, relu
            nn.Conv2d(in_channels = 384, out_channels = 384, kernel_size = 3, padding = 1, stride = 1), #27
            nn.ReLU(inplace = True),
            
            #5th Conv : conv, relu, lrm, pool
            nn.Conv2d(in_channels = 384, out_channels = 256, kernel_size = 3, padding = 1, stride = 1), #13
            nn.ReLU(inplace = True),
            nn.LocalResponseNorm(size = 5, alpha=0.0001, beta = 0.75, k = 2),
            nn.MaxPool2d(kernel_size = 3, stride = 2), #13->6
        )
            
        self.fcLayer = nn.Sequential(
            #FC Layer
            nn.Linear(256*6*6, 4096),
            nn.ReLU(inplace = True),
            nn.Dropout(p = 0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace = True),
            nn.Dropout(p = 0.5),
            nn.Linear(4096, num_classes)
        )
        
        #표준화 및 bias 초기화
        for layer in self.cnnLayer :
            if isinstance(layer, nn.Conv2d) :
                #conv 레이어들을 가우시안 분포로 표준화 하고 bias는 0
                nn.init.normal_(layer.weight, mean = 0, std = 0.01)
                nn.init.constant_(layer.bias, 0)
        
        #그런데 2, 4, 5 conv는 1로 초기화
        nn.init.constant_(self.cnnLayer[4].bias, 1)
        nn.init.constant_(self.cnnLayer[10].bias, 1)
        nn.init.constant_(self.cnnLayer[12].bias, 1)
    
    def forward(self, train) :
        #멀티 GPU는 당장 불가능하기에 제외
        output = self.cnnLayer(train)
        output = output.view(-1, 256*6*6)
        output = self.fcLayer(output)
        
        return output


alexnet = AlexNet(227, 10)
alexnet.to(devices)

# weight decay = 0.0005, momentum = 0.9, lr = 0.01
optimizer = torch.optim.SGD(alexnet.parameters(), lr = 0.01, momentum = 0.9, weight_decay = 0.0005)
criterion = nn.CrossEntropyLoss().to(devices)

#학습
from tqdm.notebook import tqdm

epochs = 5
for epoch in range(epochs) :
    epoch_loss = 0
    for data, classes in tqdm(trainset) :
        inputs, labels = data.to(devices), classes.to(devices)
        
        optimizer.zero_grad()
        outputs = alexnet(inputs)
        
        #순전파, 역전파 최적화
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        
        epoch_loss += loss.item()
    
    correct = list(0. for i in range(1000))
    total  = list(0. for i in range(1000))
    
    with torch.no_grad() :
        for data, classes in testset :
            inputs, labels = data.to(devices), classes.to(devices)
            outputs = alexnet(inputs)
            _, predicted = torch.max(outputs, 1)
            c = (predicted == labels).squeeze()
            for i in range(labels.size()[0]) :
                label = labels[i]
                correct[label] += c[i].item()
                total[label] += 1
    
            
    
    print('{0} : loss {1:.3f}, val_acc {2:.3f}'.format(epoch+1, epoch_loss, (sum(correct) / sum(total)) * 100))

print('끝')
728x90
반응형

'IT 지식 > 인공지능_딥러닝' 카테고리의 다른 글

[논문] DenseNet  (0) 2021.03.07
[논문] ResNet  (0) 2021.03.02
자연어 처리 : 트랜스포머  (0) 2021.02.22
Convolutional Neural Network (합성곱 신경망, CNN)  (0) 2021.01.27