1. 程式人生 > >[Deep-Learning-with-Python]基於Keras的房價預測

[Deep-Learning-with-Python]基於Keras的房價預測

預測房價:迴歸問題

迴歸問題預測結果為連續值,而不是離散的類別。

波士頓房價資料集

通過20世紀70年代波士頓郊區房價資料集,預測平均房價;資料集的特徵包括犯罪率、稅率等資訊。資料集只有506條記錄,劃分成404的訓練集和102的測試集。每個記錄的特徵取值範圍各不相同。比如,有0~1,1~12以及0~100的等等。

載入資料集

from keras.datasets import boston_housing

(train_data,train_targets),(test_data,test_targets) = boston_housing.load_data()

訓練集形狀:

>>> 
train_data.shape (404, 13)

測試集形狀:

>>> test_data.shape
(102, 13)

訓練集404條,測試集102條;每條記錄13個數值特徵。
房價單位為1000美元。

>>> train_targets
[ 15.2, 42.3, 50. ...19.4,19.4,29.1]

房價範圍在10,00050,000。

準備資料

因為資料各個特徵取值範圍各不相同,不能直接送到神經網路模型中進行處理。儘管網路模型能適應資料的多樣性,但是相應的學習過程變得非常困難。一種常見的資料處理方法是特徵歸一化normalization—減均值除以標準差;資料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

模型構建

由於資料集資料量過小,模型也不能太複雜,否則容易發生過擬合。

from keras import models
from 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

模型的最後一層只有一個神經元,沒有啟用函式–相當於一個線性層。這種處理方法常用在單標量回歸問題中。使用啟用函式將會限制輸出結果的範圍,比如使用sigmoid啟用函式,輸出結果在0~1之間。這裡,因為最後一層只是一個線性層,模型的輸出結果可能是任意值。
模型的損失函式為mse均方誤差。監測的指標為mean absolute error(MAE)平均絕對誤差—兩個結果之間差的絕對值。

K折交叉驗證

當調整模型引數時,為了評估模型,我們通常將資料集分成訓練集和驗證集。但是當資料量過小時,驗證集數目也變得很小,導致驗證集上的評估結果相互之間差異性很大—與訓練集和測試集的劃分結果相關。評估結果可信度不高。
最好的評估方式是採用K折交叉驗證–將資料集分成K份(K=4或5),例項化K個模型,每個模型在K-1份資料上進行訓練,在1份資料上進行評估,最後用K次評估分數的平均值做最後的評估結果。

import numpy as np

k = 4
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] # 劃分出驗證集部分
    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()
    model.fit(partial_train_data,partial_train_targets,epochs=num_epochs,batch_size=16,verbose=0)#模型訓練silent模型
    val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0) # 驗證集上評估
    all_scores.append(val_mae)

模型訓練

model = build_model()
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)# score 2.5532484335057877

 小結

  • 迴歸問題:損失函式通常為MSE均方誤差;
  • 模型評估監測指標通常為MAE(mean absolute error);
  • 當資料取值範圍不一致時,需要對特徵進行預處理;
  • 資料量小時,可以採用K折驗證來衡量模型;
  • 資料量小時,模型複雜度也應該相應的簡單,可以避免模型過擬合。