ホーム » Keras » TensorFlow 2.0 Beta : Tutorials : ML 基本 :- 燃費効率 : 回帰

TensorFlow 2.0 Beta : Tutorials : ML 基本 :- 燃費効率 : 回帰

TensorFlow 2.0 Beta : Beginner Tutorials : ML 基本 :- 燃費効率 : 回帰 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 06/22/2019

* 本ページは、TensorFlow の本家サイトの TF 2.0 Beta – Beginner Tutorials – ML basics の以下のページを翻訳した上で
適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

ML 基本 :- 燃費効率 : 回帰

回帰問題では、価格や確率のような、連続値の出力を予測することを狙いとします。これを分類問題と対比すると、そこではクラスのリストからクラスを選択することを目的とします (例えば、そこでは写真がりんごかオレンジを含む、どのフルーツが写真にあるかを認識します)。

この notebook は古典的な Auto MPG データセットを使用して 1970s 末と 1980s 初期の自動車の燃費効率を予測するモデルを構築します。これを行なうために、その期間からの多くの自動車の記述を持つモデルを提供します。この記述は次のような属性を含みます : 気筒 (= cylinders), 排気量 (= displacement), 馬力 (= horsepower) そして重量 (= weight)。

このサンプルは tf.kreas API を使用します、詳細は このガイド を見てください。

# Use seaborn for pairplot
!pip install -q seaborn
from __future__ import absolute_import, division, print_function, unicode_literals

import pathlib

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

!pip install -q tensorflow==2.0.0-beta1
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers

print(tf.__version__)
2.0.0-beta1

 

The Auto MPG データセット

データセットは UCI Machine Learning レポジトリ から利用可能です。

 

データを得る

最初にデータセットをダウンロードします。

dataset_path = keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")
dataset_path
Downloading data from http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data
32768/30286 [================================] - 0s 4us/step

'/home/kbuilder/.keras/datasets/auto-mpg.data'

pandas を使用してそれをインポートします。

column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight',
                'Acceleration', 'Model Year', 'Origin']
raw_dataset = pd.read_csv(dataset_path, names=column_names,
                      na_values = "?", comment='\t',
                      sep=" ", skipinitialspace=True)

dataset = raw_dataset.copy()
dataset.tail()

MPG Cylinders Displacement Horsepower Weight Acceleration Model Year Origin
393 27.0 4 140.0 86.0 2790.0 15.6 82 1
394 44.0 4 97.0 52.0 2130.0 24.6 82 2
395 32.0 4 135.0 84.0 2295.0 11.6 82 1
396 28.0 4 120.0 79.0 2625.0 18.6 82 1
397 31.0 4 119.0 82.0 2720.0 19.4 82 1

 

データをクリーンにする

データセットは幾つかの未知の値を含みます。

dataset.isna().sum()
MPG             0
Cylinders       0
Displacement    0
Horsepower      6
Weight          0
Acceleration    0
Model Year      0
Origin          0
dtype: int64

この初期チュートリアルを単純に維持するためにこれらの行は破棄します。

dataset = dataset.dropna()

“Origin” カラムは実際には categorical であり、numeric ではありません。そこでそれを one-hot に変換します :

origin = dataset.pop('Origin')
dataset['USA'] = (origin == 1)*1.0
dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail()

MPG Cylinders Displacement Horsepower Weight Acceleration Model Year USA Europe Japan
393 27.0 4 140.0 86.0 2790.0 15.6 82 1.0 0.0 0.0
394 44.0 4 97.0 52.0 2130.0 24.6 82 0.0 1.0 0.0
395 32.0 4 135.0 84.0 2295.0 11.6 82 1.0 0.0 0.0
396 28.0 4 120.0 79.0 2625.0 18.6 82 1.0 0.0 0.0
397 31.0 4 119.0 82.0 2720.0 19.4 82 1.0 0.0 0.0

 

データを訓練とテストに分割する

さてデータセットを訓練セットとテストセットに分割します。

モデルの最後の評価でテストセットを使用します。

train_dataset = dataset.sample(frac=0.8,random_state=0)
test_dataset = dataset.drop(train_dataset.index)

 

データを調査する

訓練セットからカラムの 2,3 のペアの同時分布を簡単に見てみます。

sns.pairplot(train_dataset[["MPG", "Cylinders", "Displacement", "Weight"]], diag_kind="kde")
<seaborn.axisgrid.PairGrid at 0x7fa0c95859e8>

全体的な統計情報も見てみます :

train_stats = train_dataset.describe()
train_stats.pop("MPG")
train_stats = train_stats.transpose()
train_stats

count mean std min 25% 50% 75% max
Cylinders 314.0 5.477707 1.699788 3.0 4.00 4.0 8.00 8.0
Displacement 314.0 195.318471 104.331589 68.0 105.50 151.0 265.75 455.0
Horsepower 314.0 104.869427 38.096214 46.0 76.25 94.5 128.00 225.0
Weight 314.0 2990.251592 843.898596 1649.0 2256.50 2822.5 3608.00 5140.0
Acceleration 314.0 15.559236 2.789230 8.0 13.80 15.5 17.20 24.8
Model Year 314.0 75.898089 3.675642 70.0 73.00 76.0 79.00 82.0
USA 314.0 0.624204 0.485101 0.0 0.00 1.0 1.00 1.0
Europe 314.0 0.178344 0.383413 0.0 0.00 0.0 0.00 1.0
Japan 314.0 0.197452 0.398712 0.0 0.00 0.0 0.00 1.0

 

ラベルから特徴を分ける

特徴からターゲット値、あるいは「ラベル」を分離します。このラベルがモデルを訓練して予測する値です。

train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')

 

データを正規化する

上の train_stats ブロックを再度見て各特徴の範囲がどのように異なっているかに注意してください。

異なるスケールと範囲を使用する特徴を正規化することは良い実践です。特徴正規化なしでもモデルは収束するかもしれませんが、それは訓練をより困難にし、そしてそれは結果としてのモデルを入力で使用される単位の選択に依拠させます。

Note: これらの統計情報を訓練データセットだけから意図的に生成しますが、こららの統計情報はまたテストデータセットを正規化するためにも使用されます。テストデータセットを (モデルがその上で訓練されたのと) 同じ分布に射影するためにそれを行なう必要があります。

def norm(x):
  return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)
normed_test_data = norm(test_dataset)

この正規化されたデータはモデルを訓練するために使用するものです。

Caution: ここで入力を正規化するために使用された統計情報 (平均と標準偏差) は、先に行なった one-hot エンコーディングと一緒に、モデルに供給されるどのような他のデータにも適用される必要があります。それはテストセットそしてプロダクションでモデルが使用されるときのライブデータを含みます。

 

モデル

モデルを構築する

私達のモデルを構築しましょう。ここで、2 つの密に結合した隠れ層、そして単一の連続値を返す出力層を持つ Sequential モデルを使用します。モデル構築ステップは関数, build_model にラップされます、何故ならば後で 2 番目のモデルを作成するからです。

def build_model():
  model = keras.Sequential([
    layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),
    layers.Dense(64, activation='relu'),
    layers.Dense(1)
  ])

  optimizer = tf.keras.optimizers.RMSprop(0.001)

  model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])
  return model
model = build_model()

 

モデルを調査する

モデルの単純な記述をプリントするために .summary メソッドを使用します。

model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 64)                640       
_________________________________________________________________
dense_1 (Dense)              (None, 64)                4160      
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 65        
=================================================================
Total params: 4,865
Trainable params: 4,865
Non-trainable params: 0
_________________________________________________________________

さてモデルを試してみましょう。訓練データから 10 サンプルのバッチを取ってその上で model.predict を呼び出します。

example_batch = normed_train_data[:10]
example_result = model.predict(example_batch)
example_result
array([[ 0.01432403],
       [ 0.05611863],
       [-0.7658546 ],
       [-0.03145953],
       [-0.14918138],
       [-0.17592657],
       [-0.13245817],
       [-0.17190717],
       [-0.11158038],
       [ 0.18116453]], dtype=float32)

それは動作しているようです、そしてそれは期待される shape と type の結果を生成します。

 

モデルを訓練する

モデルを 1000 エポックの間訓練して訓練と検証精度を 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 = 1000

history = model.fit(
  normed_train_data, train_labels,
  epochs=EPOCHS, validation_split = 0.2, verbose=0,
  callbacks=[PrintDot()])
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................
....................................................................................................

history オブジェクトにストアされている統計情報を使用してモデルの訓練進捗を可視化します。

hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
hist.tail()

loss mae mse val_loss val_mae val_mse epoch
995 3.169360 1.137359 3.169360 8.839724 2.252794 8.839724 995
996 3.343072 1.140639 3.343073 8.830334 2.231025 8.830334 996
997 3.105232 1.128542 3.105232 9.016378 2.240795 9.016376 997
998 3.309495 1.193391 3.309495 8.855472 2.234031 8.855473 998
999 3.440103 1.183400 3.440103 8.744971 2.213535 8.744972 999

def plot_history(history):
  hist = pd.DataFrame(history.history)
  hist['epoch'] = history.epoch

  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Abs Error [MPG]')
  plt.plot(hist['epoch'], hist['mae'],
           label='Train Error')
  plt.plot(hist['epoch'], hist['val_mae'],
           label = 'Val Error')
  plt.ylim([0,5])
  plt.legend()

  plt.figure()
  plt.xlabel('Epoch')
  plt.ylabel('Mean Square Error [$MPG^2$]')
  plt.plot(hist['epoch'], hist['mse'],
           label='Train Error')
  plt.plot(hist['epoch'], hist['val_mse'],
           label = 'Val Error')
  plt.ylim([0,20])
  plt.legend()
  plt.show()


plot_history(history)

このグラフはおよそ 100 エポック後には検証エラーについて殆ど改良しない、あるいは劣化さえ示します。検証スコアが改善しないとき訓練を自動的に停止するように model.fit 呼び出しを更新しましょう。EarlyStopping コールバックを使用します、これは総てのエポックのために訓練条件をテストします。エポックの設定された総数が改善を示すことなく経過する場合、訓練を自動的に停止します。

このコールバックについて ここで 更に学習できます。

model = build_model()

# The patience parameter is the amount of epochs to check for improvement
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)

history = model.fit(normed_train_data, train_labels, epochs=EPOCHS,
                    validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])

plot_history(history)

................................................

グラフは検証セット上、平均エラーが通常は +/- 2 MPG まわりであることを示しています。これは良いでしょうか?その決定は貴方に委ねましょう。

モデルを訓練するときに使用しなかった、テスト セットを使用してモデルがどの程度上手く一般化されたかを見てみましょう。これは、現実世界でモデルを使用するときどの程度上手く予測することをモデルに期待できるかを私達に教えてくれます。

loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=0)

print("Testing set Mean Abs Error: {:5.2f} MPG".format(mae))
Testing set Mean Abs Error:  1.83 MPG

 

予測を行なう

最後に、テストセットのデータを使用してMPG 値を予測します :

test_predictions = model.predict(normed_test_data).flatten()

plt.scatter(test_labels, test_predictions)
plt.xlabel('True Values [MPG]')
plt.ylabel('Predictions [MPG]')
plt.axis('equal')
plt.axis('square')
plt.xlim([0,plt.xlim()[1]])
plt.ylim([0,plt.ylim()[1]])
_ = plt.plot([-100, 100], [-100, 100])

私達のモデルは適度に上手く予想しているようです。エラー分布を見てみましょう。

error = test_predictions - test_labels
plt.hist(error, bins = 25)
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")

それは完全にはガウシアン (分布) ではありませんが、それを期待できます、何故ならばサンプルの数が非常に小さいからです。

 

最後に

この notebook は回帰問題を扱う幾つかのテクニックを紹介しました。

  • Mean Squared Error (MSE) は回帰問題のために使用される一般的な損失関数です (異なる損失関数が分類問題に使われます)。
  • 同様に、回帰に使用される評価メトリクスは分類とは異なります。一般的な回帰メトリクスは Mean Absolute Error (MAE) です。
  • 数値入力データ特徴が異なる範囲の値を持つとき、各特徴は独立的に同じ範囲にスケールされるべきです。
  • それほど多くの訓練データがない場合、overfitting を回避するために一つのテクニックは少ない隠れ層を持つ小さいネットワークを選択することです。
  • Early stopping は overfitting を回避するための有用なテクニックです。
 

以上



AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com