Python深度学习(3):波士顿房价预测

mac2022-06-30  148

这是《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() ''' #得到结果发现在第80轮后mae不再显著降低,epochs设为80 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)

训练结果

最新回复(0)