Проблема сходимости с задачами множественной линейной регрессии

Я пытаюсь решить задачу множественной линейной регрессии с помощью очень простой линейной сети. Сеть состоит только из одного плотного слоя в качестве выходного слоя, а функция активации установлена ​​на линейную. Я синтезирую выходные данные Y, умножая входные данные X на системную (весовую) матрицу A: Y = A.X. И X, и A содержат случайные числа с нормальным или равномерным распределением (проблема возникает независимо). В этом случае сеть достигает точности выше 99% всего за 7 эпох и более 1000 выборок, как и следовало ожидать.

Теперь, если я синтезирую X из Y, который на этот раз имеет однородные случайные числа, используя обратное значение A: X = inv (A) .Y, и попытаюсь обучить сеть, после двухсот эпох точность достигнет только 94%.

Почему существует такое огромное несоответствие между двумя случаями, хотя системная матрица (веса) точно такая же. Единственная разница связана со случайным распределением X и Y. Если я буду вынужден следовать второму случаю, как я могу улучшить обучаемость моей сети, чтобы ее можно было обучать за несколько эпох.

Я пробовал разные оптимизаторы, инициализаторы и регуляризации, но они не помогли.

Вот код версии, которая не так хорошо сходится. Чтобы получить первую версию, я использую gen1 в Dataset.from_generator(gen2, ...) вместо gen2.

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
import keras

N = 256
np.random.seed(0)
A = np.random.normal(0,.4,(N,N))
Ainv = np.linalg.inv(A)

import itertools

input_size = N
def gen1():
    for i in itertools.count(1):
        X = np.random.rand(N,1)-.5
        Y = np.dot(A,X)
        yield (X[:,0],Y[:,0])

def gen2():
    for i in itertools.count(1):
        Y = np.random.rand(N,1)-0.5
        X = np.dot(Ainv,Y)
        yield (X[:,0],Y[:,0])

dataset = tf.data.Dataset.from_generator(
     gen2,
     (tf.float64, tf.float64),
     (tf.TensorShape([N]), tf.TensorShape([N])))

train_ds = dataset.take(950)
valid_ds = dataset.skip(950).take(50)

#train_ds = train_ds.shuffle(2000, reshuffle_each_iteration = True)

train_ds = train_ds.batch(1)
valid_ds = valid_ds.batch(1)

from keras.layers import Input, Dense
from keras.models import Model
from keras import backend
 
def rabs(y_t, y_p):
    return backend.mean(backend.abs(y_p - y_t), axis=-1)/(tf.keras.backend.max(y_t) - tf.keras.backend.min(y_t))*100

inp = Input(shape=(input_size,))
out = Dense(N, activation='linear')(inp)

autoencoder = Model(inp, out)

#opt = tf.keras.optimizers.Adam(learning_rate=.0001)
opt = tf.keras.optimizers.SGD(learning_rate=.2, momentum=0.7)
autoencoder.compile(optimizer= opt,
              loss=tf.keras.losses.MeanSquaredError(),metrics= [rabs])

autoencoder.summary()

autoen_model = autoencoder.fit(train_ds, validation_data = valid_ds, epochs = 200)

plt.plot(autoen_model.history['rabs'])
plt.plot(autoen_model.history['val_rabs'])
plt.title('Model Accuracy')
plt.ylabel('Relative Absolute Mean Error %')
plt.xlabel('Epoch')
plt.legend(['Training set', 'Validation set'], loc='upper left')
plt.show()

Графики обучения

Случай 1: Y синтезирован

Случай 1: Y синтезирован

Случай 2: синтезирован X

Случай 2: синтезирован X




Ответы (2)


Почему я думаю, что это происходит

Я собираюсь проигнорировать то, что вы выполняете стохастический градиентный спуск, и просто представьте, что вы работаете со всем набором данных для каждого шага. В этом случае ваша проблема в обоих случаях - минимизировать || Y-AX || ^ 2 над A.

После некоторого изучения алгебры вы можете записать это как задачу квадратичной оптимизации вида

\ min_ {z} z ^ T Q z + b ^ T z,

где z \ in R ^ {256 ^ 2} представляет элементы матрицы A, Q - симметричная матрица, полученная только из X, а b - вектор, полученный из X и Y. Вы просите Tensorflow решить эта проблема с использованием градиентного спуска.

Скорость сходимости градиентного спуска в задачах этого типа определяется числом обусловленности Q, которое представляет собой наибольшее собственное значение, деленное на наименьшее. Число условий, которое намного больше единицы, приводит к медленному градиентному спуску, поскольку некоторые переменные обновляются намного быстрее, чем другие. Число условий, близкое к единице, лучше всего для получения быстрой сходимости. В «Основах оптимизации» Гулера (раздел 14.2) вы можете узнать больше о влиянии числа условий на сходимость (варианта) градиентного спуска, хотя, вероятно, есть лучшие ресурсы по этому поводу.

В вашем случае собственные значения Q - это просто собственные значения XX ^ T, которые представляют собой квадрат сингулярных значений X. Для первого набора данных X равномерно распределен, а во втором X = A_0 ^ {- 1} Y, где Y равномерно распределен.

Разница в сходимости, которую вы наблюдаете, происходит от того факта, что умножение на A_0 ^ {- 1} сильно увеличивает число обусловленности вашей матрицы. В следующем коде Python я провел несколько случайных испытаний и обнаружил, что число обусловленности второй матрицы намного больше. В тысячи раз больше.

import numpy as np

cond1 = []
cond2 = []


for i in range(10):
    A = np.random.normal(0,0.4,(256,256))
    Ainv = np.linalg.inv(A)

    X1 = np.random.rand(256,950)
    X1sv = np.linalg.svd(X1, compute_uv = False)

    Y = np.random.rand(256,950)
    X2 = np.dot(Ainv,Y)
    X2sv = np.linalg.svd(X2, compute_uv = False)

    cond1.append((X1sv.max()/X1sv.min())**2)
    cond2.append((X2sv.max()/X2sv.min())**2)
cond1 = np.array(cond1)
cond2 = np.array(cond2)

print('X1\'s condition number has mean {:.2f} and std {:.2f} '.format(cond1.mean(), cond1.std()))
print('X2\'s condition number has mean {:.2f} and std {:.2f} '.format(cond2.mean(), cond2.std()))
print('X2\'s mean condition number is {:.1f} times as big as X1\'s'.format(cond2.mean()/cond1.mean()))

Вот и я предполагаю, почему вы видите худшую сходимость во втором случае, чем в первом. Я могу ошибаться, но, возможно, это укажет вам правильное направление.

Предлагаемые решения

Для этого есть несколько решений:

  1. Используйте алгоритм оптимизации, такой как Adam или RMSprop, который приложит некоторые усилия для улучшения числа обусловленности вашей матрицы. Вы можете узнать больше о них в главе 8 https://www.deeplearningbook.org/.
  2. Вам нужно, чтобы A была гауссовой матрицей? Матрица с собственными значениями, близкими к 1, уменьшит эту проблему.
  3. Существуют методы оптимизации (не имеющие отношения к машинному обучению), облегчающие трудности, связанные с большим числом условий. Для получения дополнительной информации вы можете найти предварительный градиентный спуск.
person tmilne    schedule 21.12.2020

Я не думаю, что в процессе оптимизации что-то не так, я думаю, проблема в ваших вводящих в заблуждение показателях rabs(y_t, y_p)

Поскольку выходы rabs(y_t, y_p) одинаковы после деления MAE на (backend.max(y_t) - backend.min(y_t)), Y поколения 1 и Y поколения 2 должны иметь одинаковое распределение вероятностей, что здесь не так, поскольку в поколении 1 ваши Y = np.dot(Ainv,np.random.rand(N,1)) и в поколении 2 Y = np.random.rand(N,1)

Простым примером здесь является рассмотрение y_true_1 = (0.1, 0.2, 0.3), y_true_2 = (0.1, 0.2, 0.5) и y_predict_1 = (0.0, 0.1, 0.2), y_predict_2 = (0.0, 0.1, 0.4), затем MAE_1 = MAE_2 = 0.1, но после деления MAE_1 на (max(y_true_1) - min(y_true_1 )) RMAE_1 = 0.5 и деления MAE_2 на (max(y_true_2) - min(y_true_2 )) RMAE_2 = 0.25, теперь вы можете видеть, почему, если распределение y_true_1 отличается от распределения y_true_2, тогда нельзя ожидать, что два выхода rabs(y_t, y_p) будут одинаковыми

Меняю rabs(y_t, y_p) на МАС:

def rabs(y_t, y_p):
    return backend.mean(backend.abs(y_p - y_t))

И оптимизатор для:

learning_rate_fn = tf.keras.optimizers.schedules.InverseTimeDecay(1.0, 950 * 100, 9)
opt = tf.keras.optimizers.Adam(learning_rate=learning_rate_fn)

И я много раз запускал его с epochs = 100, выходы для gen1() и gen2() примерно такие:

gen1:
Epoch 1/100
950/950 [==============================] - 1s 625us/step - loss: 1631.5898 - rabs: 31.9912 - val_loss: 1568.4200 - val_rabs: 31.6044
Epoch 100/100
950/950 [==============================] - 1s 541us/step - loss: 16.1436 - rabs: 3.1877 - val_loss: 19.1974 - val_rabs: 3.5311

gen2:
Epoch 1/100
950/950 [==============================] - 1s 614us/step - loss: 51.9863 - rabs: 5.7896 - val_loss: 20.9347 - val_rabs: 3.5948
Epoch 100/100
950/950 [==============================] - 1s 540us/step - loss: 0.7340 - rabs: 0.6716 - val_loss: 0.5478 - val_rabs: 0.5920

Как видите, оптимизатор в основном выполняет ту же работу, он уменьшает потери (MSE) в 100 раз и rabs (MAE) в 10 раз.

person Mr. For Example    schedule 14.12.2020
comment
Я использовал относительную абсолютную среднюю ошибку, потому что она более тесно связана с ошибками веса. В первом случае результат варьируется от -100 до 100, а во втором - от 0 до 1. Даже если вы получите одинаковую абсолютную ошибку для обоих, веса будут в десятки раз точнее для случая 1. Использование вашего кода, MSE для весовой матрицы составляет 0,5 и 19 для первого и второго случаев соответственно. (веса должны быть равны Ainv в обоих случаях, а их значения находятся в диапазоне от -10 до 15). Я думаю, что проблема возникает из-за коллинеарности входных данных во втором случае. - person Kami; 14.12.2020
comment
Я не говорю, что они должны получить одинаковую абсолютную ошибку для обоих, конечный результат определяется тем, как вы инициализируете веса и другие гиперпараметры (вы не можете ожидать, что использование тех же гиперпараметров даст тот же результат, что мой код выше просто использует тот же процесс инициализации веса и один и тот же график скорости обучения для обоих случаев), я просто указываю, что использование относительной абсолютной средней ошибки для разного распределения вероятностей результатов вводит в заблуждение, и оптимизатор в основном делает одинаковый прогресс от начальных весов в обоих случаях - person Mr. For Example; 15.12.2020
comment
Короче говоря, если вы хотите, чтобы оба случая имели примерно одинаковый результат (MAE с разным масштабом), вам следует попробовать два разных процесса инициализации веса для слоя Dense и разных learning rate, удачи в поиске хороших гиперпараметров. - person Mr. For Example; 15.12.2020
comment
Это чисто линейная система, и соответствие, которое вы получили во втором случае, имеет ошибку 67%. Разве вы не ожидаете лучшего результата после 100 эпох, когда знаете, что сеть должна идеально соответствовать исходной системе, потому что они идентичны (линейные, одинаковые соединения и одинаковое количество параметров)? Для таких задач регрессии существует аналитическое решение в закрытой форме. Или посмотрите на это так: если у вас есть матрица A, можете ли вы найти обратную матрицу A с точностью лучше, чем, скажем, 1%, используя сеть и данные, которые я представил? (у вас ошибка 67%, у меня 7%, что все равно не очень хорошо). - person Kami; 15.12.2020
comment
В первом случае такой проблемы нет, и с любым оптимизатором легко достигается ошибка менее 0,01%, но это потому, что входные данные независимы, а генератор буквально использует Ainv. если бы вы использовали мой оптимизатор или даже Adam по умолчанию, вы бы получили 0,0013 и 0,1 MAE для 1-го и 2-го случаев за 100 эпох (примерно 0,0005% против 10% относительной ошибки). Они не одинаковы, независимо от того, смотрите ли вы на относительную или абсолютную ошибку. На самом деле это скорее проблема математики и множественной коллинеарности. - person Kami; 15.12.2020
comment
Позвольте мне сказать это еще раз: если вы хотите, чтобы оба случая имели примерно одинаковый результат (MAE с разным масштабом), вы должны попробовать два разных процесса инициализации веса для слоя Dense и разных learning rate, особенно разные веса инициализации в слое Dense, вы не можете ожидать обоих случаев начните с одних и тех же точек, чтобы получить тот же результат. но тот же результат не гарантируется, потому что X и Y в обоих случаях не находятся в одном и том же распределении, их пространство потерь может быть разным, поскольку, насколько я знаю, нет математического доказательства того, что вы хотите от оптимизатора - person Mr. For Example; 16.12.2020
comment
Проверьте [DeepMind On optimizer] (youtube.com/watch?v=kVU8zTI-Od0) если вы хотите узнать больше об оптимизации - person Mr. For Example; 16.12.2020