이 페이지는 Cloud Translation API를 통해 번역되었습니다.
Switch to English

혼합 정밀도

TensorFlow.org에서보기 Google Colab에서 실행 GitHub에서 소스보기 노트북 다운로드

개요

혼합 정밀도는 훈련 중에 모델에서 16 비트 및 32 비트 부동 소수점 유형을 모두 사용하여 더 빠르게 실행하고 메모리를 적게 사용하는 것입니다. 수치 안정성을 위해 모델의 특정 부분을 32 비트 유형으로 유지함으로써 모델은 정확도와 같은 평가 메트릭스 측면에서 더 낮은 단계 시간을 가지며 동일하게 학습합니다. 이 안내서는 실험적인 Keras 혼합 정밀 API를 사용하여 모델 속도를 높이는 방법을 설명합니다. 이 API를 사용하면 최신 GPU에서 3 배 이상, TPU에서 60 % 이상 성능을 향상시킬 수 있습니다.

오늘날 대부분의 모델은 32 비트 메모리를 사용하는 float32 dtype을 사용합니다. 그러나 정밀도가 낮은 dtype 인 float16과 bfloat16이 있으며 각각 16 비트의 메모리를 사용합니다. 최신 가속기는 16 비트 계산을 실행할 수있는 특수 하드웨어가 있고 16 비트 dtype을 메모리에서 더 빨리 읽을 수 있으므로 16 비트 dtype에서 작업을 더 빠르게 실행할 수 있습니다.

NVIDIA GPU는 float32보다 float16에서 작업을 더 빠르게 실행할 수 있고 TPU는 float32보다 bfloat16에서 작업을 더 빨리 실행할 수 있습니다. 따라서 이러한 정밀도가 낮은 dtype은 해당 장치에서 가능할 때마다 사용해야합니다. 그러나 변수와 몇 가지 계산은 여전히 ​​숫자로 인해 float32에 있어야 모델이 동일한 품질로 학습합니다. Keras 혼합 정밀도 API를 사용하면 float16 또는 bfloat16을 float32와 혼합하여 float16 / bfloat16의 성능 이점과 float32의 숫자 안정성 이점을 얻을 수 있습니다.

설정

Keras 혼합 정밀도 API는 TensorFlow 2.1에서 사용 가능합니다.

 import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.mixed_precision import experimental as mixed_precision
 

지원되는 하드웨어

혼합 정밀도는 대부분의 하드웨어에서 실행되지만 최신 NVIDIA GPU 및 Cloud TPU의 모델 속도 만 향상시킵니다. NVIDIA GPU는 float16과 float32의 혼합 사용을 지원하는 반면 TPU는 bfloat16과 float32의 혼합을 지원합니다.

NVIDIA GPU 중 계산 기능이 7.0 이상인 프로세서는 float16 매트릭스 곱셈 및 컨볼 루션을 가속화하기 위해 Tensor Cores라는 특수 하드웨어 장치가 있기 때문에 혼합 정밀도의 최대 성능 이점을 볼 수 있습니다. 구형 GPU는 혼합 정밀도 사용에 대한 수학 성능 이점을 제공하지 않지만 메모리 및 대역폭 절약은 일부 속도 향상을 가능하게합니다. NVIDIA CUDA GPU 웹 페이지 에서 GPU의 컴퓨팅 기능을 검색 할 수 있습니다. 혼합 정밀도의 이점이 가장 큰 GPU의 예로는 RTX GPU, Titan V 및 V100이 있습니다.

다음을 통해 GPU 유형을 확인할 수 있습니다. 이 명령은 NVIDIA 드라이버가 설치된 경우에만 존재하므로 다음과 같은 경우 오류가 발생합니다.

nvidia-smi -L
GPU 0: Tesla V100-SXM2-16GB (UUID: GPU-843a0a0c-a559-ff09-842e-2a4fdb142480)

모든 Cloud TPU는 bfloat16을 지원합니다.

속도 향상이 예상되지 않는 CPU 및 구형 GPU에서도 혼합 정밀 API를 사용하여 단위 테스트, 디버깅 또는 API를 시험해 볼 수 있습니다.

dtype 정책 설정

tf.keras.mixed_precision.experimental.Policy 에서 혼합 정밀도를 사용하려면 일반적으로 dtype 정책 이라고하는 tf.keras.mixed_precision.experimental.Policy 를 작성해야합니다. Dtype 정책은 dtypes 레이어가 실행될 dtypes를 지정합니다.이 안내서에서는 문자열 'mixed_float16' 에서 정책을 구성하고이를 전역 정책으로 설정합니다. 이로 인해 이후에 생성 된 레이어가 float16과 float32를 혼합하여 혼합 정밀도를 사용하게됩니다.

 policy = mixed_precision.Policy('mixed_float16')
mixed_precision.set_policy(policy)
 

이 정책은 레이어의 두 가지 중요한 측면, 즉 레이어 계산이 수행되는 dtype과 레이어 변수의 dtype을 지정합니다. 위에서 mixed_float16 정책 (즉, 문자열 'mixed_float16' 을 생성자에 전달하여 만든 mixed_precision.Policy 만들었습니다. 이 정책에서 레이어는 float16 계산 및 float32 변수를 사용합니다. 계산은 성능을 위해 float16에서 수행되지만 숫자 안정성을 위해서는 변수를 float32로 유지해야합니다. 이러한 정책 속성을 직접 쿼리 할 수 ​​있습니다.

 print('Compute dtype: %s' % policy.compute_dtype)
print('Variable dtype: %s' % policy.variable_dtype)
 
Compute dtype: float16
Variable dtype: float32

앞에서 언급했듯이 mixed_float16 정책은 7.0 이상의 컴퓨팅 기능으로 NVIDIA GPU의 성능을 가장 크게 향상시킵니다. 이 정책은 다른 GPU 및 CPU에서 실행되지만 성능이 향상되지 않을 수 있습니다. TPU의 경우 mixed_bfloat16 정책을 대신 사용해야합니다.

모델 구축

다음으로 간단한 모델을 만들어 봅시다. TensorFlow 런타임의 오버 헤드가 일반적으로 실행 시간을 지배하여 GPU의 성능 향상을 무시할 수 있기 때문에 매우 작은 장난감 모델은 일반적으로 혼합 정밀도의 이점을 얻지 못합니다. 따라서 GPU를 사용하는 경우 각각 4096 개의 장치로 두 개의 큰 Dense 층을 만들어 봅시다.

 inputs = keras.Input(shape=(784,), name='digits')
if tf.config.list_physical_devices('GPU'):
  print('The model will run with 4096 units on a GPU')
  num_units = 4096
else:
  # Use fewer units on CPUs so the model finishes in a reasonable amount of time
  print('The model will run with 64 units on a CPU')
  num_units = 64
dense1 = layers.Dense(num_units, activation='relu', name='dense_1')
x = dense1(inputs)
dense2 = layers.Dense(num_units, activation='relu', name='dense_2')
x = dense2(x)
 
The model will run with 4096 units on a GPU

각 계층에는 정책이 있으며 기본적으로 글로벌 정책을 사용합니다. 따라서 전역 정책을 이전에 mixed_float16 설정했기 때문에 각 Dense 레이어에는 mixed_float16 정책이 있습니다. 이로 인해 밀도가 높은 레이어는 float16 계산을 수행하고 float32 변수를 갖게됩니다. float16 계산을 수행하기 위해 입력을 float16으로 캐스팅하여 결과적으로 출력이 float16이됩니다. 변수는 float32이며 dtype 불일치로 인한 오류를 피하기 위해 레이어를 호출하면 float16으로 캐스트됩니다.

 print('x.dtype: %s' % x.dtype.name)
# 'kernel' is dense1's variable
print('dense1.kernel.dtype: %s' % dense1.kernel.dtype.name)
 
x.dtype: float16
dense1.kernel.dtype: float32

다음으로 출력 예측을 작성하십시오. 일반적으로 다음과 같이 출력 예측을 작성할 수 있지만 float16에서는 항상 수치 적으로 안정적인 것은 아닙니다.

 # INCORRECT: softmax and model output will be float16, when it should be float32
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)
print('Outputs dtype: %s' % outputs.dtype.name)
 
Outputs dtype: float16

모델 끝에서 softmax 활성화는 float32 여야합니다. dtype 정책이 mixed_float16 이므로, softmax 활성화는 일반적으로 float16 계산 dtype을 가지며 float16 텐서를 출력합니다.

Dense와 softmax 레이어를 분리하고 dtype='float32' 를 softmax 레이어에 전달하면이 문제를 해결할 수 있습니다.

 # CORRECT: softmax and model output are float32
x = layers.Dense(10, name='dense_logits')(x)
outputs = layers.Activation('softmax', dtype='float32', name='predictions')(x)
print('Outputs dtype: %s' % outputs.dtype.name)
 
Outputs dtype: float32

dtype='float32' 를 softmax 레이어 생성자에 전달하면 레이어의 dtype 정책이 float32 정책으로 재정의되어 계산을 수행하고 변수를 float32로 유지합니다. 마찬가지로 dtype=mixed_precision.Policy('float32') 대신 전달할 수도 있습니다. 레이어는 항상 dtype 인수를 정책으로 변환합니다. Activation 계층에는 변수가 없으므로 정책의 변수 dtype은 무시되지만 정책의 계산 dtype float32는 softmax 및 모델 출력을 float32로 만듭니다.

모델 중간에 float16 softmax를 추가하는 것은 좋지만 모델 끝의 softmax는 float32에 있어야합니다. 그 이유는 softmax에서 손실까지 흐르는 중간 텐서가 float16 또는 bfloat16이면 숫자 문제가 발생할 수 있기 때문입니다.

float16 계산에서 수치 적으로 안정적이지 않다고 생각되면 dtype='float32' 를 전달하여 모든 레이어의 dtype을 float32로 재정의 할 수 있습니다. 그러나 대부분의 레이어는 mixed_float16mixed_bfloat16 과 함께 충분한 정밀도를 mixed_float16 때문에 일반적으로 모델의 마지막 레이어에서만 필요합니다.

모델이 softmax로 끝나지 않더라도 출력은 여전히 ​​float32 여야합니다. 이 특정 모델에는 필요하지 않지만 다음을 사용하여 모델 출력을 float32로 캐스트 할 수 있습니다.

 # The linear activation is an identity function. So this simply casts 'outputs'
# to float32. In this particular case, 'outputs' is already float32 so this is a
# no-op.
outputs = layers.Activation('linear', dtype='float32')(outputs)
 

그런 다음 모델을 완료하고 컴파일하고 입력 데이터를 생성하십시오.

 model = keras.Model(inputs=inputs, outputs=outputs)
model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop(),
              metrics=['accuracy'])

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255
 
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step

이 예제는 입력 데이터를 int8에서 float32로 캐스트합니다. 255로 나누기가 CPU에 있으며 float32 연산보다 float16 연산이 느리기 때문에 float16으로 캐스트하지 않습니다. 이 경우 성능 차이는 무시할 만하지 만 일반적으로 CPU에서 실행되는 경우 float32에서 입력 처리 수학을 실행해야합니다. 각 레이어는 부동 소수점 입력을 계산 dtype에 캐스트하므로 모델의 첫 번째 레이어는 입력을 float16으로 캐스트합니다.

모델의 초기 가중치가 검색됩니다. 그러면 웨이트를로드하여 처음부터 다시 훈련 할 수 있습니다.

 initial_weights = model.get_weights()
 

Model.fit으로 모델 훈련

다음으로 모델을 훈련시킵니다.

 history = model.fit(x_train, y_train,
                    batch_size=8192,
                    epochs=5,
                    validation_split=0.2)
test_scores = model.evaluate(x_test, y_test, verbose=2)
print('Test loss:', test_scores[0])
print('Test accuracy:', test_scores[1])

 
Epoch 1/5
6/6 [==============================] - 0s 55ms/step - loss: 4.4853 - accuracy: 0.4174 - val_loss: 0.8197 - val_accuracy: 0.7680
Epoch 2/5
6/6 [==============================] - 0s 28ms/step - loss: 0.7953 - accuracy: 0.7641 - val_loss: 0.4589 - val_accuracy: 0.8625
Epoch 3/5
6/6 [==============================] - 0s 27ms/step - loss: 0.3360 - accuracy: 0.9025 - val_loss: 0.3131 - val_accuracy: 0.8962
Epoch 4/5
6/6 [==============================] - 0s 27ms/step - loss: 0.3322 - accuracy: 0.8883 - val_loss: 0.2289 - val_accuracy: 0.9327
Epoch 5/5
6/6 [==============================] - 0s 27ms/step - loss: 0.2313 - accuracy: 0.9289 - val_loss: 0.2115 - val_accuracy: 0.9351
313/313 - 1s - loss: 0.2157 - accuracy: 0.9295
Test loss: 0.21573331952095032
Test accuracy: 0.9294999837875366

모델은 로그에 샘플 당 시간을 인쇄합니다 (예 : "4us / sample"). TensorFlow가 모델을 최적화하는 데 시간을 소비함에 따라 첫 번째 에포크가 느려질 수 있지만 이후 샘플 당 시간이 안정화되어야합니다.

Colab에서이 가이드를 실행하는 경우 혼합 정밀도의 성능과 float32를 비교할 수 있습니다. 이렇게하려면 "dtype 정책 설정"섹션에서 정책을 mixed_float16 에서 float32 로 변경 한 다음이 시점까지 모든 셀을 다시 실행하십시오. 컴퓨팅 성능이 7.0 이상인 GPU에서는 샘플 당 시간이 크게 증가하여 혼합 정밀도가 모델을 가속화 함을 나타냅니다. 예를 들어 Titan V GPU를 사용하면 샘플 당 시간이 4us에서 12us로 증가합니다. 가이드를 계속하기 전에 정책을 mixed_float16 으로 다시 변경하고 셀을 다시 실행하십시오.

많은 실제 모델의 경우, float16 텐서가 메모리의 절반을 차지하므로 혼합 정밀도를 사용하면 메모리 부족없이 배치 크기를 두 배로 늘릴 수 있습니다. 그러나 각 배치가 60,000 개의 이미지로 구성된 전체 MNIST 데이터 세트로 구성된 모든 dtype에서 모델을 실행할 수 있으므로이 장난감 모델에는 적용되지 않습니다.

TPU에서 혼합 정밀도를 실행하는 경우 GPU에서 혼합 정밀도를 실행하는 것과 비교하여 성능이 크게 향상되지는 않습니다. 이는 기본 dtype 정책 float32 로도 TPU가 이미 bfloat16에서 특정 작업을 수행하기 때문입니다. TPU 하드웨어는 matmul과 같이 bfloat16에서 수치 적으로 안정적인 특정 op에 대해 float32를 지원하지 않습니다. 이러한 운영 체제의 경우 TPU 백엔드는 내부적으로 bfloat16을 자동으로 사용합니다. 결과적으로, 그러한 ops를 사용하는 레이어에 dtype='float32' 를 전달하는 dtype='float32' 수치 적 영향을 미치지 않을 수 있지만, bfloat16 계산으로 그러한 레이어를 실행하는 것은 거의 불가능합니다.

손실 규모

손실 스케일링 기술이다 tf.keras.Model.fit 자동으로 수행 mixed_float16 숫자 언더 플로우를 방지하기 위해 정책을. 이 섹션에서는 손실 스케일링 및 해당 동작을 사용자 정의하는 방법에 대해 설명합니다.

언더 플로 및 오버플로

float16 데이터 형식은 float32에 비해 동적 범위가 좁습니다. 이는 $ 65504 $ 이상의 값은 무한대로 오버 플로우되고 $ 6.0 \ times 10 ^ {-8} $ 미만의 값은 0으로 언더 플로됨을 의미합니다. float32 및 bfloat16은 동적 범위가 훨씬 높아 오버플로 및 언더 플로가 문제가되지 않습니다.

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

 x = tf.constant(256, dtype='float16')
(x ** 2).numpy()  # Overflow
 
inf
 x = tf.constant(1e-5, dtype='float16')
(x ** 2).numpy()  # Underflow
 
0.0

실제로 float16으로 오버플로가 거의 발생하지 않습니다. 또한 전달 과정에서 언더 플로가 거의 발생하지 않습니다. 그러나 뒤로 통과하는 동안 그라디언트가 0으로 언더 플로 될 수 있습니다. 손실 스케일링은 이러한 언더 플로를 방지하는 기술입니다.

손실 스케일링 배경

손실 스케일링의 기본 개념은 간단합니다. 손실에 약간의 숫자 (예 : $ 1024 $)를 곱하면됩니다. 우리는이 숫자를 손실 규모 라고 부릅니다. 그래디언트 크기를 $ 1024 $까지 확장하여 언더 플로 가능성을 크게 줄입니다. 최종 그래디언트가 계산되면 $ 1024 $로 나눠서 올바른 값으로 되돌립니다.

이 프로세스의 의사 코드는 다음과 같습니다.

 loss_scale = 1024
loss = model(inputs)
loss *= loss_scale
# We assume `grads` are float32. We do not want to divide float16 gradients
grads = compute_gradient(loss, model.trainable_variables)
grads /= loss_scale
 

손실 척도를 선택하는 것은 까다로울 수 있습니다. 손실 스케일이 너무 낮 으면 그래디언트가 여전히 0으로 흘러 갈 수 있습니다. 너무 높으면 반대의 문제가 발생합니다. 그래디언트가 무한대로 넘칠 수 있습니다.

이를 해결하기 위해 TensorFlow는 손실 스케일을 동적으로 결정하므로 수동으로 선택할 필요가 없습니다. tf.keras.Model.fit 을 사용하면 손실 스케일링이 수행되므로 추가 작업을 수행 할 필요가 없습니다. 이에 대해서는 다음 섹션에서 자세히 설명합니다.

손실 척도 선택

각 dtype 정책에는 선택적으로 관련 tf.mixed_precision.experimental.LossScale 오브젝트가 있으며, 이는 고정 또는 동적 손실 스케일을 나타냅니다. 기본적으로 mixed_float16 정책의 손실 규모는 tf.mixed_precision.experimental.DynamicLossScale 이며, 손실 규모 값을 동적으로 결정합니다. 다른 정책은 float16을 사용할 때만 필요하므로 기본적으로 손실 규모가 없습니다. 정책의 손실 규모를 쿼리 할 수 ​​있습니다.

 loss_scale = policy.loss_scale
print('Loss scale: %s' % loss_scale)
 
Loss scale: DynamicLossScale(current_loss_scale=32768.0, num_good_steps=30, initial_loss_scale=32768.0, increment_period=2000, multiplier=2.0)

손실 규모는 많은 내부 상태를 인쇄하지만 무시해도됩니다. 가장 중요한 부분은 current_loss_scale 부분으로, 손실 스케일의 현재 값을 보여줍니다.

대신 dtype 정책을 구성 할 때 숫자를 전달하여 정적 손실 척도를 사용할 수 있습니다.

 new_policy = mixed_precision.Policy('mixed_float16', loss_scale=1024)
print(new_policy.loss_scale)
 
FixedLossScale(1024.0)

dtype 정책 생성자는 항상 손실 규모를 LossScale 객체로 변환합니다. 이 경우 DynamicLossScale 이외의 유일한 LossScale 서브 클래스 인 tf.mixed_precision.experimental.FixedLossScale 로 변환됩니다.

레이어와 같은 모델에는 각각 dtype 정책이 있습니다. 존재하는 경우, 모델은 정책의 손실 스케일을 사용하여 tf.keras.Model.fit 메소드에서 손실 스케일링을 적용합니다. 이는 Model.fit 을 사용하는 경우 손실 스케일링에 대해 전혀 걱정할 필요가 없음을 의미합니다. mixed_float16 정책은 기본적으로 동적 손실 스케일을 가지며 Model.fit 를 적용합니다.

사용자 지정 교육 루프를 사용하면 모델이 정책의 손실 규모를 무시하므로 수동으로 적용해야합니다. 이에 대해서는 다음 섹션에서 설명합니다.

맞춤형 교육 루프를 사용하여 모델 교육

지금까지 tf.keras.Model.fit 사용하여 혼합 정밀도로 tf.keras.Model.fit 모델을 tf.keras.Model.fit . 다음으로, 맞춤 훈련 루프와 함께 혼합 정밀도를 사용합니다. 맞춤 교육 루프가 무엇인지 아직 모르는 경우 먼저 맞춤 교육 안내서 를 읽으 십시오 .

혼합 정밀도로 맞춤형 교육 루프를 실행하려면 float32에서 실행하는 것보다 두 가지 변경이 필요합니다.

  1. 혼합 정밀도로 모델을 작성하십시오 (이미 수행했습니다)
  2. mixed_float16 을 사용하는 경우 명시 적으로 손실 스케일링을 사용하십시오.

2 단계에서는 옵티 마이저를 랩핑하고 손실 스케일링을 적용하는 tf.keras.mixed_precision.experimental.LossScaleOptimizer 클래스를 사용합니다. 옵티 마이저와 손실 스케일이라는 두 가지 인수가 필요합니다. 동적 손실 척도를 사용하려면 다음과 같이 구성하십시오.

 optimizer = keras.optimizers.RMSprop()
optimizer = mixed_precision.LossScaleOptimizer(optimizer, loss_scale='dynamic')
 

'dynamic' 전달은 tf.mixed_precision.experimental.DynamicLossScale() 전달과 동일합니다.

다음으로 손실 객체와 tf.data.Dataset 정의하십시오.

 loss_object = tf.keras.losses.SparseCategoricalCrossentropy()
train_dataset = (tf.data.Dataset.from_tensor_slices((x_train, y_train))
                 .shuffle(10000).batch(8192))
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(8192)
 

다음으로 훈련 단계 기능을 정의하십시오. 손실을 최적화하고 그래디언트를 스케일링 해제하기 위해 손실 스케일 최적화 프로그램의 두 가지 새로운 방법이 사용됩니다.

  • get_scaled_loss(loss) : 손실에 손실 스케일을 곱합니다
  • get_unscaled_gradients(gradients) : 스케일 된 그라디언트 목록을 입력으로 취하고 각각을 손실 스케일로 나누어 스케일을 해제합니다.

그래디언트의 언더 플로를 방지하려면 이러한 기능을 사용해야합니다. LossScaleOptimizer.apply_gradients 는 Infs 또는 NaN이없는 그래디언트를 적용합니다. 또한 그라디언트에 Infs 또는 NaN이 있으면 절반으로 줄이고 손실 가능성을 높이면 손실 규모가 업데이트됩니다.

 @tf.function
def train_step(x, y):
  with tf.GradientTape() as tape:
    predictions = model(x)
    loss = loss_object(y, predictions)
    scaled_loss = optimizer.get_scaled_loss(loss)
  scaled_gradients = tape.gradient(scaled_loss, model.trainable_variables)
  gradients = optimizer.get_unscaled_gradients(scaled_gradients)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))
  return loss
 

LossScaleOptimizer 는 교육 시작시 처음 몇 단계를 건너 뛸 수 있습니다. 최적의 손실 규모를 신속하게 결정할 수 있도록 손실 규모가 크게 시작됩니다. 몇 단계를 거치면 손실 규모가 안정화되고 몇 단계 만 건너 뜁니다. 이 프로세스는 자동으로 수행되며 교육 품질에는 영향을 미치지 않습니다.

이제 테스트 단계를 정의하십시오.

 @tf.function
def test_step(x):
  return model(x, training=False)
 

모델의 초기 중량을로드하여 처음부터 다시 학습 할 수 있습니다.

 model.set_weights(initial_weights)
 

마지막으로 사용자 지정 교육 루프를 실행하십시오.

 for epoch in range(5):
  epoch_loss_avg = tf.keras.metrics.Mean()
  test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(
      name='test_accuracy')
  for x, y in train_dataset:
    loss = train_step(x, y)
    epoch_loss_avg(loss)
  for x, y in test_dataset:
    predictions = test_step(x)
    test_accuracy.update_state(y, predictions)
  print('Epoch {}: loss={}, test accuracy={}'.format(epoch, epoch_loss_avg.result(), test_accuracy.result()))
 
Epoch 0: loss=4.186450004577637, test accuracy=0.8429999947547913
Epoch 1: loss=0.5681900382041931, test accuracy=0.9300000071525574
Epoch 2: loss=0.330956369638443, test accuracy=0.9405999779701233
Epoch 3: loss=0.2619778513908386, test accuracy=0.9279000163078308
Epoch 4: loss=0.17072156071662903, test accuracy=0.9229999780654907

GPU 성능 팁

다음은 GPU에서 혼합 정밀도를 사용할 때의 성능 팁입니다.

배치 크기 늘리기

모델 품질에 영향을 미치지 않으면 혼합 정밀도를 사용할 때 배치 크기의 두 배로 실행하십시오. float16 텐서가 절반의 메모리를 사용하므로 메모리 부족없이 배치 크기를 두 배로 늘릴 수 있습니다. 배치 크기를 늘리면 일반적으로 훈련 처리량, 즉 모델을 실행할 수있는 초당 훈련 요소가 증가합니다.

GPU 텐서 코어 사용 보장

앞에서 언급했듯이 최신 NVIDIA GPU는 16 개의 행렬을 매우 빠르게 부동화 할 수있는 텐서 코어라는 특수 하드웨어 장치를 사용합니다. 그러나 텐서 코어는 텐서의 특정 차원이 8의 배수 여야합니다. 아래 예에서 텐서 코어를 사용하기 위해 8의 배수 여야하는 경우에만 인수가 굵게 표시됩니다.

  • tf.keras.layers.Dense ( units = 64 )
  • tf.keras.layers.Conv2d ( 필터 = 48 , 커널 _ 크기 = 7, 보폭 = 3)
    • tf.keras.layers.Conv3d와 같은 다른 컨볼 루션 레이어와 유사합니다.
  • tf.keras.layers.LSTM ( units = 64 )
    • 그리고 tf.keras.layers.GRU와 같은 다른 RNN과 유사
  • tf.keras.Model.fit (epochs = 2, batch_size = 128 )

가능하면 텐서 코어를 사용하십시오. 자세한 내용을 보려면 NVIDIA 딥 러닝 성능 안내서에 텐서 코어 및 기타 텐서 코어 관련 성능 정보를 사용하기위한 정확한 요구 사항이 설명되어 있습니다.

XLA

XLA는 혼합 정밀도 성능과 float32 성능을 더 낮출 수있는 컴파일러입니다. 자세한 내용은 XLA 안내서 를 참조하십시오.

Cloud TPU 성능 팁

bfloat16 텐서는 메모리의 절반을 사용하므로 GPU와 마찬가지로 배치 크기를 두 배로 늘려보십시오. 배치 크기를 두 배로 늘리면 훈련 처리량이 증가 할 수 있습니다.

TPU는 최적의 성능을 얻기 위해 다른 혼합 정밀 조정이 필요하지 않습니다. TPU는 이미 XLA를 사용해야합니다. 그들은 특정 치수를 $ 128 $의 배수로 얻는 것이 유리하지만, 이것은 혼합 정밀도와 마찬가지로 float32에도 동일하게 적용됩니다. float32뿐만 아니라 혼합 정밀도에도 적용되는 일반적인 TPU 성능 팁은 Cloud TPU 성능 안내서 를 참조하십시오.

요약

  • 컴퓨팅 성능이 7.0 이상인 TPU 또는 NVIDIA GPU를 사용하는 경우 혼합 정밀도를 사용해야합니다. 성능이 최대 3 배 향상되기 때문입니다.
  • 다음 줄에 혼합 정밀도를 사용할 수 있습니다.
 # On TPUs, use 'mixed_bfloat16' instead
policy = tf.keras.mixed_precision.experimental.Policy('mixed_float16')
mixed_precision.set_policy(policy)
 
  • 모델이 softmax로 끝나는 경우 float32인지 확인하십시오. 모델의 결과에 관계없이 출력이 float32인지 확인하십시오.
  • mixed_float16 과 함께 사용자 지정 교육 루프를 사용하는 경우 위의 줄 외에도 tf.keras.mixed_precision.experimental.LossScaleOptimizer 옵티 마이저를 래핑해야합니다. 그런 다음 optimizer.get_scaled_loss 를 호출하여 손실을 조정하고 optimizer.get_unscaled_gradients 를 사용하여 그라디언트의 배율을 조정하십시오.
  • 평가 정확도가 떨어지지 않으면 훈련 배치 크기를 두 배로 늘리십시오.
  • GPU에서 성능을 최대화하려면 대부분의 텐서 크기가 $ 8 $의 배수가되도록하십시오

tf.keras.mixed_precision API를 사용한 혼합 정밀도의 더 많은 예는 공식 모델 저장소를 참조하십시오. ResNetTransformer 와 같은 대부분의 공식 모델은 --dtype=fp16 을 전달하여 혼합 정밀도로 실행됩니다.