Tensorflow 多元线性回归问题的收敛性问题

Tensorflow 多元线性回归问题的收敛性问题,tensorflow,neural-network,linear-regression,convergence,multicollinearity,Tensorflow,Neural Network,Linear Regression,Convergence,Multicollinearity,我试图用一个非常简单的线性网络来解决一个多元线性回归问题。该网络仅由单个密集层作为其输出层,激活函数设置为线性。我通过将输入数据X乘以系统(权重)矩阵A:Y=A.X来合成输出数据Y。X和A都包含正态分布或均匀分布的随机数(不管发生什么问题)。在这种情况下,网络在1000个样本中仅7个时代就达到了99%以上的准确率 现在,如果我从Y合成X,这次是均匀随机数,使用A的逆:X=inv(A).Y ,并尝试训练网络,经过两百个时代,准确率仅达到94% 尽管系统矩阵(权重)完全相同,但为什么这两种情况之间存

我试图用一个非常简单的线性网络来解决一个多元线性回归问题。该网络仅由单个密集层作为其输出层,激活函数设置为线性。我通过将输入数据X乘以系统(权重)矩阵A:Y=A.X来合成输出数据Y。X和A都包含正态分布或均匀分布的随机数(不管发生什么问题)。在这种情况下,网络在1000个样本中仅7个时代就达到了99%以上的准确率

现在,如果我从Y合成X,这次是均匀随机数,使用A的逆:X=inv(A).Y ,并尝试训练网络,经过两百个时代,准确率仅达到94%

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

我尝试过不同的优化器、初始化器和正则化,但都没有帮助

下面是收敛性不太好的版本的代码。为了获得第一个版本,我在
数据集中使用
gen1
,而不是
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合成


我认为优化过程中没有任何错误,我认为问题在于你的误导性指标
rabs(y\u t,y\u 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))
和gen2
y=np.random.rand(N,1)

简单的例子是考虑<代码> yStrueE11=(0.1,0.2,0.3)<代码> ystruee2=(0.1,0.2,0.5)< /> >代码> yyReavtTy1=(0,0.1,0.2),<代码> yyReavtTy2=(0,0.1,0.4)< /代码>,然后<代码> MaEy1= MaEy2= Suff,但MAEY1除以<代码>(max(Y-TtrueE1)-min(YAuttrue1))

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\u t,y\u 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倍 我将忽略你们正在做的随机梯度下降 想象一下,您正在为每个步骤处理整个数据集。在里面 在这种情况下,您在这两种情况下的问题都是最小化A上的| | Y-AX | | ^2

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

\min_{z}z^tqz+b^tz

其中,R^{256^2}中的z表示矩阵A的条目,Q是A 仅从X得到的对称矩阵,b是从X得到的向量 你要Tensorflow做的就是用 梯度下降

这类问题的梯度下降的收敛速度是 由Q的条件数控制,Q是其最大特征值 除以它的最小值。远大于1的条件数 导致缓慢的梯度下降,因为某些变量的更新速度比 其他的。接近1的条件数最有利于快速获得 汇聚在古勒的优化基础(第14.2节)中,您可以 了解更多关于条件数对(a)收敛性的影响 梯度下降的变体,尽管可能有更好的资源 在这上面

在你的例子中,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()))
这就是我的猜测,为什么你会看到更糟糕的收敛性 第二种情况比第一种情况好。我可能错了,但也许这会说明问题 你的方向是对的

建议的解决办法 有几种解决方案:

  • 使用像Adam或RMSprop这样的优化算法,这将使 努力改善矩阵的条件数。你可以学到更多 关于第8章中的内容
  • 你需要一个高斯矩阵吗?具有特征值的矩阵 接近1将减少此问题
  • 有优化技术(与机器学习无关) 这改善了大量条件数的困难。你可以 查看预处理梯度下降,了解更多信息

  • 我使用相对绝对平均误差,因为它与权重误差更密切相关。在第一种情况下,输出在-100到100之间变化,而在第二种情况下,输出在0到1之间变化。即使两种情况的绝对误差相同,对于情况1,权重的精度也要高出几十倍。使用您的代码,第一种和第二种情况下权重矩阵的MSE分别为0.5和19。(重量应等于b中的Ainv