这是《Python深度学习》第一个回归问题,它的预测值是一个数值。常用的损失函数是均方误差MSE,常用的回归指标是平方绝对误差MAE
1.数据集介绍
波士顿房价是1970s波士顿郊区房屋价格的中位数,包含506个数据,分为404个训练样本和102个测试样本。每个样本有13个数值特征。
2.思路
与先前的手写数字和电影评论分类的例子不同,房价预测中的特征的重要性不一致,而且由于单位不尽相同,需要先对数据进行标准化处理。其次设定网络结构,然后确定网络参数,沿用电影分类中方式,先预训练一波,最后训练目标模型 数据处理->设定网络结构->调节参数->训练目标模型
3.数据预处理
对于这种取值范围差异较大的数据,一般采用标准化处理。 即对于数据的每个特征,减去特征平均值,再除以标准差,这样得到的特征的平均值为0,标准差为1。
4.网络结构
本题样本较小,网络结构不复杂,采用三层全连接层。在项目2中介绍过输入数据为向量(数组组成的数组),标签为标量(单个数组),对于这种类型的问题,带有relu激活的全连接层的简单堆叠表现较好。因此前两层的激活函数为‘relu’。最后一层使用纯线性(不加激活层),这样可以预测任意范围内的值。 第一层:全连接层,设置64个单元,激活函数为‘relu’ 第二层:全连接层,设置64个单元,激活函数为‘relu’ 第三层:全连接层,设置1个单元
5.参数调节
与路透社电影评论分类的参数选择一致,这里在调参的时候也先进行了预训练。 对于本项目中样本较少的情况,采用k折交叉验证是一个比较好的选择,将数据划分为k分,实例化k个相同的模型,每个模型在k-1个分区上训练,并在剩下的一个分区上进行苹果。最终的验证分数等于k个验证分数的平均。
6.代码详解
from keras
.datasets
import boston_housing
from keras
import models
from keras
import layers
import numpy
as np
import matplotlib
.pyplot
as plt
(train_data
, train_targets
), (test_data
, test_targets
) = boston_housing
.load_data
()
mean
= train_data
.mean
(axis
= 0)
std
= train_data
.std
(axis
= 0)
train_data
-= mean
train_data
/= std
test_data
-= mean
test_data
/= std
def build_model():
model
= models
.Sequential
()
model
.add
(layers
.Dense
(64, activation
='relu', input_shape
=(train_data
.shape
[1],)))
model
.add
(layers
.Dense
(64, activation
='relu'))
model
.add
(layers
.Dense
(1))
model
.compile(optimizer
='rmsprop', loss
= 'mse', metrics
=['mae'])
return model
'''
#K折交叉验证
k = 4 #设定k的值
num_val_samples = len(train_data) // k #计算验证集(每一份)的数据个数
num_epochs = 100 #epochs_size的值
all_scores = [] #存放验证分数
all_mae_history = [] #存放验证分数
for i in range(k):
print('processing fold #', i)
val_data = train_data[i * num_val_samples: (i+1) * num_val_samples] #验证集
val_targets = train_targets[i*num_val_samples : (i+1)*num_val_samples] #验证集结果
#使用concatenate函数将剩下的几份合并成一个训练集,axis表示在哪个轴上合并,为0表示在最外层的轴
partial_train_data = np.concatenate([train_data[: i * num_val_samples], train_data[(i+1)*num_val_samples:]], axis=0) #测试集
partial_train_targets = np.concatenate([train_targets[:i*num_val_samples], train_targets[(i+1)*num_val_samples:]],
axis=0) #训练集实际结果
model = build_model() #搭建网络
#verbose表示是否查看每次训练的结果,为0表示不看,为2表示每次迭代输出loss等相关值
history = model.fit(partial_train_data, partial_train_targets, epochs = num_epochs, batch_size=1, verbose=2) #训练网络
mae_history = history.history['mean_absolute_error'] #返回模型的mae
all_mae_history.append(mae_history) #记录mae
#val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
#评估模型
#all_scores.append(val_mae)
#记录mae
#计算所有模型的mae的平均值
average_mae_history = [np.mean([x[i] for x in all_mae_history]) for i in range(num_epochs)]
#平滑曲线,将每个值变成上一个值乘以权重和该值乘以权重的和,将曲线的变化率降低。
def smooth_curve(points, factor = 0.9):
smooth_points = []
for point in points:
if smooth_points:
previous = smooth_points[-1]
smooth_points.append(previous * factor + point * (1-factor))
else:
smooth_points.append(point)
return smooth_points
smooth_mae_history = smooth_curve(average_mae_history[10 :]) #前10个值偏差过大,去掉。将其他值平滑处理
plt.plot(range(1, len(smooth_mae_history) + 1), smooth_mae_history) #绘制曲线
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
'''
model
= build_model
()
model
.fit
(train_data
, train_targets
, epochs
= 80, batch_size
= 16, verbose
= 2)
test_mse_score
, test_mae_score
= model
.evaluate
(test_data
, test_targets
)
print('mse = ',test_mse_score
, 'mae = ', test_mae_score
)
训练结果