Я пытаюсь решить задачу множественной линейной регрессии с помощью очень простой линейной сети. Сеть состоит только из одного плотного слоя в качестве выходного слоя, а функция активации установлена на линейную. Я синтезирую выходные данные 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 синтезирован
Случай 2: синтезирован X