我正在学习!机器学习标量回归示例:房价预测


标量回归

上一次我现在学习!机器学习多类别分类示例:我们对新闻发布进行分类。多类单标签分类是预测多个标签之一的问题。
回归问题是预测连续值而不是预测标签。例如,您可以根据过去的价格预测明天的股价,或者根据过去的温度预测明天的温度。
*请注意,回归和逻辑回归是不同的。 Logistic回归属于分类算法。

房屋价格预测

这次,我们将解决预测1970年代中期波士顿附近房价中位数的问题。
预测数据包括房间数量和大小,犯罪率和税率等数据点。
另外,这次使用的数据点数仅为506(404训练数据和102测试数据),与分类问题的情况相比非常小。
输入数据的特征量使用不同的比例(犯罪率,税率,房间数等),这与先前的分类问题也有很大不同。

读取样本数据

tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
# データ読み込み
from keras.datasets import boston_housing

(train_data, train_targets), (test_data, test_targets) = boston_housing.load_data()
# データの確認
print(train_data.shape)
>>> (404, 13)
print(test_data.shape)
>>> (102, 13)
print(train_data[0])
>>> [  1.23247   0.        8.14      0.        0.538     6.142    91.7
   3.9769    4.      307.       21.      396.9      18.72   ]

数据准备

由于价格,房间大小和房间类型等值不同,因此需要对特征数据进行规范化。
*规范化:将价格,房间大小和房间类型调整为相同标准值的过程。
归一化中通常使用的方法是"减去每个特征的特征平均值并除以标准差"。

tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# データを特徴量ごとに正規化する関数
def make_train_data(dataset, axis = 0):
    """
     特徴量ごとにデータを正規化する
     [手順]
     入力データを特徴量ごとに特徴量の平均値を引き、標準偏差で割る
     --------
     dataset:正規化するデータ
     axis   :軸を指定(データが2次元配列なら0 #列が対象)
    """
    mean = dataset.mean(axis) # 1軸目の平均値(2次配列なので各列の平均値)
    dataset -= mean # 平均値で引く
    std = dataset.std(axis) # 標準偏差
    dataset /= std # 標準偏差で割る

    return dataset

# 訓練でータを正規化
train_data = make_train_data(train_data, 0)
# テストデータも正規化
test_data = make_train_data(test_data, 0)

神经网络的构建和模型定义

设计模型。
层设计层的类型,输入和输出的数量,激活功能的类型以及层的数量。
这次,由于我们使用一种称为k折叠交叉验证的方法来调用多个模型实例,因此我们将其定义为用于模型生成的函数,并在实现时调用该函数。

tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# モデルの定義
from keras import models
from keras import layers

"""
MEA
平均絶対誤差(mean absolute error):予測値と目的地の誤差の絶対値の平均
"""
def build_model(train_data):
    # モデルインスタンスを生成するメソッド
    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验证交叉验证?将数据集划分为k个样本集(折叠)并创建相同模型的k个实例。
    一种使用k-1个样本集训练k个模型,执行一个验证并最终平均验证分数的方法。
    k值通常为4或5。

tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import numpy as np

# k分割交差検証データの生成
"""
エポック数を500に増やし、エポックごとに検証ログを保存するようにして再訓練と検証を行う
"""
num_epochs = 500
k          = 4
num_val_samples = len(train_data) // 4 # 小数点以下切り捨て
all_mae_histories = []
for i in range(k):
    print('processing fold #', i)
    # 検証データの準備:フォールドiのデータ
    key   = i * num_val_samples
    value = (i + 1) * num_val_samples

    val_data    = train_data[key:value]
    val_targets = train_targets[key:value]

    # 訓練データの準備:残りのフォールドのデータ
    partial_train_data = np.concatenate(
       [
          train_data[:key],
          train_data[value:]
       ],
       axis = 0
    )
    partial_train_targets = np.concatenate(
       [
          train_targets[:key],
          train_targets[value:]
       ],
       axis = 0
    )

    # モデルインスタンスを取得
    model = build_model(train_data)

    # モデルをサイレントモードで訓練と検証を実施
    history = model.fit(
            partial_train_data,
            partial_train_targets,
            validation_data = (val_data, val_targets),
            epochs = num_epochs,
            batch_size = 1,
            verbose = 0
    )
    # i回目の平均絶対誤差を取得して格納
    mea_history = history.history['val_mean_absolute_error']
    all_mae_histories.append(mea_history)

# k分割交差検証の平均スコアの履歴を作成
average_mae_history = [np.mean([x[i] for x in all_mae_histories]) for i in range(num_epochs)]

第i个(培训,验证)输出日志

1
2
3
4
processing fold # 0
processing fold # 1
processing fold # 2
processing fold # 3

情节训练(验证)数据

tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 結果をプロット
import matplotlib.pyplot as plt

# このままだとグラフがみずらいので見やすくなるように修正
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

smoothed_mea_history = smooth_curve(average_mae_history[10:])

plt.plot(range(1, len(smoothed_mea_history) + 1), smoothed_mea_history)
plt.xlabel('Epochs')
plt.ylabel('Validation MEA')
plt.show()

ダウンロード.png

数据验证

从上图可以看出,验证得分(MEA =平均绝对误差)在30个纪元左右有了明显改善,然后出现了过拟合现象。
因此,调整模型并再次训练。

tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np


model = build_model(train_data)

# モデルをサイレントモードでfit
model.fit(
        train_data,
        train_targets,
        epochs = 30,
        batch_size = 8,
        verbose = 0 # サイレントモード
)

# 検証スコアを取得
test_mse_score, test_mea_score = model.evaluate(test_data, test_targets)


# 訓練結果出力
print(test_mea_score)
>>> 2.7296556491477815

回顾

我再次尝试了30个纪元,批量大小为8,但错误不如2700。
此后,调整时期数并以各种方式更改它们并不能取得良好的效果。
本练习的目的是如何实现回归问题的模型以及如何调整模型。
调整模型时,我发现绘制了验证分数(MEA =平均绝对误差)以找到最小点,所以它很好(基本测试结果不好,但是即使在练习教科书。

摘要

  • 在回归中,将数据归一化(归一化中常用的方法是"减去每个特征的特征平均值并除以标准差")。
  • 损失函数通常使用MSE(均方误差)。
  • MEA(平均绝对误差)通常用作评估功能。
  • 如果几乎没有可用数据,则使用k倍交叉验证是有效的。
  • 如果可用的训练数据较少,请使用具有较少隐藏层(1或2)的较小网络。