Багуля заключается в следующем. Предположим, мы хотим заимплементить Standard score, ну или какой-нибудь z-score whitening для картинок или эмбеддингов. Делается это примерно так:
def whiten(tensor):
mean = tf.math.reduce_mean(tensor)
std = tf.math.reduce_std(tensor)
return tf.math.divide_no_nan(tensor - mean, std)
Но на некоторых инпутах код сломается, начиная с вот этого коммита (ни в какую релизную версию и даже в Colab он еще не попал). Как думаете, в чём тут проблема? Ответ за спойлером:
При константых инпутах дисперсия внутри tf.math.reduce_std равна нулю, а градиент 0/0 – NaN. Начиная с этого коммита, этот NaN прекратили прятать, так что теперь любая модель с криво написанной нормализацией улетит в NaN. Корректным будет такой код (телеграм не умеет в код под спойлерами):
def whiten(tensor, epsilon=1e-6):
mean = tf.math.reduce_mean(tensor)
std = tf.math.sqrt(tf.math.reduce_variance(tensor) + epsilon)
return tf.math.divide_no_nan(tensor - mean, std)
Вот так бывает. Я нашел ~500 некорректных использований такого паттерна на гитхабе, и еще сколько-то во внутреннем коде. Посмотрим, будут ли править.