系列文章目录
深度学习入门系列1:多层感知器概述 深度学习入门系列2:用TensorFlow构建你的第一个神经网络 深度学习入门系列3:深度学习模型的性能评价方法 深度学习入门系列4:用scikit-learn找到最好的模型 深度学习入门系列5项目实战:用深度学习识别鸢尾花种类 深度学习入门系列6项目实战:声纳回声识别 深度学习入门系列7项目实战:波士顿房屋价格回归 待更新…… 深度学习入门系列8:保存模型以便稍后进行序列化 深度学习入门系列9:训练期间用检查点保存最好模型 深度学习入门系列10:从绘制记录中理解训练期间的模型行为 深度学习入门系列11:用Dropout正则减少过拟合 深度学习入门系列12:使用学习规划来提升性能 深度学习入门系列13:卷积神经网络 深度学习入门系列14项目实战:手写数字识别 深度学习入门系列15用图像增强改善模型性能 深度学习入门系列16:图像中对象识别项目 深度学习入门系列17项目实战:从电影评论预测情感 深度学习入门系列18:递归神经网络
在这个项目教程中,你将针对回归问题,学习如何使用Keras开发和评价神经网络模型。一步一步完成该教程之后,你将学到:
- 如何加载CSV数据并确保Keras可用。
- 如何针对回归问题使用Keras创建神经网络模型。
- 如何在Keras中使用scikit-learn并使用交叉验证评价模型。
- 如何进行数据预处理以提高keras模型的技能
- 如何用Keras调节模型的网络拓扑结构。
让我们开始吧!
7.1 波士顿房屋价格数据集
在这个课程中看到的问题是波士顿房屋价格数据集。数据集描述了波士顿郊区房屋的属性,关注对这些郊区的成千美元房屋价格的建模。因此,这是个回归预测建模问题。有13个输入变量,描述了波士顿郊区房屋属性。下面列出了数据集所有属性。
1.CRIM:城镇的人均犯罪率 2.ZN:占地面积超过25000平方英尺的住宅用地面积比例。 3.INDUS:每个城镇非零售业务的比例 4.CHAS:查尔斯河虚拟变量(如果管道限制河流则= 1;否则为0) 5.NOX:一氧化氮浓度(每千万份) 6.RM:每栋住宅的平均房间数量 7.AGE:1940年以前建造的自住单位比例 8:DIS:到波士顿五个就业中心的加权距离 9.RAD:径向高速公路可达性指数 10.TAX:每1000美元的全额房产税率 11.PTRATIO:城镇的师生比例 12.B:1000(Bk ? 0.63)2其中Bk是城镇黑人的比例。 13.LSTAT:较低的人口状况 14.MEDV:自住房屋的中位数为1000美元。
在机器学习中,这是很值得研究的问题。这个数据集使用起来很方便,因为所有的输入变量和输出变量都是数值,而且有506个实例可以使用。下面提供的是506个是实例中前5行。
0.00632 18.00 2.310 0 0.5380 6.5750 65.20 4.0900 1 296.0 15.30 396.90 4.98 24.00
0.02731 0.00 7.070 0 0.4690 6.4210 78.90 4.9671 2 242.0 17.80 396.90 9.14 21.60
0.02729 0.00 7.070 0 0.4690 7.1850 61.10 4.9671 2 242.0 17.80 392.83 4.03 34.70
0.03237 0.00 2.180 0 0.4580 6.9980 45.80 6.0622 3 222.0 18.70 394.63 2.94 33.40
0.06905 0.00 2.180 0 0.4580 7.1470 54.20 6.0622 3 222.0 18.70 396.90 5.33 36.20
这些数据集在本书提供源代码中也是提供了。或者,你可以下载这个数据集并保存它到你当前的工作目录下,命名为housing.csv。你可以在UCI机器学习仓库中了解更多关于波士顿房价数据集。
7.2 开发一个基准神经网络模型
在这个部分,我们针对回归问题创建一个基准模型。让我们从导入所有这个节课需要的函数和对象开始。
import numpy
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
我们现在可以从本地目录加载我们的数据集。UCI机器学习库上的这些数据集实际上并不是CSV格式的,它的属性是通过空格分隔的。我们可以使用Pandas库轻松地加载这些数据。我们可以分隔成输入变量(X)和输出变量(Y),以至于能较容易用Keras和scikit-learn 进行建模。
dataframe = 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 封装类需要一个函数作为参数。我们定义的这个函数必须负责创建一个可以评估的神经网络模型。
下面我们定义了函数,为了创建一个可评估的基准模型。这是个简单模型有单个的全连接隐藏层,拥有和输入属性一样多的神经元数量。网络使用诸多良好的实践,例如隐藏层的整流器激活功能。输出层没有使用激活函数因为它是一个回归问题。我们对直接预测而不用转换数值感兴趣。
使用有效的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()函数,如迭代次数和批处理大小。这两者都设置了合理的默认值。我们用常量种子来初始化随机生成器,对于教程中评估的每个模型,这个过程我们将可以重复。这确保我们比较模型的一致性和结果的可复制性。
seed = 7 numpy.random.seed(seed)
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)
最后一步是评估基准模型。我们将使用10-fold交叉验证评估模型。
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Baseline: %.2f (%.2f) MSE" % (results.mean(), results.std()))
为了完整性,下面列出了所有的代码
import numpy
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
seed = 7
numpy.random.seed(seed)
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Baseline: %.2f (%.2f) MSE" % (results.mean(), results.std()))
运行这些代码,给出了在这个问题上模型性能的评价。结果展示了所有10折交叉验证下的均方误差,包括平均值和标准差(平均方差)。
Baseline: 31.64 (26.82) MSE
7.3 通过标准化数据集提升性能
波士顿房价数据集重点关注是不断变化的输入属性,因为他们的度量不一样。在使用神经网络模型建模它之前,准备数据几乎是最好的练习。接着下面基准模型,我们能使用标准输入数据重新评估同样模型。
在模型评估过程和在每次交叉验证中,我们可以使用scikit-learn的Pipeline框架执行标准化。这确保没有遗漏的数据混入训练集。下面代码创建了scikit-learn Pipeline首次标准化数据集然后创建并评价基准神经网络模型。
import numpy
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
seed = 7
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()))
运行这个例子,性能要比没有标准花数据的基准模型要好,降低了误差。
Standardized: 29.54 (27.87) MSE
这部分进行了进一步的扩展,对输出变量进行重新缩放,比如正则化它0到1,在输出层使用Sigmoid或者相似激活函数来缩小输出预测到同样的范围。
7.4 调节神经网络拓扑结构
对于神经网络的优化受到很多关注。可能最大的点是网络本身的结构,包括层数和每层神经元节点。在这部分,我们将评估另外两个网络结构,进一步提高模型性能。我们将看到两个更深和更为广阔网络结构。
7.4.1 评估一个更深网络结构
提高神经网络一种方法是增加层数。这可能运行模型提取并从新整合嵌入数据中的更高层次特征。在这部分,我们评估增加不止一个隐藏层的效果。这个和定义一个新函数一样容易,将要创建这个更深模型,从下面基准模型复制过来。我们能在第一个隐藏层之后插入新一行。在这个例子中我们用一般隐藏数。我们网络拓扑结构如下:
13 inputs -> [13 -> 6] -> 1 output
我们能用下面同样的方法评估这个网络拓扑结构,同时使用上面显示的数据集的标准化来提高性能。
import numpy
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
seed = 7
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()))
运行这个模型展示了模型性能进一步提高。
Larger: 22.83 (25.33) MSE
7.4.2 评估一个更大网络拓扑结构
增加模型表示能力的另外一个方法是创建一个更大的网络。在这部分我们评估小网络结构和接近两倍隐藏层的神经元个数的效果。在这,和基准模型比较,我们增加了隐藏神经元个数,从13到20个。我们更大网络结构总结如下:
13 inputs -> [20] -> 1 output
我们使用上面同样的模式评估更大神经网络结构。
import numpy
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
seed = 7
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()))
构建这个模型能看到误差进一步下降到每平方21000美元,对于这个问题结果还不错。
Wider: 21.71 (24.39) MSE
很难想猜到在这个问题上较大的网络比更深网络表现要好。这个结果阐述了当我们在研发一个神经网络模型时先验知识重要性。
7.5 总结
在这节课,你学到用Keras深度学习库建模回归问题。通过这个课程你学习如何构建和评估一个神经网络模型,包括:
- 如何加载数据和研发基准模型。
- 如何使用数据预处理技术来提高性能,如正则化。
- 如何在一个问题上用不同拓扑结构设计和评估神经网络。
7.5.1 接下来
接下来第四部分,你将要学习如何用更高级技巧从你的神经网络模型中获得更多并使用更多高级Keras库。
|