Нейронная сеть не учится умножению (Игрушечный пример) - PullRequest
0 голосов
/ 09 мая 2018

Набор данных игрушек

  • Входы : два целых числа: a и b
  • Вывод : одно целое число, которое должно быть произведением a и b
  • 8000 учебных примеров

Образец моего X_train:

    array([[ 6220, 15403],
           [ 3197,  8054],
           [ 1723,  3711],
           ...,
           [ 9500, 14979],
           [ 2642, 16547],
           [15169, 19332]], dtype=int64)

Образец моего Y_train:

    array([ 95806660,  25748638,   6394053, ..., 142300500,  43717174,
            293247108], dtype=int64)

Модель

    def get_model():
        model = Sequential()
        model.add(Dense(20, input_shape=(2,), kernel_initializer='normal', activation='linear'))
        model.add(LeakyReLU(alpha=.001))
        model.add(Dense(20, kernel_initializer='normal', activation='linear'))
        model.add(LeakyReLU(alpha=.001))
        model.add(Dense(20, kernel_initializer='normal', activation='linear'))
        model.add(LeakyReLU(alpha=.001))
        model.add(Dense(20, kernel_initializer='normal', activation='linear'))
        model.add(LeakyReLU(alpha=.001))
        model.add(Dense(1, activation=None))
        model.compile(loss='mean_squared_error', optimizer='adam')
        return model

    estimator = KerasRegressor(build_fn=get_model, epochs=20, batch_size=20,  verbose=1)
    estimator.fit(np.array(X_train), np.array(Y_train))

Задача

Кажется, что он сходится после нескольких эпох с огромной потерей обучения:

Epoch 1/20
8000/8000 [==============================] - 3s 378us/step - loss: 8970757661335224.0000
Epoch 2/20
8000/8000 [==============================] - 1s 187us/step - loss: 1368236980395048.7500
Epoch 3/20
8000/8000 [==============================] - 2s 189us/step - loss: 731455474934743.0000
Epoch 4/20
8000/8000 [==============================] - 2s 200us/step - loss: 731256021644738.6250
Epoch 5/20
8000/8000 [==============================] - 2s 209us/step - loss: 729734634673274.8750
Epoch 6/20
8000/8000 [==============================] - 2s 215us/step - loss: 730761901553746.0000
Epoch 7/20
8000/8000 [==============================] - 2s 224us/step - loss: 729841294691532.7500
Epoch 8/20
8000/8000 [==============================] - 2s 235us/step - loss: 728911536487137.2500
Epoch 9/20
8000/8000 [==============================] - 2s 229us/step - loss: 731467433524592.6250
Epoch 10/20

Что я пытался далеко?

  • Различные скорости обучения, снижение скорости обучения
  • Более или менее скрытые слои / скрытые юниты
  • Различные функции активации (→ ReLU, Leaky ReLU)
  • Дважды проверил мой ввод и метки (→ Кажется, чтобы быть правильным)

Все эти действия не улучшают потери. Использование меньшего количества слоев делает результат еще хуже.

Редактировать

Если кто-то захочет поиграть с этим - я создал (IPython / Google Colab) блокнот здесь .

То, что я тоже попробовал сейчас:

  • Инициализация с glorot_normal → Без изменения значимости
  • Нормализация с помощью sklearn.preprocessing.StandardScaler через sc.fit_transform(dataset) и вывод с помощью sc.inverse_transform(result) → Улучшено с ~ 7.3e14 до ~ 2.0e11
  • Варьируемый размер партии → Без изменения значимости
  • Дополнительные данные → 16.000 примеров → Немного улучшено с ~ 2.0e11 до ~ 1.0e11
  • Нормализация с помощью math.log (что делает c = a * b до log(c) = log(a) + log(b), вывод с помощью exp(predicted) → Кажется лучше → 1.02e9, но это все еще далеко от точности - для простой задачи, такой как умножение

Ответы [ 3 ]

0 голосов
/ 06 июля 2018

Вы используете очень большие значения. Посмотрите на среднюю относительную абсолютную ошибку (mean(abs((output - target) / target))), чтобы получить лучшую оценку производительности модели во время оценки, которая не зависит от входной шкалы.

Кроме того, рассмотрите возможность использования меньших значений, например, в диапазоне [0; 10] ограничение выходов диапазоном [0; 100], чтобы избежать взрыва градиентов. Вы можете разделить входные данные на несколько scale (>> 1) соответственно и умножить вывод на scale^2.

Если вы НЕ используете трюк с ln и exp для преобразования умножения в сложение, вам нужно гораздо больше слоев, а также следует учитывать остаточные соединения.

0 голосов
/ 06 июля 2018

Есть несколько проблем с моделированием :

  1. Сеть слишком глубока.Для этой простой задачи достаточно 1 скрытого слоя с 4 сигмовидными нейронами.Слишком глубокая сеть только затрудняет конвергенцию.
  2. Диапазон ввода / вывода слишком велик.Абсолютное значение ввода / вывода будет влиять на значение градиента и скорость обучения.Если вы используете большой ввод, вам нужно будет вначале использовать очень большую скорость обучения, а затем постепенно снижать ее.Более того, если a и b имеют разные диапазоны, их параметры требуют разных скоростей обучения.Чтобы избежать этой проблемы, вы должны уменьшить ваши данные, например, до 0, 1 дисперсия.Но это масштабирование может повлиять на точность умножения.Более подходящим для этой проблемы является масштабирование журнала. Обратите внимание, что , если вы используете масштабирование журнала, проблема еще более проста, это просто добавление двух чисел.Вы можете использовать только 1 выходной слой с 1 линейным нейроном, скрытый слой не требуется.

Однако основная проблема связана с framework / hardware .
Даже с точными весами ([[1., 1.], [0.]]), вывод модели по-прежнему не точен, MSE на тестовом наборе все еще около 10 ^ 4.Я полагаю, это связано с тем, что вычисление числа с плавающей запятой с низкой точностью в TF и ​​/ или в Colab не позволяет правильно рассчитать большое число.

0 голосов
/ 09 мая 2018

Нормализация ваших данных (входные данные и выходные данные) для получения нулевого среднего значения и единицы измерения.

На втором шаге измените инициализаторы на что-то вроде glorot_normal.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...