Tensorflow 多元线性回归问题的收敛性问题
我试图用一个非常简单的线性网络来解决一个多元线性回归问题。该网络仅由单个密集层作为其输出层,激活函数设置为线性。我通过将输入数据X乘以系统(权重)矩阵A:Y=A.X来合成输出数据Y。X和A都包含正态分布或均匀分布的随机数(不管发生什么问题)。在这种情况下,网络在1000个样本中仅7个时代就达到了99%以上的准确率 现在,如果我从Y合成X,这次是均匀随机数,使用A的逆:X=inv(A).Y ,并尝试训练网络,经过两百个时代,准确率仅达到94% 尽管系统矩阵(权重)完全相同,但为什么这两种情况之间存在如此巨大的差异。唯一的区别是与X和Y的随机分布有关。如果我被迫遵循第二种情况,我如何提高我的网络的可训练性,以便它可以在几个时期内进行训练 我尝试过不同的优化器、初始化器和正则化,但都没有帮助 下面是收敛性不太好的版本的代码。为了获得第一个版本,我在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% 尽管系统矩阵(权重)完全相同,但为什么这两种情况之间存
数据集中使用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))
和gen2y=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