使用Keras进行简单线性回归

5

我一直在尝试使用Keras实现一个简单的线性回归模型,希望能够理解Keras库的工作原理。不幸的是,我的模型表现非常糟糕。以下是我的实现代码:

from pylab import *
from keras.models import Sequential
from keras.layers import Dense

#Generate dummy data
data = data = linspace(1,2,100).reshape(-1,1)
y = data*5

#Define the model
def baseline_model():
   model = Sequential()
   model.add(Dense(1, activation = 'linear', input_dim = 1))
   model.compile(optimizer = 'rmsprop', loss = 'mean_squared_error', metrics = ['accuracy'])
   return model


#Use the model
regr = baseline_model()
regr.fit(data,y,epochs =200,batch_size = 32)
plot(data, regr.predict(data), 'b', data,y, 'k.')

生成的图如下:

Plot

请问有人能找出上述模型定义中的缺陷(可能会确保更好的拟合)?
3个回答

7

您需要增加优化器的学习率。在RMSprop优化器中,学习率的默认值设置为0.001,因此模型需要几百个epochs才能收敛到最终解决方案(可能您自己已经注意到这一点,训练日志显示损失值下降缓慢)。要设置学习率,请导入optimizers模块:

from keras import optimizers

# ...
model.compile(optimizer=optimizers.RMSprop(lr=0.1), loss='mean_squared_error', metrics=['mae'])

两者都可以,0.010.1都应该很好用。修改后你可能不需要为模型训练200个epoch,5、10或20个epoch就足够了。

还要注意,你在执行回归任务(即预测实数),而使用“准确度”作为指标则是在执行分类任务(即预测像图像类别这样的离散标签)。因此,如上所述,我已将其替换为更易于解释的mae(即平均绝对误差),也比此处使用的损失值(即均方误差)更易于解释。


我提供了一组数据,其中一条直线完美地拟合了它。因此,预期损失应该为0。但是通过这个计算,损失在0.015左右波动。这是模型固有的问题还是可以改进以获得更好的值? - mathnoob123
1
@mathnoob123 这是由于神经网络优化方法的梯度基础和逐步优化,以及使用的优化器所致。我猜想,由于您的情况比较简单,您可以使用一种不那么复杂的优化器来获得更好的结果,例如简单随机梯度方法,即 optimizers.SGD() 并且学习率设置为 lr=0.1。我估计,使用 SGD 后经过 200 个 epoch,您将达到约为 1e-41e-5 的损失。但由于优化过程是逐步进行的,而不是明确的,因此不要期望达到精确的零损失。 - today

1
有趣的问题,因此我将数据集插入了我编写的模型生成器框架中。该框架具有两个回调:EarlyStopping回调用于“loss”和Tensorboard用于分析。我从模型编译中删除了'metric'属性-这是不必要的,并且无论如何应该是'mae'。
@mathnoob123编写的模型及学习率(lr)=0.01在2968个时期内的损失为1.2623e-06。
但是,使用Adam替换RMSprop优化器的相同模型最准确,损失为1.22e-11,在2387个时期内。
我发现的最佳折衷方案是@mathnoob123使用lr=0.01的模型,在230个时期内的损失为1.5052e-4。这比@Kunam在第一个密集层中使用20个节点和lr=0.001的模型更好:在226个时期内的损失为3.1824e-4。
现在,我要查看随机化标签数据集(y)并观察结果...

1
以下代码最适合您的数据。 看一下这个。
from pylab import *
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt
%matplotlib inline

生成虚拟数据。
data = data = linspace(1,2,100).reshape(-1,1)
y = data*5

定义模型

def baseline_model():
    global num_neurons
    model = Sequential()
    model.add(Dense(num_neurons, activation = 'linear', input_dim = 1))
    model.add(Dense(1 , activation = 'linear'))
    model.compile(optimizer = 'rmsprop', loss = 'mean_squared_error')
    return model

设置第一个密集层中的神经元数

** 您可以稍后更改它

num_neurons = 17

使用模型。
regr = baseline_model()
regr.fit(data,y,epochs =200, verbose = 0)
plot(data, regr.predict(data), 'bo', data,y, 'k-')

num_neurons = 17 的第一个图表是很好的拟合。

但我们还可以探索更多。

点击下面的链接查看图表

num_neurons = 12 的图表

num_neurons = 17 的图表

num_neurons = 19 的图表

num_neurons = 20 的图表

您可以看到,随着神经元数量的增加,

我们的模型变得更加智能和最佳拟合。

希望您已经明白了。

谢谢


我正在使用TF2。这对我来说似乎比被接受的答案更有效。 - dturvene
希望你明白了。 - Kunam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接