kreas搭建神经网络预测波士顿房价(手写K折交叉验证)
1、程序说明
所有注意事项均写入注释
from keras.datasets import boston_housing
import numpy as np
from keras import models
from keras import layers
from keras.optimizers import RMSprop
# 载入数据
(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
# 训练集404个,测试集102个,13个属性
# print(train_data[0])
# print(train_data.shape)
# print(train_targets)
# print(test_data.shape)
# 数据标准化
'''
用于测试数据标准化的均值和标准差都是在训练数据上计算得到的。
不能使用在测试数据上计算得到的任何结果,即使是像数据标准化这么简单的事情也不行。
'''
mean = train_data.mean(axis=0)
train_data -= mean
test_data -= mean
std = train_data.std(axis=0)
train_data -= std
test_data -= std
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'))
'''
网络的最后一层只有一个单元,没有**,是一个线性层。这是标量回归(标量回归是预
测单一连续值的回归)的典型设置。添加**函数将会限制输出范围。例如,如果向最后一层
添加 sigmoid **函数,网络只能学会预测 0~1 范围内的值。这里最后一层是纯线性的,所以
网络可以学会预测任意范围内的值。
'''
model.add(layers.Dense(units=1))
model.compile(optimizer=RMSprop(lr=0.001), loss='mse', metrics=['mae'])
return model
def k_fold(k, model):
num_val_samples = len(train_data) // k
all_scores = []
for i in range(k):
print('Processing fold #', i+1)
# 准备测试集,第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]
# 准备训练集,除了第i块都是训练集,这里用numpy的concatenate拼接
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)
'''
verbose:日志显示
verbose = 0 为不在标准输出流输出日志信息
verbose = 1 为输出进度条记录
verbose = 2 为每个epoch输出一行记录
注意: 默认为 1
'''
model.fit(partial_train_data, partial_train_targets, epochs=100, batch_size=1, verbose=0)
val_mse, val_mae = model.evaluate(val_data, val_targets)
print('val_mse:', val_mae, ' val_mae:', val_mae)
all_scores.append(val_mae)
return all_scores
if __name__ == '__main__':
all_scores = k_fold(5, build_model())
print(all_scores)
2、训练结果展示
Processing fold # 1
32/80 [===========>..................] - ETA: 0s
80/80 [==============================] - 0s 424us/step
val_mse: 2.2958826065063476 val_mae: 2.2958826065063476
Processing fold # 2
32/80 [===========>..................] - ETA: 0s
80/80 [==============================] - 0s 25us/step
val_mse: 2.2359493732452393 val_mae: 2.2359493732452393
Processing fold # 3
32/80 [===========>..................] - ETA: 0s
80/80 [==============================] - 0s 25us/step
val_mse: 1.8176211357116698 val_mae: 1.8176211357116698
Processing fold # 4
32/80 [===========>..................] - ETA: 0s
80/80 [==============================] - 0s 25us/step
val_mse: 1.8358864784240723 val_mae: 1.8358864784240723
Processing fold # 5
32/80 [===========>..................] - ETA: 0s
80/80 [==============================] - 0s 25us/step
val_mse: 2.025705862045288 val_mae: 2.025705862045288
[2.2958826065063476, 2.2359493732452393, 1.8176211357116698, 1.8358864784240723, 2.025705862045288]
可见,平均mae为2.04,即平均误差为2040美元。
3、k折交叉验证
4、小结
- 回归问题使用的损失函数与分类问题不同。回归常用的损失函数是均方误差(MSE),常见的回归指标是平均绝对误差(MAE)。
- 如果可用的数据很少,使用 K 折验证可以可靠地评估模型。
- 如果输入数据的特征具有不同的取值范围,应该先进行预处理,对每个特征单独进行缩放。
- 如果可用的训练数据很少,最好使用隐藏层较少(通常只有一到两个)的小型网络,以避免严重的过拟合。