Обучение с Keras / TensorFlow в fp16 / половинной точности для карт RTX
У меня только что появился RTX 2070 Super, и я хотел бы попробовать тренировку с половинной точностью с использованием Keras и серверной части TensorFlow.
Пока что я нашел статьи, подобные этой, в которых предлагается использовать следующие настройки:
import keras.backend as K
dtype='float16'
K.set_floatx(dtype)
# default is 1e-7 which is too small for float16. Without adjusting the epsilon, we will get NaN predictions because of divide by zero problems
K.set_epsilon(1e-4)
Сеть представляет собой простую четырехуровневую CNN для классификации аудио.
Мои входные данные - это 3D-массив NumPy, сгенерированный ранее (функции аудио MFCC, извлеченные с помощью LibROSA). Эти данные были сгенерированы с использованием ЦП, и я понимаю, что значения сохраняются как 32-битные числа с плавающей запятой.
Когда я пытаюсь обучить свою сеть с помощью этих данных, я получаю следующую ошибку:
TypeError: тензоры в списке, переданном на 'input' операции 'Merge', имеют типы [float16, float32], которые не все совпадают.
В другой статье я прочитал, что мне также следует "вернуть FP32 перед слоем SoftMax", что еще больше сбивает с толку...
Я был бы очень признателен за ориентацию.
Спасибо!
1 ответ
Трудно узнать причину несоответствия dtype, не зная архитектуры модели. Но я думаю, что у него есть слой BatchNorm перед слиянием.
В этом случае причина как слияния, так и рекомендации softmax будет той же: во время операций, связанных с вычислением статистики (среднее / дисперсия), предпочтительно использовать float32. Это связано с тем, что с float16 ошибки точности могут быть слишком большими и давать неточные результаты, особенно при делениях.
Я не пробовал, но в слое Keras(по крайней мере 2.2.5) BatchNormalization при использовании Tensorflow в качестве бэкэнда дисперсия преобразуется в float32.
if K.backend() != 'cntk':
sample_size = K.prod([K.shape(inputs)[axis]
for axis in reduction_axes])
sample_size = K.cast(sample_size, dtype=K.dtype(inputs))
if K.backend() == 'tensorflow' and sample_size.dtype != 'float32':
sample_size = K.cast(sample_size, dtype='float32')
# sample variance - unbiased estimator of population variance
variance *= sample_size / (sample_size - (1.0 + self.epsilon))
Возможно, получившийся тензор после нормализации не преобразуется обратно в float16 и приводит к ошибке. Чтобы решить эту проблему, вы можете удалить BatchNorm для подтверждения, а затем изменить свою локальную копию keras или реализовать собственный BatchNorm, который после нормализации преобразуется обратно в float16.