Keras深度学习(4)-回归问题之预测房价

在深度学习的任务中,回归问题也是一个常见的任务。
本文将要预测 20 世纪 70 年代中期波士顿郊区房屋价格的中位数,已知当时郊区的一些数据点,比如犯罪率、当地房产税率等。本节用到的数据集与前面两个例子有一个有趣的区别。它包含的数据点相对较少,只有 506 个,分为 404 个训练样本和 102 个测试样本。输入数据的每个特征(比如犯罪率)都有不同的取值范围。例如,有些特性是比例,取值范围为 0~1;有的取值范围为 1~12;还有的取值范围为 0~100,等等。

1 回归问题模型的训练

回归问题有以下几个要点:

  • 隐藏层激活函数用relu
  • 输出层只有一个值,并且不用激活函数(相当于使用恒等函数)
  • 损失函数使用均方误差mse
  • 监控指标使用平均绝对误差mae

模型的训练代码如下:

import numpy as np 
from tensorflow.keras.datasets import boston_housing
from tensorflow.keras import models
from tensorflow.keras import layers
import matplotlib.pyplot as plt

def build_model():
    model=models.Sequential()
    model.add(layers.Dense(units=64,activation='relu',input_shape=(13,)))
    model.add(layers.Dense(units=64,activation='relu'))
    #回归问题的输出问题不需要激活函数,默认就为恒等函数
    model.add(layers.Dense(units=1))
    #损失函数使用均方误差 监控指标使用平均绝对误差
    model.compile(optimizer='rmsprop',loss='mse',metrics=['mae'])

    return model

if __name__=='__main__':
    #准备训练数据
    #(404, 13) (404,)   (102, 13) (102,)
    #每个样本中有13个数值特征,比如人均犯罪率、每个住宅的平均房间数等
    #目标是房屋价格的中位数,单位是千美元
    (train_data,train_targets),(test_data,test_targets)=boston_housing.load_data()
    
    #将数据标准化
    #减去特征平均值,再除以标准差,得到特征平均值为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

    #由于训练样本过少,采用K折交叉验证
    k=4
    num_val_samples=len(train_data)//k
    num_epochs=500
    all_val_mae_histories=[]
    all_scores=[]

    for i in range(k):
        print('第几折:'+str(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]

        #训练集
        x_train_data=np.concatenate([train_data[:i*num_val_samples],
                                     train_data[(i+1)*num_val_samples:]],axis=0)
        y_train_targers=np.concatenate([train_targets[:i*num_val_samples],
                                        train_targets[(i+1)*num_val_samples:]],axis=0)
        
        model=build_model()
        #verbose=0代表训练时用的是静默模式
        history=model.fit(x=x_train_data,
                          y=y_train_targers,
                          validation_data=(val_data,val_targets),
                          epochs=num_epochs,
                          batch_size=1,
                          verbose=1)
        
        #保存验证的平均绝对误差
        val_mae_history=history.history['val_mae']
        all_val_mae_histories.append(val_mae_history)

    #计算所有轮次中K折验证分数的平均值
    average_mae_history=[np.mean([x[i] for x in all_val_mae_histories]) for i in range(num_epochs)]

    #绘制验证分数 不要绘制前10个数据点
    plt.plot(range(1+10,len(average_mae_history)+1),average_mae_history[10:])
    plt.xlabel('Epochs')
    plt.ylabel('Validation MAE')
    plt.show()

    #从上面的k折交叉验证得到验证损失图像中得出最佳的训练批次是80次
    #然后以这个次数训练得到最终的模型
    #在所有数据上得到训练模型
    model=build_model()
    model.fit(x=train_data,
              y=train_targets,
              epochs=80,
              batch_size=16)
    
    #在测试数据上评价
    test_mse_score, test_mae_score = model.evaluate(test_data, test_targets)
    print('test_mse_score:'+str(test_mse_score))
    print('test_mae_score:'+str(test_mae_score))

    #保存模型
    model.save('./model/house.h5')



在这个例子中,由于训练样本非常少,只有四百多个,为了在调节网络参数(比如训练的轮数)的同时对网络进行评估,你可以将数据划分为训练集和验证集,正如前面例子中所做的那样。但由于数据点很少,验证集会非常小(比如大约100 个样本)。因此,验证分数可能会有很大波动,这取决于你所选择的验证集和训练集。也就是说,验证集的划分方式可能会造成验证分数上有很大的方差,这样就无法对模型进行可靠的评估。
在这种情况下,最佳做法是使用 K 折交叉验证(见图 3-11)。这种方法将可用数据划分为 K个分区(K 通常取 4 或 5),实例化 K 个相同的模型,将每个模型在 K-1 个分区上训练,并在剩下的一个分区上进行评估。模型的验证分数等于 K 个验证分数的平均值。这种方法的代码实现很简单。
下图为3折交叉验证。
Keras深度学习(4)-回归问题之预测房价_第1张图片
交叉验证的具体代码如下:

#由于训练样本过少,采用K折交叉验证
    k=4
    num_val_samples=len(train_data)//k
    num_epochs=500
    all_val_mae_histories=[]
    all_scores=[]

    for i in range(k):
        print('第几折:'+str(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]

        #训练集
        x_train_data=np.concatenate([train_data[:i*num_val_samples],
                                     train_data[(i+1)*num_val_samples:]],axis=0)
        y_train_targers=np.concatenate([train_targets[:i*num_val_samples],
                                        train_targets[(i+1)*num_val_samples:]],axis=0)
        
        model=build_model()
        #verbose=0代表训练时用的是静默模式
        history=model.fit(x=x_train_data,
                          y=y_train_targers,
                          validation_data=(val_data,val_targets),
                          epochs=num_epochs,
                          batch_size=1,
                          verbose=1)
        
        #保存验证的平均绝对误差
        val_mae_history=history.history['val_mae']
        all_val_mae_histories.append(val_mae_history)

从交叉样本得到的验证平均绝对误差图像中,主要为了得到模型最适合的训练次数。
Keras深度学习(4)-回归问题之预测房价_第2张图片
从上图中判断出epochs的次数在80时,得到的模型效果最好,因此最终训练的模型我们以80次作为训练总批次得到最终模型。

model=build_model()
    model.fit(x=train_data,
              y=train_targets,
              epochs=80,
              batch_size=16)

最终训练得到模型文件,在测试数据上的平均绝对误差为:2.876593589782715,这表示预测的房价与真实的房价相差2876美元。
得到的模型结构图为:
Keras深度学习(4)-回归问题之预测房价_第3张图片

2 回归问题模型的调用

调用代码如下:

import numpy as np
from sympy import re 
from tensorflow.keras.datasets import boston_housing
from tensorflow.keras import models
from tensorflow.keras import layers

if __name__=='__main__':
    #准备训练数据
    #(404, 13) (404,)   (102, 13) (102,)
    #每个样本中有13个数值特征,比如人均犯罪率、每个住宅的平均房间数等
    #目标是房屋价格的中位数,单位是千美元
    (train_data,train_targets),(test_data,test_targets)=boston_housing.load_data()
    
    #将数据标准化
    #减去特征平均值,再除以标准差,得到特征平均值为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

    #载入模型
    model=models.load_model('./model/house.h5')
    model.summary()

    #预测测试数据中的第22个数据
    print('这一年的真实房价为:'+str(test_targets[22])+'(千美元)')
    result=model.predict(test_data[22].reshape(1,-1))
    print('这一年的预测房价为:'+str(result[0][0])+'(千美元)')

预测结果如下:
这一年的真实房价为:20.0(千美元)
这一年的预测房价为:21.134518(千美元)

可见,预测的价格与真实价格仅仅相差1千美元,这个回归模型效果还是可以的。

你可能感兴趣的:(深度学习,回归,深度学习,keras,房价预测,回归问题)