TensorFlow 2.0 : Beginner Tutorials : Estimator :- Estimator で線形モデルを構築する (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/10/2019
* 本ページは、TensorFlow org サイトの TF 2.0 – Beginner Tutorials – Estimator の以下のページを
翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ |
Facebook: https://www.facebook.com/ClassCatJP/ |
Estimator :- Estimator で線形モデルを構築する
概要
この end-to-end ウォークスルーは tf.estimator API を使用してロジスティック回帰モデルを訓練します。このモデルはしばしば他の、より複雑な、アルゴリズムのためのベースラインとして使用されます。
セットアップ
!pip install -q sklearn
from __future__ import absolute_import, division, print_function, unicode_literals import os import sys import numpy as np import pandas as pd import matplotlib.pyplot as plt from IPython.display import clear_output from six.moves import urllib
タイタニック・データセットをロードする
タイタニック・データセットを、性別、年齢、クラス, etc. のような特性が与えられたときに乗客の生存を予測するという (寧ろ憂鬱な) 目標で使用します。
import tensorflow.compat.v2.feature_column as fc import tensorflow as tf
# Load dataset. dftrain = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/train.csv') dfeval = pd.read_csv('https://storage.googleapis.com/tf-datasets/titanic/eval.csv') y_train = dftrain.pop('survived') y_eval = dfeval.pop('survived')
データを調べる
データセットは次の特徴を含みます。
dftrain.head()
sex | age | n_siblings_spouses | parch | fare | class | deck | embark_town | alone | |
0 | male | 22.0 | 1 | 0 | 7.2500 | Third | unknown | Southampton | n |
1 | female | 38.0 | 1 | 0 | 71.2833 | First | C | Cherbourg | n |
2 | female | 26.0 | 0 | 0 | 7.9250 | Third | unknown | Southampton | y |
3 | female | 35.0 | 1 | 0 | 53.1000 | First | C | Southampton | n |
4 | male | 28.0 | 0 | 0 | 8.4583 | Third | unknown | Queenstown | y |
dftrain.describe()
age | n_siblings_spouses | parch | fare | |
count | 627.000000 | 627.000000 | 627.000000 | 627.000000 |
mean | 29.631308 | 0.545455 | 0.379585 | 34.385399 |
std | 12.511818 | 1.151090 | 0.792999 | 54.597730 |
min | 0.750000 | 0.000000 | 0.000000 | 0.000000 |
25% | 23.000000 | 0.000000 | 0.000000 | 7.895800 |
50% | 28.000000 | 0.000000 | 0.000000 | 15.045800 |
75% | 35.000000 | 1.000000 | 0.000000 | 31.387500 |
max | 80.000000 | 8.000000 | 5.000000 | 512.329200 |
訓練と評価セットにはそれぞれ 627 と 264 サンプルがあります。
dftrain.shape[0], dfeval.shape[0]
(627, 264)
乗客の大多数は 20 代と 30 代です。
dftrain.age.hist(bins=20)
<matplotlib.axes._subplots.AxesSubplot at 0x7f5f32f298d0>
乗船した男性の乗客は女性の乗客のおよそ 2 倍いました。
dftrain.sex.value_counts().plot(kind='barh')
<matplotlib.axes._subplots.AxesSubplot at 0x7f5f30df7470>
乗客の多数は “third” クラスでした。
dftrain['class'].value_counts().plot(kind='barh')
<matplotlib.axes._subplots.AxesSubplot at 0x7f5f30dc9cc0>
女性は男性に比較して遥かに高い生存のチャンスを持ちます。これは明らかにモデルのための予測的な特徴となるでしょう。
pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')
Text(0.5, 0, '% survive')
モデルのための特徴量エンジニアリング
Estimator はモデルが生入力特徴の各々をどのように解釈するべきかを記述する 特徴カラム と呼ばれるシステムを使用します。Estimator は数値入力のベクトルを想定し、特徴カラムはモデルが各特徴をどのように変換するべきかを記述します。
特徴カラムの正しいセットを選択して巧妙に作成することは効果的なモデルを学習するための鍵です。特徴カラムは元の特徴辞書の生入力の一つであるか (ベース特徴カラム)、一つまたは複数のベースカラムに渡り定義された変換を使用して作成された任意の新しいカラム (派生特徴カラム) であることが可能です。
線形 estimator は numereic と categorical 特徴の両者を使用します。特徴カラムは総ての TensorFlow estimator と共に動作してそしてそれらの目的はモデリングのために使用される特徴を定義することです。更に、それらは one-hot-エンコーディング, 正規化と bucketization のような幾つかの特徴量エンジニアリング機能を提供します。
ベース特徴カラム
CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck', 'embark_town', 'alone'] NUMERIC_COLUMNS = ['age', 'fare'] feature_columns = [] for feature_name in CATEGORICAL_COLUMNS: vocabulary = dftrain[feature_name].unique() feature_columns.append(tf.feature_column.categorical_column_with_vocabulary_list(feature_name, vocabulary)) for feature_name in NUMERIC_COLUMNS: feature_columns.append(tf.feature_column.numeric_column(feature_name, dtype=tf.float32))
input_function はデータがどのように (ストリーミング流儀で入力パイプラインに供給する) tf.data.Dataset に変換されるかを指定します。tf.data.Dataset は dataframe, csv-形式ファイル等のような複数のソースを取ります。
def make_input_fn(data_df, label_df, num_epochs=10, shuffle=True, batch_size=32): def input_function(): ds = tf.data.Dataset.from_tensor_slices((dict(data_df), label_df)) if shuffle: ds = ds.shuffle(1000) ds = ds.batch(batch_size).repeat(num_epochs) return ds return input_function train_input_fn = make_input_fn(dftrain, y_train) eval_input_fn = make_input_fn(dfeval, y_eval, num_epochs=1, shuffle=False)
データセットを調べることができます :
ds = make_input_fn(dftrain, y_train, batch_size=10)() for feature_batch, label_batch in ds.take(1): print('Some feature keys:', list(feature_batch.keys())) print() print('A batch of class:', feature_batch['class'].numpy()) print() print('A batch of Labels:', label_batch.numpy())
Some feature keys: ['embark_town', 'sex', 'n_siblings_spouses', 'parch', 'fare', 'class', 'age', 'deck', 'alone'] A batch of class: [b'Second' b'Third' b'Third' b'Third' b'Second' b'Third' b'Third' b'Second' b'Second' b'Second'] A batch of Labels: [0 1 0 0 0 0 0 1 0 0]
tf.keras.layers.DenseFeatures 層を使用して特定の特徴カラムの結果を調べることもできます :
age_column = feature_columns[7] tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()
WARNING:tensorflow:Layer dense_features is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2. The layer has dtype float32 because it's dtype defaults to floatx. If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2. To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor. array([[21.], [18.], [28.], [33.], [36.], [38.], [ 1.], [ 7.], [39.], [16.]], dtype=float32)
DenseFeatures は密 tensor だけを受け取ります、categorical column を調べるためにはそれを indicator column に最初に変換する必要があります :
gender_column = feature_columns[0] tf.keras.layers.DenseFeatures([tf.feature_column.indicator_column(gender_column)])(feature_batch).numpy()
WARNING:tensorflow:Layer dense_features_1 is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2. The layer has dtype float32 because it's dtype defaults to floatx. If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2. To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor. WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/feature_column/feature_column_v2.py:4276: IndicatorColumn._variable_shape (from tensorflow.python.feature_column.feature_column_v2) is deprecated and will be removed in a future version. Instructions for updating: The old _FeatureColumn APIs are being deprecated. Please use the new FeatureColumn APIs instead. WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/feature_column/feature_column_v2.py:4331: VocabularyListCategoricalColumn._num_buckets (from tensorflow.python.feature_column.feature_column_v2) is deprecated and will be removed in a future version. Instructions for updating: The old _FeatureColumn APIs are being deprecated. Please use the new FeatureColumn APIs instead. array([[1., 0.], [0., 1.], [1., 0.], [1., 0.], [1., 0.], [1., 0.], [1., 0.], [0., 1.], [1., 0.], [1., 0.]], dtype=float32)
総てのベース特徴をモデルに追加した後、モデルを訓練しましょう。モデルの訓練は tf.estimator API を使用して単一のコマンドだけです :
linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns) linear_est.train(train_input_fn) result = linear_est.evaluate(eval_input_fn) clear_output() print(result)
{'global_step': 200, 'auc': 0.83379245, 'recall': 0.6363636, 'loss': 0.47335136, 'prediction/mean': 0.35310316, 'auc_precision_recall': 0.7720765, 'accuracy': 0.7462121, 'accuracy_baseline': 0.625, 'average_loss': 0.48316467, 'label/mean': 0.375, 'precision': 0.67021275}
派生特徴カラム
今では 75% の精度に達しました。各ベース特徴カラムの単独の使用はデータを説明するために十分ではないかもしれません。例えば、性別とラベルの間の相関性は異なる性別に対して異なるかもしれません。それゆえに、gender=”Male” と gender=”Female” のために単一のモデル重みを学習するだけであれば、総ての age-gender 組み合わせを補足しないでしょう (e.g. gender=”Male” AND age=”30″ AND gender=”Male” AND age=”40″ の間を識別する)。
異なる特徴の組み合わせ間の違いを学習するために、交差 (= crossed) 特徴カラムをモデルに追加することができます (cross column の前に age column を分類する (= bucketize) こともできます) :
age_x_gender = tf.feature_column.crossed_column(['age', 'sex'], hash_bucket_size=100)
モデルに combination feature を追加した後、モデルを再度訓練しましょう :
derived_feature_columns = [age_x_gender] linear_est = tf.estimator.LinearClassifier(feature_columns=feature_columns+derived_feature_columns) linear_est.train(train_input_fn) result = linear_est.evaluate(eval_input_fn) clear_output() print(result)
{'global_step': 200, 'auc': 0.8449648, 'recall': 0.64646465, 'loss': 0.4592837, 'prediction/mean': 0.36509418, 'auc_precision_recall': 0.7893224, 'accuracy': 0.7689394, 'accuracy_baseline': 0.625, 'average_loss': 0.46941984, 'label/mean': 0.375, 'precision': 0.7111111}
それは今では 77.6% の精度を獲得しました、これはベース特徴でのみ訓練されたものよりも僅かに良いです。更に上手くやれるかを見るためにより多くの特徴と変換を使用してみることができます!
今では評価セットからの乗客上で予測を行なうために訓練モデルを使用できます。TensorFlow モデルはサンプルのバッチ、あるいはコレクション上で一度に予測を行なうために最適化されています。先に、評価セット全体を使用して eval_input_fn が定義されました。
pred_dicts = list(linear_est.predict(eval_input_fn)) probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts]) probs.plot(kind='hist', bins=20, title='predicted probabilities')
INFO:tensorflow:Calling model_fn. WARNING:tensorflow:Layer linear/linear_model is casting an input tensor from dtype float64 to the layer's dtype of float32, which is new behavior in TensorFlow 2. The layer has dtype float32 because it's dtype defaults to floatx. If you intended to run this layer in float32, you can safely ignore this warning. If in doubt, this warning is likely only an issue if you are porting a TensorFlow 1.X model to TensorFlow 2. To change all layers to have dtype float64 by default, call `tf.keras.backend.set_floatx('float64')`. To change just this layer, pass dtype='float64' to the layer constructor. If you are the author of this layer, you can disable autocasting by passing autocast=False to the base Layer constructor. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from /tmp/tmp0mpvnhyc/model.ckpt-200 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. <matplotlib.axes._subplots.AxesSubplot at 0x7f5edc4dce10>
最期に、結果の ROC (receiver operating characteristic) を見ます、これは真陽性と偽陽性率の間のトレードオフのより良い考えを与えてくれます。
from sklearn.metrics import roc_curve from matplotlib import pyplot as plt fpr, tpr, _ = roc_curve(y_eval, probs) plt.plot(fpr, tpr) plt.title('ROC curve') plt.xlabel('false positive rate') plt.ylabel('true positive rate') plt.xlim(0,) plt.ylim(0,)
(0, 1.05)
以上