Predicting house prices: a regression example
波士顿房价数据集
本节将要预测 20 世纪 70 年代中期波士顿郊区房屋价格的中位数,已知当时郊区的一些数据点,比如犯罪率、当地房产税率等。本节用到的数据集与前面两个例子有一个有趣的区别。它包含的数据点相对较少,只有 506 个,分为 404 个训练样本和 102 个测试样本。输入数据的每个特征(比如犯罪率)都有不同的取值范围。例如,有些特性是比例,取值范围为 0~1;有的取值范围为 1~12;还有的取值范围为 0~100,等等。
(由于是在Jupyter Notebook上直接copy下来的,所以使用时请记得注意。)
## 1. 加载波士顿房价数据集
from tensorflow.keras.datasets import boston_housing
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
train_data.shape
train_targets.shape
train_targets
test_data.shape
test_targets.shape
## 2. 数据标准化
#如果量纲不一致,最好对输入向量进行标准化,此处采用减去均值除以标准差。
#即对于输入数据的每个特征(输入数据矩阵中的列),减去特征平均值,再除以标准差,这样得到的特征平均值为0,标准差为1。
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
## 3. 模型定义
from tensorflow.keras import models
from tensorflow.keras import layers
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
## 4. K折验证
import numpy as np
k = 4 #由于训练集数量少,为了得到较好的超参数,采用K折交叉法,此处K取4,也就是3折用作训练,1折用作验证。
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
print('processing fold #', i)
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples] #准备验证数据:第K个分区的数据
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
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() #构建Keras模型(已编译)
model.fit(partial_train_data, partial_train_targets,
epochs=num_epochs, batch_size=1, verbose=0) #训练模型(静默模式,verbose=0)
val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0) #在验证数据上评估模型
all_scores.append(val_mae)
all_scores
np.mean(all_scores)
## 5. 保存每折的验证结果
num_epochs = 500
all_mae_histories = []
for i in range(k):
print('processing fold ##', i)
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples] #准备验证数据:第K个分区的数据
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
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() #构建Keras模型(已编译)
history=model.fit(partial_train_data, partial_train_targets,validation_data=(val_data,val_targets),
epochs=num_epochs, batch_size=1, verbose=0) #训练模型(静默模式,verbose=0)
mae_history = history.history['val_mae'] #在验证数据上评估模型
all_mae_histories.append(mae_history)
history_dict=history.history
history_dict.keys()
## 6. 计算所有轮次中所有折MAE的平均值
average_mae_history=[np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]
## 7. 绘制验证分数
import matplotlib.pyplot as plt
plt.plot(range(1,len(average_mae_history)+1),average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE')
plt.show()
## 8. 绘制验证分数(删除前10个数据点)
def smooth_curve(points,alpha = 0.9):
smothed_points = []
for point in points:
if smothed_points:
pre_point = smothed_points[-1]
smothed_points.append (pre_point*alpha + point*(1- alpha))
else:
smothed_points.append(point)
return smothed_points
smooth_mae_history = smooth_curve(average_mae_history[10:])
plt.plot(range(1,len(smooth_mae_history)+1),smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MAE after 10 epchs(smoothed)')
plt.show()
## 9. 计算所有轮次中所有折MAE的平均值
# Get a fresh, compiled model.
model = build_model()
# Train it on the entirety of the data.
model.fit(train_data, train_targets,
epochs=80, batch_size=16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)
test_mae_score
test_mse_score
小结:
- 回归问题使用的损失函数与分类问题不同。回归常用的损失函数是均方误差(MSE)。
- 同样,回归问题使用的评估指标也与分类问题不同。显而易见,精度的概念不适用于回归问题。常见的回归指标是平均绝对误差(MAE)。
- 如果输入数据的特征具有不同的取值范围,应该先进行预处理,对每个特征单独进行缩放。
- 如果可用的数据很少,使用 K 折验证可以可靠地评估模型。
- 如果可用的训练数据很少,最好使用隐藏层较少(通常只有一到两个)的小型网络,以避免严重的过拟合。