2

我试图用一个非常简单的线性网络来解决多线性回归问题。该网络仅包含一个密集层作为其输出层,并且激活函数设置为线性。我通过将输入数据 X 乘以系统(权重)矩阵 A 来合成输出数据 Y: Y=AX 。X 和 A 都包含具有正态或均匀分布的随机数(无论如何都会出现问题)。在这种情况下,网络在 1000 个样本中仅 7 个 Epoch 就达到了 99% 以上的准确率,正如人们所期望的那样。

现在,如果我从 Y 合成 X,这一次具有统一的随机数,使用 A 的逆: X = inv(A).Y ,并尝试训练网络,经过 200 个 Epoch 后,准确率仅达到 94%。

即使系统矩阵(权重)完全相同,为什么这两种情况之间存在如此巨大的差异。唯一的区别与 X 和 Y 的随机分布有关。如果我被迫遵循第二种情况,我该如何提高我的网络的可训练性,以便它可以在几个 epoch 内进行训练。

我尝试了不同的优化器、初始化器和正则化,但它们没有帮助。

这是不太好收敛的版本的代码。为了获得我使用的第一个版本gen1Dataset.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合成

4

2 回答 2

1

为什么我认为会发生这种情况

我将忽略您正在执行随机梯度下降,并想象您正在处理每个步骤的整个数据集。在这种情况下,您在这两种情况下的问题都是在 A 上最小化 ||Y-AX||^2。

在做一些代数之后,你可以把它写成一个二次优化问题的形式

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

其中 z \in R^{256^2} 表示矩阵 A 的条目,Q 是仅从 X 获得的对称矩阵,b 是从 X 和 Y 获得的向量。您要求 Tensorflow 做的是解决这个问题使用梯度下降。

在这类问题上梯度下降的收敛速度由 Q 的条件数决定,即 Q 的最大特征值除以其最小值。远大于 1 的条件数会导致梯度下降缓慢,因为某些变量的更新速度比其他变量快得多。条件数更接近 1 最有利于获得快速收敛。在 Guler 的优化基础(第 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 这样的优化算法,这将努力改善矩阵的条件数。您可以在https://www.deeplearningbook.org/的第 8 章中了解有关这些内容的更多信息。
  2. 你需要让 A 是一个高斯矩阵吗?特征值接近 1 的矩阵会减少这个问题。
  3. 有一些优化技术(与机器学习无关)可以改善大条件数的困难。您可以查看预处理梯度下降以获取更多信息。
于 2020-12-21T12:46:32.223 回答
0

我认为优化过程没有任何问题,我认为问题在于您的误导性指标rabs(y_t, y_p)

rabs(y_t, y_p)由于MAE 除以 后的输出相同(backend.max(y_t) - backend.min(y_t)),因此 gen1 的 Y 和 gen2 的 Y 需要处于相同的概率分布中,这里不是这种情况,因为在 gen1 中您Y = np.dot(Ainv,np.random.rand(N,1))和在 gen2Y = 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.5MAE_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)为 MAS:

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 倍

于 2020-12-14T06:47:25.210 回答