如何利用Keras 深度学习库的进行回归

男儿欲遂平生志,五经勤向窗前读。这篇文章主要讲述如何利用Keras 深度学习库的进行回归相关的知识,希望能为你提供帮助。
1 问题描述 
2 开发基线神经网络模型 
3 标准化数据集建模 
4 调整神经网络拓扑 
  4.1 评估更深层次的网络拓扑 
  4.2 评估更广泛的网络拓扑 
5 总结 
  Keras 是一个包含高效数值库 Theano 和 TensorFlow 的深度学习库。在这篇文章中,您将了解如何使用 Keras 开发和评估神经网络模型来解决回归问题。在本文中您将了解:

  • 如何加载 CSV 数据集并使其可用于 Keras。
  • 如何使用 Keras 为回归问题创建神经网络模型。
  • 如何使用 scikit-learn 和 Keras 来评估使用交叉验证的模型。
  • 如何执行数据准备以提高 Keras 模型的技能。
  • 如何使用 Keras 调整模型的网络拓扑。
1 问题描述
  我们将在本教程中研究的问题是波士顿房价数据集。您可以下载此数据集并将其保存到您当前的工作中,直接使用文件名 Housing.csv。数据集描述了波士顿郊区房屋的数值属性,并关注以数千美元为单位对这些郊区的房(分开)屋价格进行建模。 因此,这是一个回归预测建模问题。 输入属性包括犯罪率、非零售商业面积的比例、化学品浓度等。
    这是机器学习中一个经过充分研究的问题。 使用起来很方便,因为所有输入和输出属性都是数字的,并且有 506 个实例可供使用。使用均方误差 (MSE) 评估的模型的合理性能约为 20 美元的平方数(如果您愿意,则为 4,500 美元) 取平方根)。 这是我们的神经网络模型的一个目标。
2 开发基线神经网络模型
  在本节中,我们将为回归问题创建一个基线神经网络模型。让我们从包含本文所需的所有函数和对象开始。
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 进行建模。
...
dataframe = pandas.read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
X = dataset[:,0:13]
Y = dataset[:,13]

  我们可以使用 Keras 库对象创建 Keras 模型并使用 scikit-learn 对其进行评估。 这是可取的,因为 scikit-learn 擅长评估模型,并且允许我们使用强大的数据准备和模型评估方案,只需要很少的代码行。
  Keras 包装器需要一个函数作为参数。 我们必须定义的这个函数负责创建要评估的神经网络模型。
  下面我们定义函数来创建要评估的基线模型。 这是一个简单的模型,它有一个完全连接的隐藏层,其神经元数量与输入属性 (13) 相同。 该网络网络中使用的参数为最佳实践,例如隐藏层的整流器激活函数。 输出层没有使用激活函数,因为它是一个回归问题,我们有兴趣直接预测数值而不进行变换。
  使用高效的 ADAM 优化算法并优化均方误差损失函数。 这将与我们用于评估模型性能的指标相同。 这是一个理想的度量标准,因为通过取平方根,我们可以得到一个误差值,我们可以在问题的上下文中直接理解(数千美元)。
...
def baseline_model():
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer=normal, activation=relu))
model.add(Dense(1, kernel_initializer=normal))
model.compile(loss=mean_squared_error, optimizer=adam)
return model

  在 scikit-learn 中用作回归估计器的 Keras 包装器对象称为 KerasRegressor。 我们创建一个实例并将创建神经网络模型的函数名称以及稍后传递给模型的 fit() 函数的一些参数传递给它,例如 epoch 数和批量大小。 这两个都设置为合理的默认值。最后一步是评估这个基线模型。 我们将使用 10 折交叉验证来评估模型。
...
kfold = KFold(n_splits=10)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Results: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  将所有这些结合在一起,下面列出了完整的示例。
from pandas import read_csv
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
dataframe = read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
X = dataset[:,0:13]
Y = dataset[:,13]
def baseline_model():
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer=normal, activation=relu))
model.add(Dense(1, kernel_initializer=normal))
model.compile(loss=mean_squared_error, optimizer=adam)
return model
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)
kfold = KFold(n_splits=10)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Baseline: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  运行此代码可以让我们估计模型在未见数据问题上的性能。
  注意:您的结果可能会因算法或评估过程的随机性或数值精度的差异而有所不同。 考虑运行该示例几次并比较平均结果。
  注意:均方误差是负数,因为 scikit-learn 会反转,从而使度量最大化而不是最小化。 您可以忽略结果的符号。
  结果报告了均方误差,包括交叉验证评估的所有 10 倍的平均值和标准偏差(平均方差)。
Baseline: -32.65 (23.33) MSE

3 标准化数据集建模
  波士顿房价数据集的一个重要问题是输入属性的尺度各不相同,因为它们测量不同的数量。在使用神经网络模型对其进行建模之前准备数据几乎总是一种好习惯。从上述基线继续优化模型,我们可以使用输入数据集的标准化版本重新评估相同的模型。
  我们可以使用 scikit-learn 的 Pipeline 框架在模型评估过程中,在交叉验证的每个折叠中执行标准化。 这确保了每个测试集交叉验证折叠没有数据泄漏到训练数据中。下面的代码创建了一个 scikit-learn 管道,它首先标准化数据集,然后创建和评估基线神经网络模型。
  下面的代码创建了一个 scikit-learn 管道,它首先标准化数据集,然后创建和评估基线神经网络模型。
...
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)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Standardized: %.2f (%.2f) MSE" % (results.mean(), results.std()))
from pandas import read_csv
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
dataframe = read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
X = dataset[:,0:13]
Y = dataset[:,13]
def baseline_model():
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer=normal, activation=relu))
model.add(Dense(1, kernel_initializer=normal))
model.compile(loss=mean_squared_error, optimizer=adam)
return model
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)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Standardized: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  注意:您的结果可能会因算法或评估过程的随机性或数值精度的差异而有所不同。 考虑运行该示例几次并比较平均结果。
  在没有标准化数据的情况下,运行该示例提供了比基线模型更好的性能,从而消除了错误。
Standardized: -29.54 (27.87) MSE

  本节的进一步扩展将类似地对输出变量应用重新缩放,例如将其归一化到 0-1 的范围,并在输出层上使用 Sigmoid 或类似的激活函数将输出预测缩小到相同的范围。
【如何利用Keras 深度学习库的进行回归】4 调整神经网络拓扑
  有很多问题可以针对神经网络模型进行优化。也许最大的杠杆点是网络本身的结构,包括层数和每层中的神经元数量。在本节中,我们将评估另外两个 网络拓扑结构,以进一步提高模型的性能。 我们将研究更深和更广泛的网络拓扑。
4.1 评估更深层次的网络拓扑
  提高神经网络性能的一种方法是添加更多层。 这可能允许模型提取和重组嵌入在数据中的高阶特征。在本节中,我们将评估向模型添加一个隐藏层的效果。 这就像定义一个新函数一样简单,该函数将创建这个更深层次的模型,从我们上面的基线模型中复制而来。 然后我们可以在第一个隐藏层之后插入一个新行。 在这种情况下,大约有一半的神经元数量。
...
def larger_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))
model.compile(loss=mean_squared_error, optimizer=adam)
return model


  我们的网络拓扑现在看起来像:
13 inputs -> [13 -> 6] -> 1 output

  我们可以以与上述相同的方式评估此网络拓扑,同时还使用上述数据集的标准化来提高性能。
...
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)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Larger: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  将这些结合在一起,下面列出了完整的示例。
from pandas import read_csv
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
dataframe = read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
X = dataset[:,0:13]
Y = dataset[:,13]
def larger_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))
model.compile(loss=mean_squared_error, optimizer=adam)
return model
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)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Larger: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  注意:您的结果可能会因算法或评估过程的随机性或数值精度的差异而有所不同。 考虑运行该示例几次并比较平均结果。
  运行此模型确实显示性能进一步提高,从 28 降至 24000 平方美元。
4.2 评估更广泛的网络拓扑
  增加模型表示能力的另一种方法是创建更广泛的网络。在本节中,我们评估了保持浅层网络架构并将一个隐藏层中的神经元数量几乎翻倍的效果。 同样,我们需要做的就是定义一个新函数来创建我们的神经网络模型。 在这里,与基线模型相比,我们将隐藏层中的神经元数量从 13 个增加到 20 个。
...
def wider_model():
model = Sequential()
model.add(Dense(20, input_dim=13, kernel_initializer=normal, activation=relu))
model.add(Dense(1, kernel_initializer=normal))
model.compile(loss=mean_squared_error, optimizer=adam)
return model

  我们的网络拓扑现在看起来像:
13 inputs -> [20] -> 1 output

  我们可以使用与上述相同的方案来评估更广泛的网络拓扑:
...
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)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Wider: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  将这些结合在一起,下面列出了完整的示例。
from pandas import read_csv
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
dataframe = read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
X = dataset[:,0:13]
Y = dataset[:,13]
def wider_model():
model = Sequential()
model.add(Dense(20, input_dim=13, kernel_initializer=normal, activation=relu))
model.add(Dense(1, kernel_initializer=normal))
model.compile(loss=mean_squared_error, optimizer=adam)
return model
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)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Wider: %.2f (%.2f) MSE" % (results.mean(), results.std()))

  注意:您的结果可能会因算法或评估过程的随机性或数值精度的差异而有所不同。 考虑运行该示例几次并比较平均结果。
  构建模型确实看到误差进一步下降到大约 21000 平方美元。 对于这个问题,这不是一个坏结果。
Wider: -21.71 (24.39) MSE

  很难猜测更广泛的网络会在这个问题上胜过更深的网络。 结果证明了在开发神经网络模型时经验测试的重要性。
5 总结
  在这篇文章中,您发现了用于建模回归问题的 Keras 深度学习库。通过本教程,您学习了如何开发和评估神经网络模型,包括:
  • 如何加载数据和开发基线模型。
  • 如何使用标准化等数据准备技术提升性能。
  • 如何在一个问题上设计和评估具有不同拓扑的网络。


    推荐阅读