Python中Keras深度学习库的回归教程

2018-02-09 09:48:11 浏览数 (1)

Keras 是一个深度学习库,它封装了高效的数学运算库 Theano 和 TensorFlow。

在这篇文章中,你将会了解到如何使用 Keras 开发和评估神经网络模型来解决回归问题。

在完成这个循序渐进的教程后,你将知道:

  • 如何加载 CSV 数据集并将其作为 Keras 库算法的输入。
  • 如何使用 Keras 建立一个回归问题的神经网络模型。
  • 如何使用 Keras 和 scikit-learn 交叉验证来评估模型。
  • 如何进行数据处理,以提高 Keras 模型的性能。
  • 如何调整 Keras 模型的网络拓扑结构。

现在就让我们开始吧。

  • 2017 年 3 月 更新:基于 Keras 2.0.2,TensorFlow 1.0.1 和 Theano 0.9.0 版本的示例
Python Keras深度学习库回归问题教程  照片由Salim Fadhley拍摄,保留相应权利。Python Keras深度学习库回归问题教程 照片由Salim Fadhley拍摄,保留相应权利。

1.问题描述

我们在本教程中要解决问题基于波士顿房价数据集。

你可以通过这个链接下载这个数据集,并将其保存到当前工作目录,命名为 housing.csv。

该数据集描述了波士顿郊区房屋的13个数字量化属性,并以每十万美元的平方数为单位模拟郊区房屋的价格。因此,这是一个回归预测建模问题。输入属性包括犯罪率,非零售商业面积,化学污染浓度等等。

这是机器学习研究中一个很好的问题。因为所有的输入和输出属性都是量化的,并且有多达506个实例可以使用,所以这个问题研究起来很方便。

使用均方误差(MSE)评估的模型的合理性能约为20平方每十万美元(也就是每平方米4500美元)。这个数字对于我们的神经网络来说是一个很好的训练目标。

2.开发基准神经网络模型

在本节中,我们将为回归问题创建一个基准神经网络模型。

首先介绍本教程所需的所有函数和对象(所需的Python库)。

代码语言:js复制
import numpy
import pandas
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

在引入所需的库后,我们现在可以从本地目录中的文件加载我们的数据集。

UCI机器学习库中的数据集实际上不是 CSV 格式,而是用空格分隔两个属性。我们可以使用pandas库轻松加载这个数据集。然后,分离输入(X)和输出(Y)属性,以便更容易使用 Keras 和 scikit-learn 进行建模。

代码语言:js复制
# load dataset
dataframe = pandas.read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:13]
Y = dataset[:,13]

我们可以使用 scikit-learn 来创建,并通过其易用的包装对象来评估 Keras模型。这样的方式是很理想的,因为 scikit-learn 擅长评估模型,并允许我们通过寥寥数行代码,就能使用强大的数据预处理和模型评估方案。

Keras 包装函数需要一个函数作为参数。这个必须被定义的函数负责创建要评估的神经网络模型。

下面我们来定义创建待评估的基准模型的函数。这是一个简单的模型,只有一个完全连接的隐藏层,具有与输入属性相同数量的神经元(13个)。网络使用隐藏层 relu 激活函数。没有激活函数用于输出层,因为这是一个回归问题,我们希望直接预测数值,而不需要采用激活函数进行变换。

我们会使用高效的 ADAM 优化算法以及优化的最小均方误差损失函数。这将是我们用来评估多个模型性能时的统一度量。这是一个可取的指标,因为通过平方根计算输出一个错误值,我们可以直接在问题的背景下(十万美元为单位)理解。

代码语言:js复制
# define base model
def baseline_model():
# create model
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')
return model

在 scikit-learn 库中用作回归计算估计器的 Keras 封装对象名为 KerasRegressor。我们创建一个 KerasRegressor

对象实例,并将创建神经网络模型的函数名称,以及一些稍后传递给模型 fit( ) 函数的参数,比如最大训练次数,每批数据的大小等。两者都被设置为合理的默认值。

我们还使用一个常量随机种子来初始化随机数生成器,我们将为本教程中评估的每个模型重复整个过程(相同的随机数)。这是为了确保我们始终如一地比较模型。

代码语言:js复制
# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# evaluate model with standardized dataset
estimator = KerasRegressor(build_fn=baseline_model, nb_epoch=100, batch_size=5, verbose=0)

最后一步是评估这个基准模型。我们将使用 10 倍交叉验证来评估模型。

代码语言:js复制
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))

运行这个代码为我们评估了模型在不可见的数据(随机生成的)上的性能。结果输出均方误差,包括 10 倍交叉验证中(10次)评估的所有结果的平均值和标准差(平均方差)。

代码语言:js复制
Baseline: 31.64 (26.82) MSE

3.建模标准化数据集

波士顿房价数据集的一个重要问题是输入属性的对于房价的影响各不相同。

在使用神经网络模型对数据进行建模之前,准备好所要使用数据总是一种好的做法。

从上文中的基准模型继续讨论,我们可以使用输入数据集的标准化版本重新评估之前评估的模型。

我们可以使用scikit-learn的 Pipeline 框架在交叉验证的每一步中在模型评估过程中对数据进行标准化处理。这确保了在每个测试集在交叉验证中,没有数据泄漏到训练数据。

下面的代码创建一个 scikit-learn Pipeline,首先标准化数据集,然后创建和评估基准神经网络模型。

代码语言:js复制
# evaluate model with standardized dataset
numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasRegressor(build_fn=baseline_model, epochs=50, batch_size=5,verbose=0)))
pipeline = Pipeline(estimators)
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Standardized: %.2f (%.2f) MSE" % (results.mean(), results.std()))

运行示例提供了比使用没有经过标准化的数据的基准模型更好的性能,降低了错误。

代码语言:js复制
Standardized: 29.54 (27.87) MSE

这部分的进一步扩展可以对输出变量采用类似的缩放,例如将其归一化到0-1的范围,并在输出层上使用Sigmoid或类似的激活函数将输出预测缩小到通输入相同的范围。

4.调整神经网络拓扑

对于神经网络模型而言,可以优化的方面有很多。

可能效果最明显的优化之处是网络本身的结构,包括层数和每层神经元的数量。

在本节中,我们将评估另外两个网络拓扑,进一步提高模型的性能。这两个结构分别是层数更深和层宽更宽的网络拓扑结构。

4.1。评估层数更深的网络拓扑

一种改善神经网络性能的方法是增加更多层次。这可能允许模型提取和重新组合数据中蕴含的高阶特性。

在本节中,我们将评估添加一个隐藏层到模型中的效果。这就像定义一个新的函数一样简单,这个函数将创建这个更深的模型,大部分程序从上面的基准模型中的代码复制而来。然后我们可以在第一个隐藏层之后插入一个新层。在本例中,新层包含一半的神经元(6个)

代码语言:js复制
# define the model
def larger_model():
# create model
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(6, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')
return model

我们的网络拓扑如下所示:

代码语言:js复制
13 inputs -> [13 -> 6] -> 1 output

我们可以用与上面相同的方式来评估这个网络拓扑结构,同时也使用上述数据集的标准化数据来提高性能。

代码语言:js复制
numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasRegressor(build_fn=larger_model, epochs=50, batch_size=5,verbose=0)))
pipeline = Pipeline(estimators)
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Larger: %.2f (%.2f) MSE" % (results.mean(), results.std()))

运行代码,这个模型确实表现出进一步改善,从28降低到24平方每10万美元。

Larger: 22.83 (25.33) MSE

4.2。评估层宽更宽的网络拓扑

另一种提高模型表现能力的方法是建立层宽更宽的网络。

在本节中,我们将评估保持浅层网络架构的效果,但将隐藏层中的神经元数量增加近一倍。

同样,我们需要做的是定义一个新的函数来创建我们的神经网络模型。在下面的代码中,我们已经增加了隐藏层的神经元数量,与基准模型相比从 13 个增加到 20 个。

代码语言:js复制
# define wider model
def wider_model():
# create model
model = Sequential()
model.add(Dense(20, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')
return model

我们的网络拓扑如下所示:

代码语言:js复制
13 inputs -> [20] -> 1 output

我们可以使用与上面相同的方案来评估更宽的网络拓扑结构:

代码语言:js复制
numpy.random.seed(seed)
estimators = []
estimators.append(('standardize', StandardScaler()))
estimators.append(('mlp', KerasRegressor(build_fn=wider_model, epochs=100, batch_size=5,verbose=0)))
pipeline = Pipeline(estimators)
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Wider: %.2f (%.2f) MSE" % (results.mean(), results.std()))

建立这个模型的误差进一步下降到21平方每10万美元左右。这对于这个问题并不是一个槽糕的结果。

代码语言:js复制
Wider: 21.64 (23.75) MSE

在付诸行动前很难猜到,更宽的网络在这个问题上的表现会比更的网络结构更好。该结果证明了在开发神经网络模型时进行实证检验的重要性。

概要

在这篇文章中,你了解了用于建模回归问题的 Keras 深度学习库用法。

通过本教程,你学习了如何开发和评估神经网络模型,其中包括:

  • 如何加载数据和开发基准模型。
  • 如何使用数据准备技术(如标准化)来提升性能。
  • 如何设计和评估具有不同拓扑结构的网络。
pythonkeras深度学习scikit-learnpythonkeras深度学习scikit-learn

0 人点赞