Keras 및 TPU를 사용한 최신 컨버닛, 스퀴즈넷, Xception

1. 개요

이 실습에서는 최신 컨볼루셔널 아키텍처에 관해 알아보고 지식을 활용하여 'squeezenet'이라는 간단하지만 효과적인 컨볼루션을 구현합니다.

이 실습에는 컨볼루셔널 신경망에 관한 필요한 이론적 설명이 포함되어 있으며, 딥 러닝을 배우는 개발자가 이 실습을 시작하기에 좋은 출발점이 될 것입니다.

이 실습은 'TPU 기반 Keras'의 4부입니다. Google Cloud 시리즈를 확인해 보세요 다음 순서대로 또는 개별적으로 수행할 수 있습니다.

ca8cc21f6838eccc.png

학습할 내용

  • Keras 기능 스타일 마스터하기
  • 스퀴즈넷 아키텍처를 사용하여 모델 빌드
  • 빠른 학습 및 아키텍처 반복을 위해 TPU 사용
  • tf.data.dataset를 사용한 데이터 증강 구현
  • TPU에서 사전 학습된 대규모 모델 (Xception)을 미세 조정하기 위해

의견

이 Codelab에서 잘못된 부분을 발견하면 알려주세요. 의견은 GitHub 문제[의견 링크]를 통해 제공할 수 있습니다.

2. Google Colaboratory 빠른 시작

이 실습에서는 Google Collaboratory를 사용하므로 사용자가 별도로 설정할 필요가 없습니다. Colaboratory는 교육용 온라인 노트북 플랫폼입니다. 무료 CPU, GPU, TPU 학습을 제공합니다.

688858c21e3beff2.png

이 샘플 노트북을 열고 몇 개의 셀을 실행하여 Colaboratory에 익숙해지세요.

c3df49e90e5a654f.png Welcome to Colab.ipynb

TPU 백엔드 선택

8832c6208c99687d.png

Colab 메뉴에서 런타임 > 런타임 유형 변경을 선택한 다음 TPU를 선택합니다. 이 Codelab에서는 하드웨어 가속 학습에 지원되는 강력한 TPU (Tensor Processing Unit)를 사용합니다. 처음 실행 시 런타임에 자동으로 연결이 이루어집니다. 또는 '연결' 버튼을 클릭합니다.

노트북 실행

76d05caa8b4db6da.png

셀을 클릭하고 Shift-Enter를 사용하여 셀을 한 번에 하나씩 실행합니다. 런타임 > 모두 실행

목차

429f106990037ec4.png

모든 노트북에는 목차가 있습니다. 왼쪽에 있는 검은색 화살표를 사용해 파일을 열 수 있습니다.

숨겨진 셀

edc3dba45d26f12a.png

일부 셀에는 제목만 표시됩니다. Colab 전용 노트북 기능입니다. 두 번 클릭하면 안의 코드를 볼 수 있지만 보통은 그다지 흥미롭지 않습니다. 일반적으로 지원 또는 시각화 함수입니다. 내부의 함수를 정의하려면 이러한 셀을 실행해야 합니다.

인증

cdd4b41413100543.png

승인된 계정으로 인증하면 Colab에서 비공개 Google Cloud Storage 버킷에 액세스할 수 있습니다. 위의 코드 스니펫은 인증 프로세스를 트리거합니다.

3. [정보] Tensor Processing Unit (TPU)이란 무엇인가요?

요약

f88cf6facfc70166.png

Keras의 TPU에서 모델을 학습시키기 위한 코드 (TPU를 사용할 수 없는 경우 GPU 또는 CPU로 대체)

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

오늘은 TPU를 사용하여 상호작용 속도 (학습 실행당 분)의 꽃 분류기를 빌드하고 최적화해 보겠습니다.

688858c21e3beff2.png

TPU를 사용해야 하는 이유

최신 GPU는 프로그래밍 가능한 '코어'를 중심으로 구성됩니다. 코어는 3D 렌더링, 딥 러닝, 물리적 시뮬레이션 등과 같은 다양한 작업을 처리할 수 있는 매우 유연한 아키텍처입니다. 반면 TPU는 기본 벡터 프로세서에 전용 행렬 곱셈 유닛을 결합하고 신경망과 같이 큰 행렬 곱셈이 중요한 모든 작업에서 탁월한 성능을 발휘합니다.

8eb3e718b8e2ed08.png

그림: 행렬 곱셈이 적용된 밀집 신경망 레이어로, 신경망을 통해 한 번에 처리된 8개의 이미지 배치가 포함됩니다. 한 줄 x 열 곱셈을 실행하여 이미지의 모든 픽셀 값에 대한 가중치가 적용된 합계를 실제로 수행하고 있는지 확인하세요. 컨볼루셔널 레이어는 조금 더 복잡하지만 ( 이 섹션 1의 설명)도 행렬 곱셈으로 표현할 수 있습니다.

하드웨어

MXU 및 VPU

TPU v2 코어는 행렬 곱셈과 VPU(벡터 처리 장치)를 실행하는 MXU(Matrix Multiply Unit)로 구성되며, 활성화, softmax 등의 기타 모든 작업을 위한 VPU(벡터 처리 장치)가 실행됩니다. VPU는 float32 및 int32 계산을 처리합니다. 반면에 MXU는 혼합 정밀도 16~32비트 부동 소수점 형식으로 작동합니다.

7d68944718f76b18.png

정밀도 부동 소수점과 bfloat16이 혼합됨

MXU는 bfloat16 입력 및 float32 출력을 사용하여 행렬 곱셈을 계산합니다. 중간 누적은 float32 정밀도로 실행됩니다.

19c5fc432840c714.png

신경망 학습은 일반적으로 부동 소수점 정밀도 감소로 인해 발생하는 노이즈에 강합니다. 노이즈가 옵티마이저가 수렴하는 데까지 도움이 되는 경우도 있습니다. 전통적으로 16비트 부동 소수점 정밀도는 계산을 가속화하는 데 사용되었지만 float16 및 float32 형식은 범위가 매우 다릅니다. 정밀도를 float32에서 float16으로 줄이면 일반적으로 오버 및 언더플로가 발생합니다. 솔루션이 있지만 float16이 작동하려면 일반적으로 추가 작업이 필요합니다.

이러한 이유로 Google은 TPU에 bfloat16 형식을 도입했습니다. bfloat16은 float32와 정확히 동일한 지수 비트와 범위를 가진 잘린 float32입니다. 이는 TPU가 bfloat16 입력과 float32 출력의 혼합 정밀도로 행렬 곱셈을 계산한다는 사실에 더해, 일반적으로 낮은 정밀도의 성능 향상 이점을 누리기 위해 코드를 변경할 필요가 없다는 뜻입니다.

수축 배열

MXU는 이른바 '시스톨릭 배열'을 사용하여 하드웨어에서 행렬 곱셈을 구현합니다. 데이터 요소가 하드웨어 계산 장치의 배열을 통해 흐르는 아키텍처. (의학에서 '수축기'는 심장 수축과 혈류, 여기서는 데이터의 흐름을 의미합니다.)

행렬 곱셈의 기본 요소는 한 행렬의 선과 다른 행렬의 열 사이의 내적입니다 (이 섹션 상단의 그림 참조). 행렬 곱셈 Y=X*W의 경우 결과의 한 요소는 다음과 같습니다.

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

GPU에서는 이 제품을 GPU '코어'로 프로그래밍합니다. 최대한 많은 '코어'에서 결과 행렬의 모든 값을 한 번에 계산하려고 시도합니다. 결과 행렬이 128x128 큰 경우 128x128=16K '코어'가 필요합니다. 일반적으로는 불가능한 상태입니다 가장 큰 GPU에는 약 4000개의 코어가 있습니다. 반면 TPU는 MXU의 컴퓨팅 단위에 최소한의 하드웨어만 사용합니다. 즉, bfloat16 x bfloat16 => float32 곱셈-누산기만 사용합니다. 이러한 연산은 매우 작아서 TPU에서 128x128 MXU로 16K를 구현하고 한 번에 행렬 곱셈을 처리할 수 있습니다.

f1b283fc45966717.gif

그림: MXU 수축기 배열 컴퓨팅 요소는 곱셈-누산기입니다. 한 행렬의 값이 배열 (빨간색 점)에 로드됩니다. 다른 행렬의 값은 배열 (회색 점)을 통과합니다. 수직선은 값을 위로 전파합니다. 가로선은 부분 합계를 전파합니다. 데이터가 배열을 통과할 때 오른쪽에서 행렬 곱셈의 결과가 나오는지 확인하는 작업은 사용자의 연습으로 남겨 둡니다.

그 밖에도, 내적이 MXU에서 계산되는 동안 중간 합계는 단순히 인접한 컴퓨팅 단위 간에 흐릅니다. 메모리 또는 레지스터 파일에서도 저장하고 검색할 필요가 없습니다. 결과적으로 TPU 시스톨릭 배열 아키텍처는 밀도와 전력 측면에서 상당한 이점을 얻을 뿐만 아니라 행렬 곱셈을 계산할 때 GPU에 비해 무시할 수 없는 속도상의 이점을 얻게 됩니다.

Cloud TPU

" Cloud TPU v2인치 PCI 연결 TPU 보드가 포함된 가상 머신 (VM)을 얻을 수 있습니다. TPU 보드에는 4개의 듀얼 코어 TPU 칩이 있습니다. 각 TPU 코어에는 VPU (벡터 처리 장치)와 128x128 MXU (MatriX 곱하기 단위)가 있습니다. 이 'Cloud TPU'는 일반적으로 네트워크를 통해 이를 요청한 VM에 연결됩니다. 전체 그림은 다음과 같습니다.

dfce5522ed644ece.png

그림: 네트워크에 연결된 'Cloud TPU'가 있는 VM 액셀러레이터를 생성합니다 'Cloud TPU' 듀얼 코어 TPU 칩이 4개 있는 PCI 연결 TPU 보드가 탑재된 VM으로 구성됩니다.

TPU 포드

Google의 데이터 센터에서 TPU는 고성능 컴퓨팅 (HPC) 상호 연결에 연결되어 하나의 거대한 가속기처럼 보일 수 있습니다. Google은 이를 포드라고 부르며 최대 512개의 TPU v2 코어 또는 2,048개의 TPU v3 코어를 포함할 수 있습니다.

2ec1e0d341e7fc34.jpeg

그림: TPU v3 포드 HPC Interconnect를 통해 연결된 TPU 보드 및 랙

학습 중에는 AllReduce 알고리즘을 사용하여 TPU 코어 간에 경사가 교환됩니다 ( 여기에 all-Reduce에 대한 자세한 설명). 학습 중인 모델은 큰 배치 크기로 학습시켜 하드웨어를 활용할 수 있습니다.

d97b9cc5d40fdb1d.gif

그림: Google TPU의 2D 원환형 메시 HPC 네트워크에서 AllReduce 알고리즘을 사용하여 학습 중 경사의 동기화

소프트웨어는

대형 배치 크기 학습

TPU에 이상적인 배치 크기는 TPU 코어당 128개의 데이터 항목이지만, 하드웨어는 이미 TPU 코어당 8개의 데이터 항목 중에서 적절한 사용률을 표시하고 있습니다. Cloud TPU 한 개에는 코어가 8개 있습니다.

이 Codelab에서는 Keras API를 사용합니다. Keras에서 지정하는 배치는 전체 TPU의 전역 배치 크기입니다. 배치가 자동으로 8개로 분할되어 TPU의 8개 코어에서 실행됩니다.

da534407825f01e3.png

추가 성능 팁은 TPU 성능 가이드를 참조하세요. 매우 큰 배치 크기의 경우 일부 모델에서 특별한 주의가 필요할 수 있습니다. 자세한 내용은 LARSOptimizer를 참고하세요.

비하인드 스토리: XLA

TensorFlow 프로그램은 계산 그래프를 정의합니다. TPU는 Python 코드를 직접 실행하지 않고 TensorFlow 프로그램에서 정의한 계산 그래프를 실행합니다. 내부적으로 XLA (가속 선형 대수 컴파일러)라는 컴파일러는 계산 노드의 TensorFlow 그래프를 TPU 기계어 코드로 변환합니다. 이 컴파일러는 코드 및 메모리 레이아웃에 관해 다양한 고급 최적화도 실행합니다. 작업이 TPU로 전송될 때 컴파일이 자동으로 실행됩니다. 빌드 체인에 명시적으로 XLA를 포함하지 않아도 됩니다.

edce61112cd57972.png

그림: TPU에서 실행하기 위해 TensorFlow 프로그램에서 정의한 계산 그래프는 먼저 XLA (가속 선형 대수학 컴파일러) 표현으로 변환된 다음 XLA를 통해 TPU 머신 코드로 컴파일됩니다.

Keras에서 TPU 사용

TPU는 Tensorflow 2.1부터 Keras API를 통해 지원됩니다. Keras 지원은 TPU 및 TPU 포드에서 작동합니다. 다음은 TPU, GPU, CPU에서 작동하는 예입니다.

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

이 코드 스니펫에서 각 항목의 의미는 다음과 같습니다.

  • TPUClusterResolver().connect()는 네트워크에서 TPU를 찾습니다. 대부분의 Google Cloud 시스템 (AI Platform 작업, Colaboratory, Kubeflow, 'ctpu up' 유틸리티를 통해 생성된 딥 러닝 VM)에서 매개변수 없이 작동합니다. 이러한 시스템은 TPU_NAME 환경 변수 덕분에 TPU의 위치를 알고 있습니다. TPU를 직접 만드는 경우 TPU_NAME 환경을 설정하거나 var. 사용 중인 VM에서 또는 명시적 매개변수(TPUClusterResolver(tp_uname, zone, project))를 사용하여 TPUClusterResolver를 호출합니다.
  • TPUStrategy는 분포와 'all-reduce'를 구현하는 부분입니다. 경사 동기화 알고리즘입니다.
  • 전략이 범위를 통해 적용됩니다. 모델은 전략 scope() 내에 정의되어야 합니다.
  • tpu_model.fit 함수에는 TPU 학습을 위한 입력으로 tf.data.Dataset 객체가 필요합니다.

일반적인 TPU 포팅 작업

  • TensorFlow 모델에서 데이터를 로드하는 방법에는 여러 가지가 있지만 TPU의 경우 tf.data.Dataset API를 사용해야 합니다.
  • TPU는 매우 빠르기 때문에 데이터를 수집할 때 TPU 실행 시 병목 현상이 발생하는 경우가 많습니다. TPU 성능 가이드에는 데이터 병목 현상을 감지하는 데 사용할 수 있는 도구와 기타 성능 팁이 있습니다.
  • int8 또는 int16 숫자는 int32로 취급됩니다. TPU에는 32비트 미만에서 작동하는 정수 하드웨어가 없습니다.
  • 일부 TensorFlow 작업은 지원되지 않습니다. 목록은 여기에서 확인하세요. 좋은 소식은 이 제한이 모델을 정방향 및 역방향으로 전달하는 학습 코드에만 적용된다는 것입니다. 모든 TensorFlow 작업은 CPU에서 실행되므로 데이터 입력 파이프라인에서 계속 사용할 수 있습니다.
  • tf.py_func는 TPU에서 지원되지 않습니다.

4. [정보] 신경망 분류 기준 101

요약

다음 단락에서 굵게 표시된 모든 용어를 이미 알고 있는 경우 다음 실습으로 이동할 수 있습니다. 딥 러닝을 이제 막 시작했다면 환영하며, 계속 읽어 보시기 바랍니다.

레이어의 시퀀스로 빌드된 모델의 경우 Keras는 Sequential API를 제공합니다. 예를 들어 밀집 레이어 3개를 사용하는 이미지 분류기는 Keras로 다음과 같이 작성할 수 있습니다.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

고밀도 신경망

이는 이미지 분류를 위한 가장 단순한 신경망입니다. 인코더-디코더는 '뉴런'으로 층으로 배열됩니다. 첫 번째 레이어는 입력 데이터를 처리하고 그 출력을 다른 레이어에 제공합니다. 이를 '밀도가 높은' 각 뉴런이 이전 레이어의 모든 뉴런과 연결되어 있기 때문입니다.

c21bae6dade487bc.png

모든 픽셀의 RGB 값을 긴 벡터로 평면화하고 입력으로 사용하여 이미지를 이러한 네트워크에 피드할 수 있습니다. 이미지 인식에 가장 적합한 기술은 아니지만 나중에 개선하겠습니다.

뉴런, 활성화, RELU

'뉴런' 모든 입력의 가중 합계를 계산한 다음 '편향'이라는 값을 더합니다. 소위 '활성화 함수'를 통해 결과를 제공합니다. 가중치와 편향은 처음에는 알 수 없습니다. 무작위로 초기화되고 '학습'됩니다. 신경망을 학습시킬 수 있습니다.

644f4213a4ee70e5.png

가장 많이 사용되는 활성화 함수는 정류 선형 유닛의 RELU입니다. 위의 그래프에서 볼 수 있듯이 매우 간단한 함수입니다.

소프트맥스 활성화

꽃을 5가지 카테고리 (장미, 튤립, 민들레, 데이지, 해바라기)로 분류하기 때문에 위의 네트워크는 5개의 뉴런 레이어로 끝납니다. 중간 레이어의 뉴런은 클래식 RELU 활성화 함수를 사용하여 활성화됩니다. 하지만 마지막 레이어에서는 이 꽃이 장미나 튤립일 확률을 나타내는 0과 1 사이의 숫자를 계산하려고 합니다. 이를 위해 '소프트맥스'라는 활성화 함수를 사용하겠습니다.

벡터에 소프트맥스를 적용하려면 각 요소의 지수를 구한 다음, 일반적으로 L1 norm (절대값의 합)을 사용하여 값의 합이 최대 1이 되어 확률로 해석될 수 있도록 벡터를 정규화합니다.

ef0d98c0952c262d.png d51252f75894479e.gif

교차 엔트로피 손실

이제 신경망이 입력 이미지에서 예측을 생성하므로 얼마나 좋은지 측정해야 합니다. 즉, 네트워크가 알려준 내용과 종종 '라벨'이라고 하는 정답 사이의 거리를 측정해야 합니다. 데이터 세트의 모든 이미지에 올바른 라벨이 있다는 점을 기억하세요.

모든 거리가 작동하지만 분류 문제의 경우 '교차 엔트로피 거리'가 가장 효과적입니다. 이를 오류 또는 '손실'이라고 하겠습니다. 함수:

7bdf8753d20617fb.png

경사하강법

"학습" 신경망은 실제로 학습 이미지와 라벨을 사용하여 교차 엔트로피 손실 함수를 최소화하기 위해 가중치와 편향을 조정하는 것을 의미합니다. 작동 원리는 다음과 같습니다.

교차 엔트로피는 가중치, 편향, 학습 이미지의 픽셀 및 알려진 클래스의 함수입니다.

모든 가중치와 모든 편향에 상대적인 교차 엔트로피의 편미분을 계산하면 주어진 이미지, 라벨, 가중치와 편향의 현재 값에 대해 계산된 '경사'를 얻게 됩니다. 수백만 개의 가중치와 편향이 있을 수 있으므로 경사를 계산하는 것은 엄청난 노력으로 들립니다. 다행히 Tensorflow가 이를 자동으로 수행합니다. 그라데이션의 수학적 특성은 '위쪽'을 향한다는 것입니다. 교차 엔트로피가 낮은 곳으로 가려고 하므로 반대 방향으로 갑니다. 가중치와 편향은 경사의 비율로 업데이트합니다. 그런 다음 학습 루프에서 다음 학습 이미지 및 라벨 배치를 사용하여 동일한 작업을 반복해서 수행합니다. 이 경우 교차 엔트로피가 최소 수준인 지점으로 연결되길 바라지만 이 최솟값이 고유하다는 것을 보장하지는 않습니다.

경사하강법 2.png

미니 배치 및 모멘텀

예시 이미지 한 개에 대해서만 경사를 계산하고 가중치와 편향을 즉시 업데이트할 수 있지만, 예를 들어 128개 이미지 배치에서는 그라데이션이 적용되어 서로 다른 예시 이미지가 주는 제약 조건을 더 잘 표현하는 그라데이션이 제공되므로 솔루션을 향해 더 빠르게 수렴할 수 있습니다. 미니 배치의 크기는 조정 가능한 매개변수입니다.

'확률적 경사하강법'이라고도 하는 이 기법 또 다른 실용적인 이점이 있습니다. 배치 작업은 더 큰 행렬로 작업하게 되어 일반적으로 GPU 및 TPU에서 더 쉽게 최적화할 수 있다는 것입니다.

하지만 수렴은 여전히 약간 혼란스러울 수 있으며 경사 벡터가 모두 0이면 멈출 수도 있습니다. 최솟값을 찾았다는 뜻일까요? 항상 그렇지는 않습니다. 그라데이션 구성요소는 최솟값이나 최댓값이 0일 수 있습니다. 수백만 개의 요소가 있는 경사 벡터에서 요소가 모두 0인 경우 모든 0이 최솟값에 해당하고 어느 것도 최댓값에 해당하지 않을 확률은 매우 작습니다. 여러 차원의 공간에서 안장점은 매우 일반적이며 여기서 멈추고 싶지 않습니다.

52e824fe4716c4a0.png

삽화: 새들 포인트 경사는 0이지만 모든 방향에서 최솟값은 아닙니다. (이미지 저작자 표시 Wikimedia: By Nicoguaro - own work, CC BY 3.0)

해결책은 최적화 알고리즘에 모멘텀을 더하여 멈추지 않고 안장 지점을 지나 항해할 수 있도록 하는 것입니다.

용어집

배치 또는 미니 배치: 항상 학습 데이터 및 라벨 배치에 대해 학습이 수행됩니다. 이렇게 하면 알고리즘이 수렴되는 데 도움이 됩니다. '배치' 차원은 일반적으로 데이터 텐서의 첫 번째 차원입니다. 예를 들어 형태가 [100, 192, 192, 3] 인 텐서에는 픽셀당 3개의 값 (RGB)이 있는 192x192픽셀 이미지 100개가 포함됩니다.

교차 엔트로피 손실: 분류기에서 자주 사용되는 특수한 손실 함수입니다.

밀집 레이어: 각 뉴런이 이전 레이어의 모든 뉴런과 연결되는 뉴런 레이어입니다.

특성: 신경망의 입력을 '특성'이라고 부르기도 합니다. 좋은 예측을 하기 위해 데이터 세트의 어떤 부분 (또는 부분의 조합)을 신경망에 입력해야 하는지 알아내는 기술을 '특성 추출'이라고 합니다.

labels: '클래스'의 다른 이름 지도 분류 문제에서 정답과 같은

학습률: 학습 루프의 각 반복에서 가중치와 편향이 업데이트되는 경사의 비율입니다.

로지트: 활성화 함수가 적용되기 전의 뉴런 레이어의 출력을 '로지트'라고 합니다. 이 용어는 '로지스틱 함수'에서 유래했습니다. '시그모이드 함수'라고도 합니다. 이는 가장 인기 있는 활성화 함수였습니다. '로지스틱 함수 이전의 뉴런 출력' 'logits'로 단축되었습니다.

loss: 신경망 출력을 정답과 비교하는 오류 함수

뉴런: 입력의 가중 합계를 계산하고 편향을 더한 후 활성화 함수를 통해 결과를 제공합니다.

원-핫 인코딩: 클래스 5개 중 3개가 5개 요소로 구성된 벡터로 인코딩됩니다. 이때 세 번째 원-핫 인코딩은 1인 클래스만 제외하고 모두 0입니다.

relu: 정류 선형 유닛입니다. 뉴런에 널리 사용되는 활성화 함수입니다.

시그모이드: 예전에는 널리 사용되어 왔지만 특별한 경우에 여전히 유용한 또 다른 활성화 함수입니다.

소프트맥스: 벡터에서 작동하고, 가장 큰 구성요소와 다른 구성요소 간의 차이를 늘리고, 확률 벡터로 해석될 수 있도록 벡터를 합계가 1이 되도록 정규화합니다. 분류기의 마지막 단계로 사용됩니다.

tensor: '텐서' 는 행렬과 같지만, 임의의 차원 수를 사용합니다. 1차원 텐서는 벡터입니다. 2차원 텐서는 행렬입니다. 그런 다음 3차원, 4차원, 5차원 또는 그 이상의 차원을 가진 텐서를 사용할 수 있습니다.

5. [정보] 컨볼루셔널 신경망

요약

다음 단락에서 굵게 표시된 모든 용어를 이미 알고 있는 경우 다음 실습으로 이동할 수 있습니다. 컨볼루셔널 신경망을 이제 막 배우셨다면 계속 읽어 보시기 바랍니다.

convolutional.gif

그림: 각각 4x4x3=48의 학습 가능 가중치로 구성된 2개의 연속된 필터로 이미지를 필터링하고 있습니다.

Keras에서 간단한 컨볼루셔널 신경망은 다음과 같습니다.

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

컨볼루셔널 신경망 기초

컨볼루셔널 신경망의 레이어에는 하나의 '뉴런'이 는 이미지의 작은 영역에 대해서만 바로 위에 있는 픽셀의 가중 합계를 수행합니다. 일반 밀집 레이어의 뉴런처럼 편향을 추가하고 활성화 함수를 통해 합계를 제공합니다. 그런 다음 동일한 가중치를 사용하여 전체 이미지에서 이 연산을 반복합니다. 밀집 레이어에서 각 뉴런에는 고유한 가중치가 있다는 점을 기억하세요. 여기에서는 단일 '패치'가 이미지에서 양방향으로 슬라이드되는 가중치의 비율('컨볼루션') 출력에는 이미지의 픽셀 수만큼의 값이 있습니다. 하지만 가장자리에는 일부 패딩이 필요합니다. 이는 4x4x3=48 가중치 필터를 사용하는 필터링 연산입니다.

하지만 48개의 가중치로는 충분하지 않습니다. 자유도를 더 추가하려면 새로운 가중치 집합으로 동일한 연산을 반복합니다. 그러면 새로운 필터 출력 세트가 생성됩니다. 'channel'이라고 하겠습니다. 출력의 R,G,B 채널을 입력 이미지의 채널과 비유하면 됩니다

스크린샷 2016-07-29(16.02.37.png)

새 차원을 추가하여 두 개 이상의 가중치 집합을 하나의 텐서로 합산할 수 있습니다. 이렇게 하면 컨볼루셔널 레이어에 대한 가중치 텐서의 일반적인 형태를 얻을 수 있습니다. 입력 및 출력 채널의 수가 매개변수이므로 컨볼루셔널 레이어를 스택하고 체이닝할 수 있습니다.

d1b557707bcd1cb9.png

삽화: 컨볼루셔널 신경망이 '정육면체'를 변환 데이터를 다른 '정육면체'로 확인할 수 있습니다

스트라이드 컨볼루션, 최대 풀링

2 또는 3의 스트라이드로 컨볼루션을 수행함으로써 결과로 생성되는 데이터 큐브를 수평 차원에서 축소할 수도 있습니다. 여기에는 두 가지 일반적인 방법이 있습니다.

  • 스트라이드 컨볼루션: 위와 같지만 스트라이드가 1보다 큰 슬라이딩 필터
  • 최대 풀링: MAX 연산을 적용하는 슬라이딩 윈도우 (일반적으로 2x2 패치에서 2픽셀마다 반복됨)

b2d4263bb8470b.gif

그림: 컴퓨팅 기간을 3픽셀 단위로 슬라이드하면 출력 값이 감소합니다. 스트라이드 컨볼루션 또는 최대 풀링 (2x2 윈도우에서 2의 스트라이드 슬라이딩의 최댓값)는 수평 차원에서 데이터 큐브를 축소하는 방법입니다.

온볼루셔널 분류기

마지막으로, 마지막 데이터 큐브를 평면화하고 밀집된 소프트맥스 활성화 레이어를 통해 피드하는 방식으로 분류 헤드를 연결합니다. 일반적인 컨볼루셔널 분류기는 다음과 같습니다.

4a61aaffb6cba3d1.png

삽화: 컨볼루셔널 및 소프트맥스 레이어를 사용하는 이미지 분류기 3x3 및 1x1 필터를 사용합니다. maxpool 레이어는 2x2 데이터 포인트 그룹의 최대 개수를 사용합니다. 분류 헤드는 소프트맥스 활성화를 통해 밀집 레이어로 구현됩니다.

Keras 사용 시

위에서 설명한 컨볼루셔널 스택은 다음과 같이 Keras로 작성할 수 있습니다.

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. [신규 정보] 최신 컨볼루셔널 아키텍처

요약

7968830b57b708c0.png

그림: 컨볼루셔널 '모듈'. 현 시점에서 가장 좋은 점은 무엇인가요? max-pool 레이어 다음에 1x1 컨볼루셔널 레이어나 레이어의 다른 조합이 나오나요? 모두 시도하고 결과를 연결하여 네트워크가 결정하게 합니다. 오른쪽: " inception' 컨볼루셔널 아키텍처를 살펴보겠습니다.

Keras에서 데이터 흐름이 안팎으로 분기될 수 있는 모델을 만들려면 모델 스타일입니다. 예를 들면 다음과 같습니다.

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

그 밖의 유용한 정보

작은 3x3 필터

40a7b15fb7dbe75c.png

이 그림에는 2개의 연속된 3x3 필터의 결과가 나와 있습니다. 결과에 기여한 데이터 포인트를 추적해 보세요. 이 두 개의 연속하는 3x3 필터는 5x5 영역의 일부 조합을 계산합니다. 5x5 필터로 계산하는 것과 정확히 동일한 조합은 아니지만 연속으로 두 개의 3x3 필터가 단일 5x5 필터보다 저렴하기 때문에 시도해 볼 가치가 있습니다.

1x1 컨볼루션?

fd7cac16f8ecb423.png

수학적으로 보면 '1x1'은 컨볼루션은 상수의 곱셈이며 그다지 유용한 개념은 아닙니다. 하지만 컨볼루셔널 신경망에서는 필터가 2D 이미지뿐만 아니라 데이터 큐브에도 적용된다는 점을 기억하세요. 따라서 '1x1'은 필터는 1x1 데이터 열의 가중 합계를 계산하고 (그림 참조) 데이터를 슬라이드하면 입력 채널의 선형 조합을 얻습니다. 이것은 실제로 유용합니다. 채널을 개별 필터링 작업의 결과라고 생각하면(예: '뾰족한 귀' 필터, '수염'에 대한 필터) 세 번째는 '슬릿 아이'이고 '1x1' 컨볼루셔널 레이어는 이러한 특성의 가능한 선형 조합을 여러 개 계산하므로 '고양이'를 찾을 때 유용할 수 있습니다. 게다가 1x1 레이어는 더 적은 가중치를 사용합니다.

7. 스퀴즈넷

아이디어를 한데 모으는 간단한 방법이 'Squeezenet' 문서를 참조하세요. 저자들은 1x1 및 3x3 컨볼루셔널 레이어만 사용하는 매우 간단한 컨볼루셔널 모듈 설계를 제안합니다.

1730ac375379269b.png

그림: 'fire 모듈'을 기반으로 하는 스퀴즈넷 아키텍처 이 커버는 1x1 층을 번갈아 가며 '압착'하는 수직 차원으로 들어오는 데이터에 이어 '확장'되는 2개의 병렬 1x1 및 3x3 컨볼루셔널 레이어 다시 한 번 살펴보겠습니다.

실습

이전 노트북에서 계속 진행하여 스퀴즈넷에서 영감을 받은 컨볼루셔널 신경망을 빌드합니다. 모델 코드를 Keras '기능 스타일'로 변경해야 합니다.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

추가 정보

이 연습에서는 스퀴즈넷 모듈의 도우미 함수를 정의하는 것이 유용합니다.

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

이번에는 80% 의 정확성을 달성하는 것이 목표입니다.

시도해 볼 수 있는 작업

하나의 컨볼루셔널 레이어로 시작한 다음 'fire_modules'와 MaxPooling2D(pool_size=2) 레이어를 번갈아 가며 사용합니다. 네트워크에서 2~4개의 최대 풀링 레이어를 실험할 수 있으며, 최대 풀링 레이어 사이에 1개, 2개 또는 3개의 연속 파이어 모듈을 사용해 실험할 수도 있습니다.

Firestore 모듈의 'squeeze'는 매개변수는 일반적으로 '확장'보다 작아야 합니다. 매개변수 값으로 사용됩니다. 이러한 매개변수는 실제로는 필터의 수입니다. 일반적으로 8에서 196까지 가능합니다. 네트워크를 통해 필터 수가 점진적으로 증가하는 아키텍처 또는 모든 Fire 모듈에 동일한 수의 필터가 있는 간단한 아키텍처를 실험해 볼 수 있습니다.

예를 들면 다음과 같습니다.

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

이 시점에서 실험이 잘 진행되지 않고 있고 80% 정확성 목표는 멀어지는 것처럼 보일 수 있습니다. 이제 몇 가지 저렴한 방법을 더 추천해 드리겠습니다.

배치 정규화

Batch norm은 발생한 수렴 문제를 해결하는 데 도움이 됩니다. 다음 워크숍에서 이 기법에 대한 자세한 설명이 있습니다. 지금은 블랙박스 '마법'으로 사용하세요. help_module 함수 내부의 레이어를 포함하여 네트워크의 모든 컨볼루셔널 레이어 뒤에 다음 줄을 추가합니다.

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

모멘텀 매개변수는 기본값인 0.99에서 0.9로 줄여야 합니다. 데이터 세트가 작기 때문입니다. 지금은 이 세부정보를 무시하셔도 됩니다.

데이터 증강

채도를 좌우로 뒤집는 것과 같은 간단한 변환을 통해 데이터를 보강하면 몇 퍼센트포인트를 더 얻을 수 있습니다.

4ed2958e09b487ca.png

ad795b70334e0d6b.png

tf.data.Dataset API를 사용하면 Tensorflow에서 아주 쉽게 할 수 있습니다. 데이터에 대한 새 변환 함수를 정의합니다.

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

그런 다음 이를 최종 데이터 변환('학습 및 검증 데이터 세트', 함수 'get_batched_dataset' 셀)에서 사용합니다.

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

데이터 증강을 선택사항으로 만들고 필요한 코드를 추가하여 학습 데이터 세트만 증강되도록 하는 것을 잊지 마세요. 검증 데이터 세트를 보강하는 것은 의미가 없습니다.

이제 35세대에서 80% 의 정확도가 도달합니다.

해결 방법

다음은 솔루션 노트북입니다. 문제가 있을 때 사용할 수 있습니다.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

학습한 내용

  • 🤔 Keras '기능적 스타일' 모델
  • 🤓 Squeezenet 아키텍처
  • 🤓 tf.data.datset를 사용한 데이터 증강

잠시 시간을 내어 이 체크리스트를 머릿속에 살펴보세요.

8. Xception 미세 조정됨

분리 가능한 컨볼루션

최근 컨볼루셔널 레이어를 구현하는 다른 방법이 인기를 끌고 있는데 바로 깊이 분리 가능한 컨볼루션입니다. 한마디씩 하는 말이지만 개념은 매우 간단합니다. Tensorflow 및 Keras에서 tf.keras.layers.SeparableConv2D로 구현됩니다.

분리 가능한 컨볼루션은 이미지에서 필터를 실행하지만 입력 이미지의 각 채널에 고유한 가중치 집합을 사용합니다. '1x1 컨볼루션'이 뒤따르며, '1x1 컨볼루션'은 필터링된 채널의 가중치 합계를 구하는 일련의 내적입니다. 매번 새로운 가중치를 사용하면 채널의 가중치가 적용된 재조합이 필요한 만큼 계산됩니다.

615720b803bf8dda.gif

그림: 분리 가능한 컨볼루션. 1단계: 각 채널에 별도의 필터가 있는 컨볼루션 2단계: 채널의 선형 재조합 원하는 출력 채널 수에 도달할 때까지 새로운 가중치 세트로 반복합니다. 1단계도 매번 새로운 가중치로 반복할 수 있지만 실제로는 거의 그렇지 않습니다.

분리 가능한 컨볼루션은 MobileNetV2, Xception, EfficientNet 등 최신 컨볼루셔널 네트워크 아키텍처에서 사용됩니다. 참고로 MobileNetV2는 이전에 전이 학습에 사용한 것입니다.

일반 컨볼루션보다 저렴하며 실제로 동일하게 효과가 있는 것으로 확인되었습니다. 다음은 위 예시의 가중치 수입니다.

컨볼루셔널 레이어: 4 x 4 x 3 x 5 = 240

분리 가능한 컨볼루셔널 레이어: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63

각 스타일의 컨볼루셔널 레이어 스케일 스타일을 비슷한 방식으로 적용하는 데 필요한 곱셈의 개수를 계산하는 것은 독자가 연습해야 합니다. 분리 가능한 컨볼루션은 더 작고 계산 면에서 훨씬 효과적입니다.

실습

'전이 학습'에서 다시 시작 이번에는 선행 학습된 모델로 Xception을 선택합니다. Xception은 분리 가능한 컨볼루션만 사용합니다. 모든 가중치를 학습 가능한 상태로 둡니다. 우리는 선행 학습된 레이어를 사용하는 대신 데이터에 대해 선행 학습된 가중치를 미세하게 조정할 것입니다.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

목표: 정확성 > 95% (아니요, 가능성이 있습니다.)

이 연습이 마지막 연습이므로, 약간의 코드와 데이터 과학 작업이 더 많이 필요합니다.

미세 조정에 대한 추가 정보

Xception은 tf.keras.application.*의 선행 학습된 표준 모델에서 사용할 수 있습니다. 이번에는 모든 가중치를 학습 가능한 상태로 두는 것을 잊지 마세요.

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

모델을 미세 조정할 때 좋은 결과를 얻으려면 학습률에 주의를 기울이고 적응 기간이 있는 학습률 일정을 사용해야 합니다. 다음 행을 추가하면 됩니다.

9b1af213b2b36d47.png

표준 학습률로 시작하면 모델의 선행 학습된 가중치가 중단됩니다. 시작하면 모델이 합리적인 방식으로 데이터를 수정할 수 있을 때까지 점진적으로 보존됩니다. 램프 이후에는 학습률을 일정하게 유지하거나 기하급수적으로 감소하는 학습률을 계속 유지할 수 있습니다.

Keras에서 학습률은 각 에포크에 적절한 학습률을 계산할 수 있는 콜백을 통해 지정됩니다. Keras는 각 에포크의 옵티마이저에 올바른 학습률을 전달합니다.

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

해결 방법

다음은 솔루션 노트북입니다. 문제가 있을 때 사용할 수 있습니다.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

학습한 내용

  • 🤔 깊이 분리 가능한 컨볼루션
  • 🤓 학습률 일정
  • 🏈 선행 학습된 모델 미세 조정하기

잠시 시간을 내어 이 체크리스트를 머릿속에 살펴보세요.

9. 축하합니다.

최초의 최신 컨볼루셔널 신경망을 빌드하고 90% 이상의 정확도로 학습시켰으며, TPU를 활용하여 단 몇 분 만에 연속적인 학습을 반복했습니다. 이로써 4가지 'TPU 기반 Keras' Codelab을 마칩니다.

TPU의 실제 사용 사례

TPU 및 GPU는 Cloud AI Platform에서 사용할 수 있습니다.

마지막으로, YouTube는 고객의 의견을 소중하게 생각합니다. 이 실습에서 부족한 부분이 있거나 개선이 필요하다고 생각되는 부분이 있으면 알려 주세요. 의견은 GitHub 문제[의견 링크]를 통해 제공할 수 있습니다.

HR.png

마틴 괴르너 ID small.jpg
작성자: 마틴 괴르너
트위터: @martin_gorner

TensorFlow 로고.jpg
www.tensorflow.org