1. 程式人生 > >keras探索:regression-波士頓房價預測例項(小樣本K折驗證)

keras探索:regression-波士頓房價預測例項(小樣本K折驗證)


open source: deep learning with python (keras)

open code: https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/3.7-predicting-house-prices.ipynb


from keras.datasets import boston_housing
from keras import models
from keras import layers

import numpy as np
import matplotlib.pyplot as plt


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)) # activation function will limit putput range
    model.compile(optimizer = 'rmsprop',
                  loss = 'mse',
                  metrics=['mae'])
    return model
    

(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


#++++++++++++++++K-fold validation
k = 4
num_val_samples = len(train_data) // k
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]
    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()
    history = model.fit(partial_train_data,
                        partial_train_targets,
                        validation_data = (val_data, val_targets),
                        epochs = num_epochs,
                        batch_size = 1,
                        verbose = 1)
    mae_history = history.history['val_mean_absolute_error']
    all_mae_histories.append(mae_history)
    average_mae_history = [ np.mean([x[i] \
                                    for x in all_mae_histories]) \
                                    for i in range(num_epochs)]

#+++++++++++++++++ triaining final model
model = build_model()
model.fit(train_data, 
          train_targets,
          epochs = 100,
          batch_size = 16,
          verbose = 1)
test_mae, _ = model.evaluate(test_data, test_targets)


#+++++++++++++++++ matplotlib
plt.plot(range(1, len(average_mae_history)+1), average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('Validation Mae')
plt.show()

總結-關於小樣本K-折驗證:

    為了調節神經網路(比如說神經網路的訓練輪數)的同時對網路進行評估,我們需要將資料集劃分為訓練集和測試集。如果樣本的資料量很少(小樣本問題),驗證集會更小,因此驗證分數可能會有很大的波動,這完全取決於如何劃分訓練集和驗證集。這就是小樣本中常見的,驗證集的劃分方式可能會存在很大的方差,這種情況下很難對模型進行有效可靠地評估。

    最佳做法是採用K-折驗證的方式,其原理圖如下所示。

 

  • 如果訓練資料集相對較小,則增大k值

         增大k值,在每次迭代過程中將會有更多的資料用於模型訓練,能夠得到最小偏差,同時演算法時間延長。且訓練塊間高度相似,導致評價結果方差較高。

  • 如果訓練集相對較大,則減小k值

        減小k值,降低模型在不同的資料塊上進行重複擬合的效能評估的計算成本,在平均效能的基礎上獲得模型的準確評估。