TensorFlow 2.0 Alpha : Beginner Tutorials : Estimator :- Estimator で線形モデルを構築する (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/05/2019
* 本ページは、TensorFlow の本家サイトの TF 2.0 Alpha – Beginner Tutorials – Estimators の以下のページを翻訳した上で
適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
Estimator :- Estimator で線形モデルを構築する
概要
この end-to-end ウォークスルーは tf.estimator API を使用してロジスティック回帰モデルを訓練します。このモデルはしばしば他の、より複雑な、アルゴリズムのためのベースラインとして使用されます。
セットアップ
!pip install -q sklearn
from __future__ import absolute_import, division, print_function 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. のような特質が与えられたときに乗客の生存を予測するという (寧ろ憂鬱な) 目標で使用します。
!pip install -q tensorflow==2.0.0-alpha0 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);
乗船した男性の乗客は女性の乗客のおよそ 2 倍いました。
dftrain.sex.value_counts().plot(kind='barh');
乗客の多数は “third” クラスでした。
dftrain['class'].value_counts().plot(kind='barh');
女性は男性に比較して遥かに高い生存のチャンスを持ちます。これは明らかにモデルのための予測的な特徴となるでしょう。
pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive');
モデルのための特徴量エンジニアリング
Estimator はモデルが生入力特徴の各々をどのように解釈するべきかを記述する feature columns と呼ばれるシステムを使用します。Estimator は数値入力のベクトルを想定し、feature columns はモデルが特徴の各々をどのように変換するべきかを記述します。
feature columns の正しいセットを選択して巧妙に作成することは効果的なモデルを学習するためのキーです。feature column は元の特徴辞書の生入力の一つであるか (ベース feature column)、一つまたは複数のベースカラムに渡り定義された transformation を使用して作成された任意の新しいカラム (派生 feature column) であり得ます。
線形 estimator は numereic と categorical feature の両者を使用します。feature columns は総ての TensorFlow estimator と動作してそしてそれらの目的はモデリングのために使用される特徴を定義することです。更に、それらは one-hot-エンコーディング, 正規化と bucketization のような幾つかの特徴量エンジニアリング機能を提供します。
ベース Feature Columns
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', 'class', 'parch', 'n_siblings_spouses', 'deck', 'sex', 'age', 'fare', 'alone'] A batch of class: [b'Third' b'Third' b'Third' b'Third' b'Third' b'Third' b'First' b'Third' b'Third' b'Third'] A batch of Labels: [0 1 0 0 0 0 0 1 0 0]
tf.keras.layers.DenseFeatures 層を使用して特定の feature column の結果を調べることもできます :
age_column = feature_columns[7] tf.keras.layers.DenseFeatures([age_column])(feature_batch).numpy()
WARNING: Logging before flag parsing goes to stderr. W0307 18:19:20.561428 140073716143872 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column_v2.py:2758: to_float (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.cast` instead. array([[28. ], [32. ], [23. ], [28. ], [29. ], [55.5], [40. ], [ 5. ], [34. ], [34. ]], 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()
W0307 18:19:20.583961 140073716143872 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/ops/lookup_ops.py:1347: to_int64 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.cast` instead. W0307 18:19:20.585764 140073716143872 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column_v2.py:4307: 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. W0307 18:19:20.586556 140073716143872 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column_v2.py:4362: 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.], [1., 0.], [0., 1.], [1., 0.], [1., 0.], [1., 0.], [1., 0.], [0., 1.], [1., 0.], [1., 0.]], dtype=float32)
総てのベース feature をモデルに追加した後、モデルを訓練しましょう。モデルの訓練は 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)
{'label/mean': 0.375, 'loss': 0.52442783, 'auc': 0.82681364, 'global_step': 200, 'recall': 0.7878788, 'auc_precision_recall': 0.7858568, 'accuracy': 0.7537879, 'average_loss': 0.5273171, 'prediction/mean': 0.4911321, 'precision': 0.6393443, 'accuracy_baseline': 0.625}
派生 Featuer Columns
今では 75% の精度に達しました。各ベース feature column の単独の使用はデータを説明するために十分ではないかもしれません。例えば、性別とラベルの間の相関性は異なる性別に対して異なるかもしれません。それゆえに、gender=”Male” と gender=”Female” のために単一のモデル重みを学習だけれあれば、総ての age-gender 組み合わせを補足しないでしょう (e.g. gender=”Male” AND age=”30″ AND gender=”Male” AND age=”40″ 間を識別する)。
異なる特徴の組み合わせ間の違いを学習するために、crossed feature columns をモデルに追加することができます (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)
{'label/mean': 0.375, 'loss': 0.46076283, 'auc': 0.84664834, 'global_step': 200, 'recall': 0.64646465, 'auc_precision_recall': 0.79672474, 'accuracy': 0.7537879, 'average_loss': 0.4691896, 'prediction/mean': 0.40174615, 'precision': 0.68085104, 'accuracy_baseline': 0.625}
それは今では 77.6% の精度を獲得しました、これはベース feature でのみ訓練されたものよりも僅かに良いです。更に上手くやれるかを見るためにより多くの features と transformations を使用してみることができます!
今では評価セットからの乗客上で予測を行なうために訓練モデルを使用できます。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')
<matplotlib.axes._subplots.AxesSubplot at 0x7f64c44c5d30>
最期に、結果の 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)
以上