深度学习 从零开始 —— 神经网络(六),回归问题,波士顿房间数据

回归问题

预测输入数据对应的一个连续值,而不是离散的标签。

比如根据气象数据预测气温等等。

加载数据

波士顿房价数据集,基本上就是根据13种不同数值,例如周边学校个数,犯罪率等等,来预测房价。

from keras.datasets import boston_housing

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

print(train_data.shape)

print(test_data.shape)

print(train_targets)

在这里插入图片描述
可以看到训练样本有404个,测试样本102个。每个样本是包含13个特征。
目标是每个样本对应的房价。单位是千美元。

数据预处理

将取值范围差异很大的数据输入到神经网络,这是有问题的。
网络可能会自适应这种取值范围不同,但是学习肯定会变得更困难。

对应这样的数据,通常对每个特征进行标准化。即,减去特征平均值,再除以标准差。这样得到的特征平均值为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

最后一层网络只有一个单元,没有激活,是一个线性层。
这是标量回归(标量回归是预测单一连续值的回归)的典型设置。
添加激活函数将限制输出范围。
损失函数用的是mse均方误差(MES, mean squared error),预测值与目标值之差的平方。这是回归问题常用的损失函数。

监控的指标为mae平均绝对误差(MAE, mean absolute error),预测值与目标值之差的绝对值

K折交叉验证

之前的验证数据都是直接从训练数据中取出来一部分。
但是目前这个案例数据太少了,再分就更少了。

采用k折交叉验证。
具体做法是,将数据划分为K个分区(通常K是4或者5)。实例化K个相同模型,每个模型在K-1个分区上训练,在剩下一个分区上验证评估。模型的验证分数等于K个验证分数的平均值。

在这里插入图片描述

#K折验证
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]#取出第i块分区数据用作验证
    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=1,verbose=0)# 训练模式(静默模式,verbose=0)
    val_mse, val_mae = model.evaluate(val_data,val_targets,verbose=0)# 验证数据集上评估
    all_scores.append(val_mae)

print(all_scores)
print(np.mean(all_scores))

在这里插入图片描述
评价分数为2.5。因此预测价格与实际价格平均相差2500美元。还是挺大差别的。

我们将轮次epochs提升到500次。并计算出所有轮次中的所有折的MAE平均值。并将图画出来

import matplotlib.pyplot as plt

#K折验证
k = 4
num_val_samples = len(train_data) // k
num_epochs = 500
# all_scores = []
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]#取出第i块分区数据用作验证
    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,
              epochs=num_epochs,batch_size=1,verbose=0)# 训练模式(静默模式,verbose=0)
    # val_mse, val_mae = model.evaluate(val_data,val_targets,verbose=0)# 验证数据集上评估
    # all_scores.append(val_mae)
    mae_history = history.history['val_mean_absolute_error']
    all_mae_histories.append(mae_history)

# print(all_scores)
# print(np.mean(all_scores))

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

plt.plot(range(1,len(average_mae_history)+1),average_mae_history)
plt.xlabel('Epochs')
plt.ylabel('val MAE')
plt.show()

在这里插入图片描述
纵轴范围太大,删除前十个数据。
将每个数据点替换为前面数据点的指数移动平均值,来得到光滑的曲线。

def smooth_curve(points, factor = 0.9):
    smoothed_points = []
    for point in points:
        if smoothed_points:
            previous = smoothed_points[-1]
            smoothed_points.append(previous * factor + point * (1 - factor))
        else:
            smoothed_points.append(point)
    return smoothed_points

average_mae_history = [np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]

smooth_mae_history = smooth_curve(average_mae_history[10:])

plt.plot(range(1,len(smooth_mae_history)+1),smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('val MAE')
plt.show()

在这里插入图片描述

可以看出一直在降。
则可以根据最佳参数,训练最终模型。

训练最终模型

from keras.datasets import boston_housing
from keras import models
from keras import layers
import numpy as np

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

print(train_data.shape)

print(test_data.shape)

print(train_targets)

#数据减去平均值,再除以标准差
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
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

model = build_model()
model.fit(train_data,train_targets,
          epochs=500, batch_size=16, verbose=0)
test_mse_score, test_mae_score = model.evaluate(test_data,test_targets)

print(test_mae_score)

在这里插入图片描述
预测的放假和真实值平均差2400美元。

实验中间过程全部代码

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()

print(train_data.shape)

print(test_data.shape)

print(train_targets)

#数据减去平均值,再除以标准差
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
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
num_val_samples = len(train_data) // k
num_epochs = 500
# all_scores = []
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]#取出第i块分区数据用作验证
    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,
              epochs=num_epochs,batch_size=16,verbose=0)# 训练模式(静默模式,verbose=0)
    # val_mse, val_mae = model.evaluate(val_data,val_targets,verbose=0)# 验证数据集上评估
    # all_scores.append(val_mae)
    mae_history = history.history['mae']
    all_mae_histories.append(mae_history)

# print(all_scores)
# print(np.mean(all_scores))
#
# plt.plot(range(1,len(all_scores)+1),all_scores)
# plt.xlabel('Epochs')
# plt.ylabel('val MAE')
# plt.show()

def smooth_curve(points, factor = 0.9):
    smoothed_points = []
    for point in points:
        if smoothed_points:
            previous = smoothed_points[-1]
            smoothed_points.append(previous * factor + point * (1 - factor))
        else:
            smoothed_points.append(point)
    return smoothed_points

average_mae_history = [np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]

smooth_mae_history = smooth_curve(average_mae_history[10:])

plt.plot(range(1,len(smooth_mae_history)+1),smooth_mae_history)
plt.xlabel('Epochs')
plt.ylabel('val MAE')
plt.show()

猜你喜欢

转载自blog.csdn.net/wwb1990/article/details/104952688
今日推荐