TensorFlow : Tutorials : Keras : 住宅価格を予測する: 回帰 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 08/26/2018
* TensorFlow 1.10 で更に改訂されています。
* TensorFlow 1.9 でドキュメント構成が変更され、数篇が新規に追加されましたので再翻訳しました。
* 本ページは、TensorFlow の本家サイトの Tutorials – Learn and use ML – Predict house prices: regression を翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
回帰問題では、価格や確率のような、連続値の出力を予測することを目標にします。これを分類問題と対比すると、そこでは離散ラベルを予測することを目標にしています (例えば、そこでは絵がりんごかオレンジを含みます)。
このノートブックは、1970 年代半ばの間の Boston 郊外の住宅の median 価格を予測するモデルを構築します。これを行なうために、犯罪率と地方財産 (= local property) 税率のような、郊外についての幾つかのデータポイントを持つモデルを提供します。
このサンプルは tf.keras API を使用します、詳細は このガイド を見てください。
import tensorflow as tf from tensorflow import keras import numpy as np print(tf.__version__)
1.10.0
Boston 住宅価格データセット
データセット は TensorFlow で直接アクセス可能です。訓練セットをダウンロードしてシャッフルします :
boston_housing = keras.datasets.boston_housing (train_data, train_labels), (test_data, test_labels) = boston_housing.load_data() # Shuffle the training set order = np.argsort(np.random.random(train_labels.shape)) train_data = train_data[order] train_labels = train_labels[order]
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/boston_housing.npz 57344/57026 [==============================] - 0s 0us/step
サンプルと特徴
データセットはこれまでに作業した他のものよりも遥かに小さいです: それは 506 総計サンプルを持ち、404 訓練サンプルと 102 テストサンプルに分割されています :
print("Training set: {}".format(train_data.shape)) # 404 examples, 13 features print("Testing set: {}".format(test_data.shape)) # 102 examples, 13 features
Training set: (404, 13) Testing set: (102, 13)
データセットは 13 の異なる特徴を含みます :
- 一人当たりの犯罪率。
- 25,000 平方フィート超の区画の住宅地の比率
- タウン毎の非小売りビジネスエーカーの比率。
- チャールズ川ダミー変数 (= 1 区画が川に隣接する場合; 0 otherwise)。
- 酸化窒素濃度 (parts per 10 million (訳注: 千万分率)).
- 住居当たりの平均部屋数。
- 1940 以前に建てられた所有者が住むユニットの比率。
- 5 つの Boston 雇用センターへの荷重距離。
- 放射状光速道路へのアクセス可能性のインデックス。
- $10,000 当たりの全額財産税率。
- タウン毎の 1 教師当たりの生徒数比率。
- 1000 * (Bk – 0.63) ** 2 ここで Bk はタウンによる黒人の比率です。
- 地位が比較的低い人口の割合。
これらの入力データ特徴の各々は異なるスケールを使用してストアされます。ある特徴は 0 と 1 の間の比率で表わされ、他の特徴は 1 と 12 の間の範囲で、幾つかは 0 と 100 の間の範囲です、等々。これは現実世界のデータでしばしば当てはまり、そのようなデータをどのように調査してクリーンにするかを理解することは開発のために重要なスキルです。
print(train_data[0]) # Display sample features, notice the different scales
[7.8750e-02 4.5000e+01 3.4400e+00 0.0000e+00 4.3700e-01 6.7820e+00 4.1100e+01 3.7886e+00 5.0000e+00 3.9800e+02 1.5200e+01 3.9387e+02 6.6800e+00]
データセットの最初の数行を良くフォーマットされたテーブルで表示するために pandas ライブラリを使用します :
import pandas as pd column_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT'] df = pd.DataFrame(train_data, columns=column_names) df.head()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | |
0 | 0.07875 | 45.0 | 3.44 | 0.0 | 0.437 | 6.782 | 41.1 | 3.7886 | 5.0 | 398.0 | 15.2 | 393.87 | 6.68 |
1 | 4.55587 | 0.0 | 18.10 | 0.0 | 0.718 | 3.561 | 87.9 | 1.6132 | 24.0 | 666.0 | 20.2 | 354.70 | 7.12 |
2 | 0.09604 | 40.0 | 6.41 | 0.0 | 0.447 | 6.854 | 42.8 | 4.2673 | 4.0 | 254.0 | 17.6 | 396.90 | 2.98 |
3 | 0.01870 | 85.0 | 4.15 | 0.0 | 0.429 | 6.516 | 27.7 | 8.5353 | 4.0 | 351.0 | 17.9 | 392.43 | 6.36 |
4 | 0.52693 | 0.0 | 6.20 | 0.0 | 0.504 | 8.725 | 83.0 | 2.8944 | 8.0 | 307.0 | 17.4 | 382.00 | 4.63 |
ラベル
ラベルは数千ドル単位の住居価格です (1970 年代なかばの価格であることに気がつくかもしれません)。
print(train_labels[0:10]) # Display first 10 entries
[32. 27.5 32. 23.1 50. 20.6 22.6 36.2 21.8 19.5]
特徴を正規化する
異なるスケールと範囲を使用している特徴を正規化することが推奨されます。各特徴について、特徴の平均を減算して標準偏差で除算します。
# Test data is *not* used when calculating the mean and std. mean = train_data.mean(axis=0) std = train_data.std(axis=0) train_data = (train_data - mean) / std test_data = (test_data - mean) / std print(train_data[0]) # First training sample, normalized
[-0.39725269 1.41205707 -1.12664623 -0.25683275 -1.027385 0.72635358 -1.00016413 0.02383449 -0.51114231 -0.04753316 -1.49067405 0.41584124 -0.83648691]
特徴の正規化なしでもモデルは収束しますが、訓練をより困難にし、結果としてのモデルを入力で使用されたユニットの選択により依存させます。
モデルを作成する
モデルを構築しましょう。ここでは、2 つの密に接続された隠れ層を持ち、そして単一の、連続値を返す出力層を持つ Sequential モデルを使用します。モデル構築ステップは関数 build_model にラップされます、何故ならば、後で 2 番目のモデルを作成するからです。
def build_model(): model = keras.Sequential([ keras.layers.Dense(64, activation=tf.nn.relu, input_shape=(train_data.shape[1],)), keras.layers.Dense(64, activation=tf.nn.relu), keras.layers.Dense(1) ]) optimizer = tf.train.RMSPropOptimizer(0.001) model.compile(loss='mse', optimizer=optimizer, metrics=['mae']) return model model = build_model() model.summary()
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 64) 896 _________________________________________________________________ dense_1 (Dense) (None, 64) 4160 _________________________________________________________________ dense_2 (Dense) (None, 1) 65 ================================================================= Total params: 5,121 Trainable params: 5,121 Non-trainable params: 0 _________________________________________________________________
モデルを訓練する
モデルは 500 エポックの間訓練されて、訓練と検証精度を history オブジェクトに記録します。
# Display training progress by printing a single dot for each completed epoch. class PrintDot(keras.callbacks.Callback): def on_epoch_end(self,epoch,logs): if epoch % 100 == 0: print('') print('.', end='') EPOCHS = 500 # Store training stats history = model.fit(train_data, train_labels, epochs=EPOCHS, validation_split=0.2, verbose=0, callbacks=[PrintDot()])
history オブジェクトにストアされたスタッツを使用してモデルの訓練進捗を可視化します。モデルが向上するのを停止する前にどのくらい長く訓練するかを決定するためにこのデータを使用することを望みます。
import matplotlib.pyplot as plt def plot_history(history): plt.figure() plt.xlabel('Epoch') plt.ylabel('Mean Abs Error [1000$]') plt.plot(history.epoch, np.array(history.history['mean_absolute_error']), label='Train Loss') plt.plot(history.epoch, np.array(history.history['val_mean_absolute_error']), label = 'Val loss') plt.legend() plt.ylim([0,5]) plot_history(history)
このグラフはおよそ 200 エポック後に殆どモデルの改良を見せません。検証スコアが改良されないとき訓練を自動的に停止するように model.fit メソッドを更新しましょう。総てのエポックについて訓練条件をテストする callback を使用します。エポックの設定された総量が改良を示すことなしに経過する場合、訓練を自動的に停止します。
model = build_model() # The patience parameter is the amount of epochs to check for improvement. early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=20) history = model.fit(train_data, train_labels, epochs=EPOCHS, validation_split=0.2, verbose=0, callbacks=[early_stop, PrintDot()]) plot_history(history)
グラフは平均エラーがおよそ $2,500 ドルであることを示しています。これは良いでしょうか?そうですね、ラベルの幾つかが $15,000 だけであるとき、$2,500 は取るに足りない量とは言えません。
モデルがテストセット上でどのように遂行するかを見てみましょう :
[loss, mae] = model.evaluate(test_data, test_labels, verbose=0) print("Testing set Mean Abs Error: ${:7.2f}".format(mae * 1000))
Testing set Mean Abs Error: $2679.54
予測する
最後に、テストセットのデータを使用して幾つかの住宅価格を予測します :
test_predictions = model.predict(test_data).flatten() print(test_predictions)
[ 7.832362 18.450851 22.45164 34.88103 27.348196 22.26736 26.963049 21.669811 19.895964 22.601202 19.965273 17.110151 16.567072 44.0524 21.04799 21.103464 26.45786 18.709482 20.825438 27.020702 11.160862 13.017411 22.807884 16.611425 21.076998 26.213572 32.766167 32.652153 11.298579 20.164223 19.82201 14.905633 34.83156 24.764723 19.957857 8.5664625 16.906912 17.79298 18.071428 26.850712 32.625023 29.406805 14.310859 44.013615 31.179125 28.41265 28.72704 19.22457 23.301258 23.555346 37.15091 19.271719 10.640091 14.898285 36.21053 29.63736 12.255004 50.43345 37.141464 26.562092 25.075682 15.84047 15.081948 20.062723 25.168509 21.119642 14.220254 22.637339 12.629622 7.517413 25.981508 30.909727 26.12176 12.866787 25.869745 18.303373 19.470121 24.58047 36.444992 10.777396 22.28932 37.976543 16.47492 14.191712 18.707952 19.026419 21.038057 20.713434 21.794077 32.14987 22.412184 20.55821 27.877415 44.4067 38.00193 21.748753 35.57821 45.50506 26.612532 48.747063 34.60436 20.451048 ]
終わりに
このノートブックは回帰問題を処理するために幾つかのテクニックを紹介しました。
- 平均二乗誤差 (MSE) は (分類問題とは異なる) 回帰問題のために使用される一般的な損失関数です。
- 同様に、回帰のために使用される評価メトリックも分類とは異なります。一般的な回帰メトリックは平均絶対誤差 (MAE) です。
- 入力データ特徴が異なる範囲の値を持つとき、各特徴は独立にスケールされるべきです。
- 多くの訓練データがない場合、overfitting を回避するために少ない隠れ層を持つ小さいネットワークが好ましいです。
- early stopping は overfitting を防ぐために有用なテクニックです。
以上