При обучении нейросети получаются огромные числа, который python воспринимает как null, inf и не может продолжать вычисления

Рейтинг: 5Ответов: 2Опубликовано: 11.05.2023

обучаю нейросеть определять цифры на изображениях 24*24 px.

Принципиальное условие: не использовать библиотеки tensorflow, keras...

По мере того, как выполняется код, в промежуточных слоях нейросети получаются огромные числа, которые python воспринимает как nan и inf. После чего у него не получается выполнять дальнейшие действия.

Вот пара мест, где происходит эта проблема:

1. Функция нормировки(применяется только к последнему слою нейросети):

    def SoftMax(self, t2):
        out = np.exp(t2)
        return out/np.sum(out)

Насколько я поимаю тут появляются inf, т.е. бесконечно большие числа.

2. Для вычисления ошибки используется категориальная кросс-энтропия.

    def CrossEntropy(self):
        error = np.log(self.res_vector[np.argmax(self.y)])
        return error

Насколько я понимаю тут порой появляются nan, т.е. бесконечно малые числа.

3. Далее пытаюсь выполнить градиентный шаг, а там inf и nan уже лежат:

# Вручную вычисляем градиенты на каждом слое и корректируем веса. 
    def back_propogation(self):
        dE_dt = self.res_vector - self.y
        i = self.N-2

        while i >= 0:
            if i > 0:
                dE_dw = self.H[i][None, ...].T @ dE_dt[None, ...]
                dE_db = dE_dt

                alpha = 0.001
                self.M[i+1] += alpha * dE_dw
                self.B[i+1] += alpha * dE_db

                dE_dh = dE_dt @ self.M[i+1].T
                dE_dt = dE_dh * self.ReluDeriv(self.S[i])
                i -= 1
            if i == 0:
                dE_dw = self.S[0][None, ...].T @ dE_dt[None, ...]
                dE_db = dE_dt

                self.M[i+1] += alpha * dE_dw
                self.B[i+1] += alpha * dE_db

                break

Ну и понятно, что в весах M[i] и B[i] уже не числа лежат...

Надо сказать, Tensorflow я тоже изучил. И там всё тоже самое, также можно вызывать функции softmax и crossentropy, просто у них не происходит таких неприятных переполнений. Вот мне хочется узнать, что я должен исправить в этих функциях чтоб такой проблемы не возникало. И ещё вопрос, можно ли вообще эти функции как-либо менять, ведь тогда и градиент надо будет ссчитать по-другому...

Поясню, я вдохновялся следующим матреиалом: https://www.youtube.com/playlist?list=PLOSf9rRg-fvJt5adxPbefB394QBtW9smZ

Автор видео сводит вычисления производных к перемножению матриц! Оно и логично, ведь зависимости везде линейные... Но его программа состояла из 1го промежуточного слоя, а моя - из произвольного количества нейронов. Именно поэтому в промежуточных слоях у меня накапливаются "плохие" числа :(

Я пробывал нормировать все значения на входном слое, пытался всячески зажимать интервалы в пределах от e^(-720) до e^(25), путем различных делений, и вроде всё было классно, но накапливаемая ошибка перестала уменьшаться в процессе обучения.

Мне показалось, что мои методы не работали, потому что python или numpy не ссчитал дробные числа дальше 7го знака после запятой... Во всяком случае в консоль так выводилось. Вообщем зашел в тупик, буду рад если окажете помощь :)

Приведу в пример несколько фото, может они внесут дополнительную ясность в то, что было по приложенной ссылке.

План нахождения градиентов

Рис.1

Пример как автор советовал искать компоненты градиента

Пример как автор советовал искать компоненты градиента

И вот эти формулы можно применять на каждом слое, поэтому они УНИКАЛЬНЫ. Вот я и обхожу в цикле все слои "справа-налево", и выполняю back-propogation. Заранее скажу, что backpropogation работает правильно, т.к. в тех случаях, когда по счастливой случайности переполнения НЕ возникали, нейросеть с точностью в 70% определяла цифры на тестовой выборке. А ещё очень приятно было смотреть на убывающую ошибку в процессе обучения...

Поэтому с уверенностью заверяю что проблема в этих inf и nan, помогите пожалуйста.

Ответы

▲ 1

Насчёт nan и inf я понял:

график логарифма

На единице значение достигает нуля и и уходит в отрицательные, а там уже и nan недалеко.

график экспоненты

А здесь 50 похоже уже до бесконечности. Но ваши текстовые утверждения верны. Можно попробовать другую функцию нормировки, например сигмоиду. И другой метод вычисления ошибки, например mean squared error.

▲ 0

Удалось избавиться от нежелательных больших чисел в функции softmax, смотрите как: https://russianblogs.com/article/87702691403/

введите сюда описание изображения

Но прикол в том, что когда мы отнимем M, мы рискуем получить супер-маленькое число и тогда в знаменателе, там где сумма, может появиться nan.

В целом, ошибка по-прежнему не пропала. Точности вычисления по-прежнему не хватает.