ホーム » Estimator

Estimator」カテゴリーアーカイブ

TensorFlow 2.0 : Tutorials : Estimator :- Keras モデルから Estimator を作成する

TensorFlow 2.0 : Beginner Tutorials : Estimator :- Keras モデルから Estimator を作成する (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/11/2019
* 本ページは、TensorFlow org サイトの TF 2.0 – Beginner Tutorials – Estimator の以下のページを
翻訳した上で適宜、補足説明したものです:

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

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

Estimator :- Keras モデルから Estimator を作成する

概要

TensorFlow Estimator は TensorFlow で完全にサポートされます、そして新しいそして既存の tf.keras モデルから作成できます。このチュートリアルはそのプロセスの完全で、最小限のサンプルを含みます。

 

セットアップ

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf

import numpy as np
import tensorflow_datasets as tfds

 

単純な Keras モデルを作成する

Keras では、モデルを構築するために層をアセンブルします。モデルは (通常は) 層のグラフです。モデルの最も一般的なタイプは層のスタック : tf.keras.Sequential モデルです。

単純な、完全結合ネットワーク (i.e. 多層パーセプトロン) を構築するには :

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(16, activation='relu', input_shape=(4,)),
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

モデルをコンパイルして要約を得ます。

model.compile(loss='categorical_crossentropy', optimizer='adam')
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 16)                80        
_________________________________________________________________
dropout (Dropout)            (None, 16)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 17        
=================================================================
Total params: 97
Trainable params: 97
Non-trainable params: 0
_________________________________________________________________

 

入力関数を作成する

巨大なデータセットやマルチデバイス訓練にスケールするために Datasets API を使用します。

Estimator はそれらの入力パイプラインがいつそしてどのように構築されるかの制御を必要とします。これを可能にするために、それらは「入力関数」あるいは input_fn を必要とします。Estimator はこの関数を引数なしで呼び出します。input_fn は tf.data.Dataset を返さなければなりません。

def input_fn():
  split = tfds.Split.TRAIN
  dataset = tfds.load('iris', split=split, as_supervised=True)
  dataset = dataset.map(lambda features, labels: ({'dense_input':features}, labels))
  dataset = dataset.batch(32).repeat()
  return dataset

貴方の input_fn を試します。

for features_batch, labels_batch in input_fn().take(1):
  print(features_batch)
  print(labels_batch)
Downloading and preparing dataset iris (4.44 KiB) to /home/kbuilder/tensorflow_datasets/iris/1.0.0...

HBox(children=(IntProgress(value=1, bar_style='info', description='Dl Completed...', max=1, style=ProgressStyl…
HBox(children=(IntProgress(value=1, bar_style='info', description='Dl Size...', max=1, style=ProgressStyle(des…





/home/kbuilder/.local/lib/python3.5/site-packages/urllib3/connectionpool.py:1004: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning,

HBox(children=(IntProgress(value=1, bar_style='info', max=1), HTML(value='')))


HBox(children=(IntProgress(value=0, description='Shuffling...', max=1, style=ProgressStyle(description_width='…
WARNING:tensorflow:From /home/kbuilder/.local/lib/python3.5/site-packages/tensorflow_datasets/core/file_format_adapter.py:209: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`

WARNING:tensorflow:From /home/kbuilder/.local/lib/python3.5/site-packages/tensorflow_datasets/core/file_format_adapter.py:209: tf_record_iterator (from tensorflow.python.lib.io.tf_record) is deprecated and will be removed in a future version.
Instructions for updating:
Use eager execution and: 
`tf.data.TFRecordDataset(path)`

HBox(children=(IntProgress(value=1, bar_style='info', description='Reading...', max=1, style=ProgressStyle(des…
HBox(children=(IntProgress(value=0, description='Writing...', max=150, style=ProgressStyle(description_width='…
Dataset iris downloaded and prepared to /home/kbuilder/tensorflow_datasets/iris/1.0.0. Subsequent calls will reuse this data.
{'dense_input': }
tf.Tensor([1 0 2 1 1 0 1 2 1 1 2 0 0 0 0 1 2 1 1 2 0 2 0 2 2 2 2 2 0 0 0 0], shape=(32,), dtype=int64)

 

tf.keras モデルから Estimator を作成する

tf.keras.Model は tf.keras.estimator.model_to_estimator でモデルを tf.estimator.Estimator オブジェクトに変換することにより tf.estimator API で訓練できます。

model_dir = "/tmp/tfkeras_example/"
keras_estimator = tf.keras.estimator.model_to_estimator(
    keras_model=model, model_dir=model_dir)
INFO:tensorflow:Using default config.

INFO:tensorflow:Using default config.

INFO:tensorflow:Using the Keras model provided.

INFO:tensorflow:Using the Keras model provided.

WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.

INFO:tensorflow:Using config: {'_num_ps_replicas': 0, '_session_creation_timeout_secs': 7200, '_global_id_in_cluster': 0, '_save_checkpoints_secs': 600, '_save_checkpoints_steps': None, '_protocol': None, '_log_step_count_steps': 100, '_num_worker_replicas': 1, '_master': '', '_task_id': 0, '_train_distribute': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_is_chief': True, '_experimental_max_worker_delay_secs': None, '_experimental_distribute': None, '_service': None, '_task_type': 'worker', '_eval_distribute': None, '_tf_random_seed': None, '_evaluation_master': '', '_cluster_spec': , '_device_fn': None, '_save_summary_steps': 100, '_model_dir': '/tmp/tfkeras_example/', '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
}

estimator を訓練して評価します。

keras_estimator.train(input_fn=input_fn, steps=25)
eval_result = keras_estimator.evaluate(input_fn=input_fn, steps=10)
print('Eval result: {}'.format(eval_result))
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.

WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Warm-starting with WarmStartSettings: WarmStartSettings(ckpt_to_initialize_from='/tmp/tfkeras_example/keras/keras_model.ckpt', vars_to_warm_start='.*', var_name_to_vocab_info={}, var_name_to_prev_var_name={})

INFO:tensorflow:Warm-starting with WarmStartSettings: WarmStartSettings(ckpt_to_initialize_from='/tmp/tfkeras_example/keras/keras_model.ckpt', vars_to_warm_start='.*', var_name_to_vocab_info={}, var_name_to_prev_var_name={})

INFO:tensorflow:Warm-starting from: /tmp/tfkeras_example/keras/keras_model.ckpt

INFO:tensorflow:Warm-starting from: /tmp/tfkeras_example/keras/keras_model.ckpt

INFO:tensorflow:Warm-starting variables only in TRAINABLE_VARIABLES.

INFO:tensorflow:Warm-starting variables only in TRAINABLE_VARIABLES.

INFO:tensorflow:Warm-started 4 variables.

INFO:tensorflow:Warm-started 4 variables.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tfkeras_example/model.ckpt.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tfkeras_example/model.ckpt.

INFO:tensorflow:loss = 118.05543, step = 0

INFO:tensorflow:loss = 118.05543, step = 0

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tfkeras_example/model.ckpt.

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tfkeras_example/model.ckpt.

INFO:tensorflow:Loss for final step: 84.80701.

INFO:tensorflow:Loss for final step: 84.80701.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Starting evaluation at 2019-10-01T01:26:35Z

INFO:tensorflow:Starting evaluation at 2019-10-01T01:26:35Z

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Restoring parameters from /tmp/tfkeras_example/model.ckpt-25

INFO:tensorflow:Restoring parameters from /tmp/tfkeras_example/model.ckpt-25

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Evaluation [1/10]

INFO:tensorflow:Evaluation [1/10]

INFO:tensorflow:Evaluation [2/10]

INFO:tensorflow:Evaluation [2/10]

INFO:tensorflow:Evaluation [3/10]

INFO:tensorflow:Evaluation [3/10]

INFO:tensorflow:Evaluation [4/10]

INFO:tensorflow:Evaluation [4/10]

INFO:tensorflow:Evaluation [5/10]

INFO:tensorflow:Evaluation [5/10]

INFO:tensorflow:Evaluation [6/10]

INFO:tensorflow:Evaluation [6/10]

INFO:tensorflow:Evaluation [7/10]

INFO:tensorflow:Evaluation [7/10]

INFO:tensorflow:Evaluation [8/10]

INFO:tensorflow:Evaluation [8/10]

INFO:tensorflow:Evaluation [9/10]

INFO:tensorflow:Evaluation [9/10]

INFO:tensorflow:Evaluation [10/10]

INFO:tensorflow:Evaluation [10/10]

INFO:tensorflow:Finished evaluation at 2019-10-01-01:26:36

INFO:tensorflow:Finished evaluation at 2019-10-01-01:26:36

INFO:tensorflow:Saving dict for global step 25: global_step = 25, loss = 101.27602

INFO:tensorflow:Saving dict for global step 25: global_step = 25, loss = 101.27602

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tfkeras_example/model.ckpt-25

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tfkeras_example/model.ckpt-25

Eval result: {'global_step': 25, 'loss': 101.27602}
 

以上






TensorFlow 2.0 : Tutorials : Estimator :- 勾配ブースティング木: モデル理解

TensorFlow 2.0 : Beginner Tutorials : Estimator :- 勾配ブースティング木: モデル理解 (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 10/11/2019
* 本ページは、TensorFlow org サイトの TF 2.0 – Beginner Tutorials – Estimator の以下のページを
翻訳した上で適宜、補足説明したものです:

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

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

 

Estimator :- 勾配ブースティング木: モデル理解

勾配ブースティング・モデルを訓練する end-to-end ウォークスルーについては ブースティング木チュートリアル を調べてください。このチュートリアルで貴方は :

  • ブースティング木モデルをローカルとグルーバルの両者でどのように解釈するかを学習します。
  • ブースティング木モデルがデータセットにどのように fit するかについて直感を得ます。

 

ブースティング木モデルをローカルとグローバルの両者でどのように解釈するか

ローカル解釈可能性 (= interpretability) は個別のサンプルレベルでのモデルの予測の理解を参照し、その一方で、グルーバル解釈可能性は全体としてのモデルの理解を参照します。そのようなテクニックは機械学習 (ML) 実践者にモデル開発段階でバイアスとバグを検出する助けとなれます。

ローカル解釈可能性については、どのようにインスタンス毎の寄与を作成して可視化するかを学習します。これを特徴量重要度と区別するため、これらの値を DFC (directional feature contributions) として参照します。

グローバル解釈可能性については、gain-based 特徴量重要度、再配列 (= permutation) 特徴量重要度 を取得して可視化し、そしてまた総計 (= aggregated) DFC を示します。

 

タイタニック・データセットをロードします

タイタニック・データセットを使用していきます、そこでは (寧ろ憂鬱な) 目標は性別、年齢、クラス, etc. のような特質が与えられたときに乗客の生存を予測することです。

from __future__ import absolute_import, division, print_function, unicode_literals

import numpy as np
import pandas as pd
from IPython.display import clear_output

# 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')
import tensorflow as tf
tf.random.set_seed(123)

特徴の説明については、前のチュートリアルを見直してください。

 

特徴カラム、input_fn を作成して estimator を訓練する

データを前処理する

元の numeric column そのままと one-hot-エンコーディング categorical 変数を使用して特徴カラムを作成します。

fc = tf.feature_column
CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

def one_hot_cat_column(feature_name, vocab):
  return fc.indicator_column(
      fc.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(fc.numeric_column(feature_name,
                                           dtype=tf.float32))

 

入力パイプラインを構築する

Pandas から直接データを読み込むために tf.data API の from_tensor_slices メソッドを使用して入力関数を作成します。

# Use entire batch since this is such a small dataset.
NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((X.to_dict(orient='list'), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).
    dataset = (dataset
      .repeat(n_epochs)
      .batch(NUM_EXAMPLES))
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

 

モデルを訓練する

params = {
  'n_trees': 50,
  'max_depth': 3,
  'n_batches_per_layer': 1,
  # You must enable center_bias = True to get DFCs. This will force the model to
  # make an initial prediction before using any features (e.g. use the mean of
  # the training labels for regression or log odds for classification when
  # using cross entropy loss).
  'center_bias': True
}

est = tf.estimator.BoostedTreesClassifier(feature_columns, **params)
# Train model.
est.train(train_input_fn, max_steps=100)

# Evaluation.
results = est.evaluate(eval_input_fn)
clear_output()
pd.Series(results).to_frame()

accuracy 0.806818
accuracy_baseline 0.625000
auc 0.866606
auc_precision_recall 0.849128
average_loss 0.421549
global_step 100.000000
label/mean 0.375000
loss 0.421549
precision 0.755319
prediction/mean 0.384944
recall 0.717172

パフォーマンスの理由のため、貴方のデータがメモリに収まるときは、boosted_trees_classifier_train_in_memory 関数を使用することを勧めます。けれども訓練時間が関心事ではないか、あるいは非常に巨大なデータセットを持ち分散訓練を行なうことを望む場合には、上で示された tf.estimator.BoostedTrees API を使用してください。

このメソッドを使用するとき、入力データをバッチ化するべきではありません、何故ならばメソッドはデータセット全体上で作用するからです。

in_memory_params = dict(params)
in_memory_params['n_batches_per_layer'] = 1
# In-memory input_fn does not use batching.
def make_inmemory_train_input_fn(X, y):
  y = np.expand_dims(y, axis=1)
  def input_fn():
    return dict(X), y
  return input_fn
train_input_fn = make_inmemory_train_input_fn(dftrain, y_train)

# Train the model.
est = tf.estimator.BoostedTreesClassifier(
    feature_columns, 
    train_in_memory=True, 
    **in_memory_params)

est.train(train_input_fn)
print(est.evaluate(eval_input_fn))
{'accuracy_baseline': 0.625, 'loss': 0.41725963, 'auc': 0.86810529, 'label/mean': 0.375, 'average_loss': 0.41725963, 'accuracy': 0.80681819, 'global_step': 153, 'precision': 0.75531918, 'prediction/mean': 0.38610166, 'recall': 0.71717173, 'auc_precision_recall': 0.8542586}

 

モデル解釈とプロット

import matplotlib.pyplot as plt
import seaborn as sns
sns_colors = sns.color_palette('colorblind')

 

ローカル解釈可能性

次に個々の予測を説明するために Palczewska et alInterpreting Random Forests で Saabas により概説されたアプローチを使用して DFC (directional feature contributions) を出力します (このメソッドはまた treeinterpreter パッケージで Random Forests のための scikit-learn でも利用可能です)。DFC は次で生成されます :

pred_dicts = list(est.experimental_predict_with_explanations(pred_input_fn))

(Note: このメソッドは experimental として命名されていますがこれは experimental prefix を落とす前に API を変更するかもしれないためです。)

pred_dicts = list(est.experimental_predict_with_explanations(eval_input_fn))
# Create DFC Pandas dataframe.
labels = y_eval.values
probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])
df_dfc = pd.DataFrame([pred['dfc'] for pred in pred_dicts])
df_dfc.describe().T

count mean std min 25% 50% 75% max
age 264.0 -0.025285 0.085606 -0.172007 -0.075237 -0.075237 0.011908 0.466216
sex 264.0 0.008138 0.108147 -0.097388 -0.074132 -0.072698 0.138499 0.197285
class 264.0 0.017317 0.093436 -0.075741 -0.045486 -0.044461 0.035060 0.248212
deck 264.0 -0.016094 0.033232 -0.096513 -0.042359 -0.026754 0.005053 0.205399
fare 264.0 0.016471 0.089597 -0.330205 -0.031050 -0.011403 0.050212 0.229989
embark_town 264.0 -0.007320 0.027672 -0.053676 -0.015208 -0.014375 -0.003016 0.068483
n_siblings_spouses 264.0 0.003973 0.027914 -0.144680 0.003582 0.004825 0.006412 0.138123
parch 264.0 0.001342 0.007995 -0.062833 0.000405 0.000510 0.002834 0.048722
alone 264.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

DFC の素晴らしい特性は寄与の合計 + bias が与えられたサンプルの予測に等しいことです。

# Sum of DFCs + bias == probabality.
bias = pred_dicts[0]['bias']
dfc_prob = df_dfc.sum(axis=1) + bias
np.testing.assert_almost_equal(dfc_prob.values,
                               probs.values)

個々の乗客のための DFC をプロットします。寄与の方向性に基づいたカラー・コーディングによりプロットを素晴らしくしてそして図に特徴量値を追加しましょう。

# Boilerplate code for plotting :)
def _get_color(value):
    """To make positive DFCs plot green, negative DFCs plot red."""
    green, red = sns.color_palette()[2:4]
    if value >= 0: return green
    return red

def _add_feature_values(feature_values, ax):
    """Display feature's values on left of plot."""
    x_coord = ax.get_xlim()[0]
    OFFSET = 0.15
    for y_coord, (feat_name, feat_val) in enumerate(feature_values.items()):
        t = plt.text(x_coord, y_coord - OFFSET, '{}'.format(feat_val), size=12)
        t.set_bbox(dict(facecolor='white', alpha=0.5))
    from matplotlib.font_manager import FontProperties
    font = FontProperties()
    font.set_weight('bold')
    t = plt.text(x_coord, y_coord + 1 - OFFSET, 'feature\nvalue',
    fontproperties=font, size=12)

def plot_example(example):
  TOP_N = 8 # View top 8 features.
  sorted_ix = example.abs().sort_values()[-TOP_N:].index  # Sort by magnitude.
  example = example[sorted_ix]
  colors = example.map(_get_color).tolist()
  ax = example.to_frame().plot(kind='barh',
                          color=[colors],
                          legend=None,
                          alpha=0.75,
                          figsize=(10,6))
  ax.grid(False, axis='y')
  ax.set_yticklabels(ax.get_yticklabels(), size=14)

  # Add feature values.
  _add_feature_values(dfeval.iloc[ID][sorted_ix], ax)
  return ax
# Plot results.
ID = 182
example = df_dfc.iloc[ID]  # Choose ith example from evaluation set.
TOP_N = 8  # View top 8 features.
sorted_ix = example.abs().sort_values()[-TOP_N:].index
ax = plot_example(example)
ax.set_title('Feature contributions for example {}\n pred: {:1.2f}; label: {}'.format(ID, probs[ID], labels[ID]))
ax.set_xlabel('Contribution to predicted probability', size=14)
plt.show()

より大きな量の寄与がモデルの予測の上でより大きなインパクトを持ちます。ネガティブな寄与は与えられたサンプルに対する特徴量値がモデルの予測を減少させることを示し、その一方でポジティブな値は予測において増量に寄与します。

バイオリンプロットを使用して全体の分布と比較してサンプルの DFC をプロットすることもできます。

# Boilerplate plotting code.
def dist_violin_plot(df_dfc, ID):
  # Initialize plot.
  fig, ax = plt.subplots(1, 1, figsize=(10, 6))

  # Create example dataframe.
  TOP_N = 8  # View top 8 features.
  example = df_dfc.iloc[ID]
  ix = example.abs().sort_values()[-TOP_N:].index
  example = example[ix]
  example_df = example.to_frame(name='dfc')

  # Add contributions of entire distribution.
  parts=ax.violinplot([df_dfc[w] for w in ix],
                 vert=False,
                 showextrema=False,
                 widths=0.7,
                 positions=np.arange(len(ix)))
  face_color = sns_colors[0]
  alpha = 0.15
  for pc in parts['bodies']:
      pc.set_facecolor(face_color)
      pc.set_alpha(alpha)

  # Add feature values.
  _add_feature_values(dfeval.iloc[ID][sorted_ix], ax)

  # Add local contributions.
  ax.scatter(example,
              np.arange(example.shape[0]),
              color=sns.color_palette()[2],
              s=100,
              marker="s",
              label='contributions for example')

  # Legend
  # Proxy plot, to show violinplot dist on legend.
  ax.plot([0,0], [1,1], label='eval set contributions\ndistributions',
          color=face_color, alpha=alpha, linewidth=10)
  legend = ax.legend(loc='lower right', shadow=True, fontsize='x-large',
                     frameon=True)
  legend.get_frame().set_facecolor('white')

  # Format plot.
  ax.set_yticks(np.arange(example.shape[0]))
  ax.set_yticklabels(example.index)
  ax.grid(False, axis='y')
  ax.set_xlabel('Contribution to predicted probability', size=14)

このサンプルをプロットします。

dist_violin_plot(df_dfc, ID)
plt.title('Feature contributions for example {}\n pred: {:1.2f}; label: {}'.format(ID, probs[ID], labels[ID]))
plt.show()

最後に、LIMEshap のようなサードパーティのツールもまたモデルのための個々の予測を理解する助けになれます。

 

グローバル特徴量重要度

追加として、個々の予測の研究よりもモデルを全体として理解することを望むかもしれません。下で、以下を計算して使用します :

  1. est.experimental_feature_importances を使用して gain-based 特徴量重要度
  2. 再配列 (= permutation) 重要度
  3. est.experimental_predict_with_explanations を使用して総計 DFC

gain-based 特徴量重要度は特定の特徴上で分割するときの損失変化を測定します、一方で再配列重要度は各特徴を一つずつシャッフルしてモデル性能の変化をシャッフルされた特徴に帰することによって評価セット上のモデル性能を評価することにより計算されます。

一般に、再配列特徴量重要度が gain-based 特徴量重要度より好まれます、両者のメソッドは潜在的予測変数が測定のスケールやカテゴリー数が変化する状況で特徴が相関関係があるときには信頼できない可能性はありますが (ソース)。異なる特徴量重要度タイプについての掘り下げた概要と素晴らしい議論については この記事 を調べてください。

 

1. Gain-based 特徴量重要度

grain-based 特徴量重要度は est.experimental_feature_importances を使用して TensorFlow Boosted Trees estimator に組み込まれます。

importances = est.experimental_feature_importances(normalize=True)
df_imp = pd.Series(importances)

# Visualize importances.
N = 8
ax = (df_imp.iloc[0:N][::-1]
    .plot(kind='barh',
          color=sns_colors[0],
          title='Gain feature importances',
          figsize=(10, 6)))
ax.grid(False, axis='y')

 

2. DFC の絶対値を平均する

グローバルレベルのインパクトを理解するために DFC の絶対値を平均することもできます。

# Plot.
dfc_mean = df_dfc.abs().mean()
N = 8
sorted_ix = dfc_mean.abs().sort_values()[-N:].index  # Average and sort by absolute.
ax = dfc_mean[sorted_ix].plot(kind='barh',
                       color=sns_colors[1],
                       title='Mean |directional feature contributions|',
                       figsize=(10, 6))
ax.grid(False, axis='y')

特徴量が変化するとき DFC がどのように変化するかを見ることもできます。

FEATURE = 'fare'
feature = pd.Series(df_dfc[FEATURE].values, index=dfeval[FEATURE].values).sort_index()
ax = sns.regplot(feature.index.values, feature.values, lowess=True)
ax.set_ylabel('contribution')
ax.set_xlabel(FEATURE)
ax.set_xlim(0, 100)
plt.show()

 

3. 再配列特徴量重要度

def permutation_importances(est, X_eval, y_eval, metric, features):
    """Column by column, shuffle values and observe effect on eval set.

    source: http://explained.ai/rf-importance/index.html
    A similar approach can be done during training. See "Drop-column importance"
    in the above article."""
    baseline = metric(est, X_eval, y_eval)
    imp = []
    for col in features:
        save = X_eval[col].copy()
        X_eval[col] = np.random.permutation(X_eval[col])
        m = metric(est, X_eval, y_eval)
        X_eval[col] = save
        imp.append(baseline - m)
    return np.array(imp)

def accuracy_metric(est, X, y):
    """TensorFlow estimator accuracy."""
    eval_input_fn = make_input_fn(X,
                                  y=y,
                                  shuffle=False,
                                  n_epochs=1)
    return est.evaluate(input_fn=eval_input_fn)['accuracy']
features = CATEGORICAL_COLUMNS + NUMERIC_COLUMNS
importances = permutation_importances(est, dfeval, y_eval, accuracy_metric,
                                      features)
df_imp = pd.Series(importances, index=features)

sorted_ix = df_imp.abs().sort_values().index
ax = df_imp[sorted_ix][-5:].plot(kind='barh', color=sns_colors[2], figsize=(10, 6))
ax.grid(False, axis='y')
ax.set_title('Permutation feature importance')
plt.show()

 

モデル fitting を可視化する

最初に次の式を使用して訓練データをシミュレート/ 作成しましょう :

\[
z=x* e^{-x^2 – y^2}
\]

ここで (z) は貴方が予測しようとする従属変数でそして (x) と (y) は特徴です。

from numpy.random import uniform, seed
from matplotlib.mlab import griddata

# Create fake data
seed(0)
npts = 5000
x = uniform(-2, 2, npts)
y = uniform(-2, 2, npts)
z = x*np.exp(-x**2 - y**2)
# Prep data for training.
df = pd.DataFrame({'x': x, 'y': y, 'z': z})

xi = np.linspace(-2.0, 2.0, 200),
yi = np.linspace(-2.1, 2.1, 210),
xi,yi = np.meshgrid(xi, yi)

df_predict = pd.DataFrame({
    'x' : xi.flatten(),
    'y' : yi.flatten(),
})
predict_shape = xi.shape
def plot_contour(x, y, z, **kwargs):
  # Grid the data.
  plt.figure(figsize=(10, 8))
  # Contour the gridded data, plotting dots at the nonuniform data points.
  CS = plt.contour(x, y, z, 15, linewidths=0.5, colors='k')
  CS = plt.contourf(x, y, z, 15,
                    vmax=abs(zi).max(), vmin=-abs(zi).max(), cmap='RdBu_r')
  plt.colorbar()  # Draw colorbar.
  # Plot data points.
  plt.xlim(-2, 2)
  plt.ylim(-2, 2)

関数をビジュアル化できます。より赤い色がより大きな関数値に対応します。

zi = griddata(x, y, z, xi, yi, interp='linear')
plot_contour(xi, yi, zi)
plt.scatter(df.x, df.y, marker='.')
plt.title('Contour on training data')
plt.show()

fc = [tf.feature_column.numeric_column('x'),
      tf.feature_column.numeric_column('y')]
def predict(est):
  """Predictions from a given estimator."""
  predict_input_fn = lambda: tf.data.Dataset.from_tensors(dict(df_predict))
  preds = np.array([p['predictions'][0] for p in est.predict(predict_input_fn)])
  return preds.reshape(predict_shape)

最初に線形モデルをデータに fit させてみましょう。

train_input_fn = make_input_fn(df, df.z)
est = tf.estimator.LinearRegressor(fc)
est.train(train_input_fn, max_steps=500);
plot_contour(xi, yi, predict(est))

それは非常に良い fit ではありません。次に GBDT モデルをそれに fit させてみましょうそしてモデルがどのように関数に fit するか理解してみましょう。

n_trees = 22 #@param {type: "slider", min: 1, max: 80, step: 1}

est = tf.estimator.BoostedTreesRegressor(fc, n_batches_per_layer=1, n_trees=n_trees)
est.train(train_input_fn, max_steps=500)
clear_output()
plot_contour(xi, yi, predict(est))
plt.text(-1.8, 2.1, '# trees: {}'.format(n_trees), color='w', backgroundcolor='black', size=20)
plt.show()

木の数を増やすにつれて、モデルの予測は基礎となる関数をより良く近似します。

 

最後に

このチュートリアルでは DFC (directional feature contributions) と特徴量重要度テクニックを使用してブースティング木モデルをどのように解釈するかを学習しました。これらのテクニックは特徴量がモデルの予測にどのようにインパクトを与えるかの洞察を提供します。最後に、幾つかのモデルについて決定面を見ることによりブースティング木モデルが複雑な関数にどのように fit するかについての直感もまた得られました。

 

以上






TensorFlow 2.0 : Tutorials : Estimator :- Estimator を使用するブースティング木

TensorFlow 2.0 : Beginner Tutorials : Estimator :- Estimator を使用するブースティング木 (翻訳/解説)

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

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

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

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

Estimator :- Estimator を使用するブースティング木

このチュートリアルは tf.estimator API で決定木を使用する勾配ブースティング木モデルを訓練する end-to-end なウォークスルーです。ブースティング木モデルは回帰と分類の両者のための最も一般的で効果的な機械学習アプローチの一つです。それは幾つか (10s, 100s あるいは 1000s さえも考えます) の木モデルからの予測を連結するアンサンブル・テクニックです。

ブースト木モデルは多くの機械学習実践者により人気があります、何故ならばそれらは最小限のハイパーパラメータ調整で素晴らしいパフォーマンスを獲得できるからです。

 

タイタニック・データセットをロードする

タイタニック・データセットを使用していきます、そこでは (寧ろ憂鬱な) 目標は性別、年齢、クラス, etc. のような特性が与えられたときに乗客の生存を予測することです。

from __future__ import absolute_import, division, print_function, unicode_literals

import numpy as np
import pandas as pd
from IPython.display import clear_output
from matplotlib import pyplot as plt

# 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')
import tensorflow as tf
tf.random.set_seed(123)

データセットは訓練セットと評価セットから成ります :

  • dftrain と y_train は訓練セットです — モデルが学習するために使用するデータです。
  • モデルは評価セット, dfeval と y_eval に対してテストされます。

訓練のために次の特徴を使用します :

Feature Name Description
sex 乗客の性別
age 乗客の年齢
n_siblings_spouses # 乗船した兄弟とパートナー
parch # of 乗船した両親と子供
fare 乗客が支払った運賃
class 船の乗客のクラス
deck 乗客がどのデッキ上にいたか
embark_town 乗客がどの町から乗船したか
alone 乗客が一人であるか否か

 

データを調査する

最初にデータの幾つかをプレビューして訓練セット上の簡易統計 (= summary statistics) を作成します。

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)
plt.show()

乗船した男性の乗客は女性の乗客のおよそ 2 倍いました。

dftrain.sex.value_counts().plot(kind='barh')
plt.show()

乗客の多数は “third” クラスでした。

dftrain['class'].value_counts().plot(kind='barh')
plt.show()

殆どの乗客は Southampton から乗船しました。

dftrain['embark_town'].value_counts().plot(kind='barh')
plt.show()

女性は男性に比較して遥かに高い生存のチャンスを持ちます。これは明らかにモデルのための予測的な特徴となるでしょう。

pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive')
plt.show()

 

特徴カラムと入力関数を作成する

勾配ブースティング estimator は numeric と categorical 特徴の両者を利用できます。特徴カラムは総ての TensorFlow estimator とともに動作してそれらの目的はモデリングのために使用される特徴を定義することです。更にそれらは one-hot-エンコーディング、正規化そして bucketization のようなある特徴エンジニアリング機能を提供します。このチュートリアルでは、CATEGORICAL_COLUMNS のフィールドは categorical column から one-hot-エンコードされた column (indicator column) へ変形されます :

fc = tf.feature_column
CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck',
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']

def one_hot_cat_column(feature_name, vocab):
  return tf.feature_column.indicator_column(
      tf.feature_column.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))

for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name,
                                           dtype=tf.float32))

特徴カラムが生成する変換を見ることができます。例えば、ここに単一のサンプル上で indicator_column を使用するときの出力があります :

example = dict(dftrain.head(1))
class_fc = tf.feature_column.indicator_column(tf.feature_column.categorical_column_with_vocabulary_list('class', ('First', 'Second', 'Third')))
print('Feature value: "{}"'.format(example['class'].iloc[0]))
print('One-hot encoded: ', tf.keras.layers.DenseFeatures([class_fc])(example).numpy())
Feature value: "Third"
One-hot encoded:  [[ 0.  0.  1.]]

更に、総ての特徴カラム変換も一緒に見ることができます :

tf.keras.layers.DenseFeatures(feature_columns)(example).numpy()
array([[ 22.  ,   1.  ,   0.  ,   1.  ,   0.  ,   0.  ,   1.  ,   0.  ,
          0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   1.  ,   0.  ,
          0.  ,   0.  ,   7.25,   1.  ,   0.  ,   0.  ,   0.  ,   0.  ,
          0.  ,   0.  ,   1.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ,
          1.  ,   0.  ]], dtype=float32)

次に入力関数を作成する必要があります。これらは訓練と推論の両者に対してデータがどのようにモデルに読まれるかを指定します。Pandas から直接データを読み込むために tf.data API の from_tensor_slices メソッドを使用します。これはより小さい、in-メモリなデータセットに対して適しています。より巨大なデータセットについては、メモリに収まらないデータセットを処理できるように tf.data API は (csv を含む) 様々な種類のファイルフォーマットをサポートします。

# Use entire batch since this is such a small dataset.
NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(X), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).
    dataset = dataset.repeat(n_epochs)
    # In memory training doesn't use batching.
    dataset = dataset.batch(NUM_EXAMPLES)
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

 

モデルを訓練して評価する

下では次のステップを行ないます :

  1. 特徴とハイパーパラメータを指定して、モデルを初期化します。
  2. train_input_fn を使用してモデルに訓練データを供給して train 関数を使用してモデルを訓練します。
  3. 評価セット — この例では dfeval DataFrame を使用してモデル・パフォーマンスを評価します。予測が y_eval 配列からのラベルにマッチするか検証します。

ブースティング木モデルを訓練する前に、最初に線形分類器 (ロジスティック回帰モデル) を訓練しましょう。ベンチマークを確証するためにより単純なモデルで始めるのがベストプラクティスです。

linear_est = tf.estimator.LinearClassifier(feature_columns)

# Train model.
linear_est.train(train_input_fn, max_steps=100)

# Evaluation.
result = linear_est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.765152
accuracy_baseline         0.625000
auc                       0.832844
auc_precision_recall      0.789631
average_loss              0.478908
global_step             100.000000
label/mean                0.375000
loss                      0.478908
precision                 0.703297
prediction/mean           0.350790
recall                    0.646465
dtype: float64

次に、ブーティング木モデルを訓練しましょう。ブースティング木については、回帰 (BoostedTreesRegressor) と分類 (BoostedTreesClassifier) がサポートされます。目標はクラス – 生存か非生存かを推測することですから、BoostedTreesClassifier を使用します。

# Since data fits into memory, use entire dataset per layer. It will be faster.
# Above one batch is defined as the entire dataset.
n_batches = 1
est = tf.estimator.BoostedTreesClassifier(feature_columns,
                                          n_batches_per_layer=n_batches)

# The model will stop training once the specified number of trees is built, not
# based on the number of steps.
est.train(train_input_fn, max_steps=100)

# Eval.
result = est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.829545
accuracy_baseline         0.625000
auc                       0.872788
auc_precision_recall      0.857807
average_loss              0.411839
global_step             100.000000
label/mean                0.375000
loss                      0.411839
precision                 0.793478
prediction/mean           0.381942
recall                    0.737374
dtype: float64

今では評価セットからの乗客について予測を行なうために訓練モデルを使用できます。TensorFlow モデルはサンプルのバッチやコレクションの上で同時に予測を行なうために最適化されています。前に、eval_input_fn は評価セット全体を使用して定義されています。

pred_dicts = list(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')
plt.show()

最後に結果の ROC (receiver operating characteristic) もまた見ることができます、これは真陽性率 (= true positive rate) と偽陽性率 (= false positive rate) 間のトレードオフのより良い考えを与えます。

from sklearn.metrics import roc_curve

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,)
plt.show()

 

以上



TensorFlow 2.0 : Tutorials : Estimator :- Estimator で線形モデルを構築する

TensorFlow 2.0 : Beginner Tutorials : Estimator :- Estimator で線形モデルを構築する (翻訳/解説)

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

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

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

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく 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)

 

以上



TensorFlow 2.0 : Tutorials : Estimator :- Premade Estimator

TensorFlow 2.0 : Beginner Tutorials : Estimator :- Premade Estimator (翻訳/解説)

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

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

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

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

Estimator :- Premade Estimator

このチュートリアルは Estimator を使用して TensorFlow でアイリス分類問題をどのように解くかを示します。Estimator は完全なモデルの TensorFlow の高位表現で、そしてそれは容易なスケーリングと非同期訓練のために設計されています。より詳細については Estimators を見てください。

TensorFlow 2.0 では、Keras API はこれらと同じタスクの多くを成し遂げることができて、そしてそれは学習するためにより容易な API であると見られていることに注意してください。もしあなたが新たに始めている場合には、Keras で始めることを貴方に勧めます。TensorFlow 2.0 で利用可能な高位 API についてのより多くの情報のためには、Standardizing on Keras を見てください。

 

大事なことを最初に

始めるために、最初に TensorFlow と必要な多くのライブラリをインポートします。

from __future__ import absolute_import, division, print_function, unicode_literals


import tensorflow as tf

import pandas as pd

 

データセット

このドキュメントのサンプル・プログラムはアイリス花をそれらの がく片花弁 のサイズに基づいて 3 つの異なる種に分類するためのモデルを構築してテストします。

アイリス・データセットを使用してモデルを訓練します。アイリス・データセットは 4 つの特徴と 1 つの ラベル を含みます。4つの特徴は個々のアイリス花の次の植物学的特性を識別します :

  • がく片長さ
  • がく片幅
  • 花弁長さ
  • 花弁幅

これらの情報に基づいて、データをパースするための 2,3 の役立つ定数を定義できます :

CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']

次に、Keras と Pandas を使用してアイリス・データセットをダウンロードしてパースします。訓練とテストのための別個のデータセットを保持していることに注意してください。

train_path = tf.keras.utils.get_file(
    "iris_training.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv")
test_path = tf.keras.utils.get_file(
    "iris_test.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv")

train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)

4 つの float 特徴カラムと 1 つの int32 ラベルを持つことを見るためのデータを調べることができます。

train.head()

がく片長さ

がく片幅

花弁長さ

花弁幅

0

6.4

2.8

5.6

2.2

2

1

5.0

2.3

3.3

1.0

1

2

4.9

2.5

4.5

1.7

2

3

4.9

3.1

1.5

0.1

0

4

5.7

3.8

1.7

0.3

0

データセットの各々のために、ラベルを分離します、これをモデルが予測するために訓練されます。

train_y = train.pop('Species')
test_y = test.pop('Species')

# The label column has now been removed from the features.
train.head()

がく片長さ

がく片幅

花弁長さ

花弁幅

0

6.4

2.8

5.6

2.2

1

5.0

2.3

3.3

1.0

2

4.9

2.5

4.5

1.7

3

4.9

3.1

1.5

0.1

4

5.7

3.8

1.7

0.3

 

Estimator によるプログラミング概要

セットアップされたデータを持つ今、TensorFlow Estimator を使用してモデルを定義できます。Estimator は tf.estimator.Estimator から派生する任意のクラスです。TensorFlow は一般的な ML アルゴリズムを実装する tf.estimator のコレクション (例えば、LinearRegressor) を提供します。それらを越えて、貴方自身の カスタム Estimator を書いても良いです。単に始めるときには pre-made Estimator を使用することを勧めます。

pre-made Estimator に基づく TensorFlow プログラムを書くには、次のタスクを遂行しなければなりません :

  • 一つまたはそれ以上の入力関数を作成する。
  • モデルの特徴カラムを定義する。
  • 特等カラムと様々なハイパーパラメータを指定して、Estimator をインスタンス化する。
  • データのソースとして適切な入力関数を渡して、Estimator オブジェクト上で一つまたはそれ以上のメソッドを呼び出します。

それらのタスクがアイリス分類のためにどのように実装されるかを見ましょう。

 

入力関数を作成する

訓練、評価そして予測のためにデータを供給する入力関数を作成しなければなりません。

入力関数は次の 2-要素タプルを出力する tf.data.Dataset オブジェクトを返す関数です :

  • 特徴 – Python 辞書、そこでは :
    • 各キーは特徴名です。
    • 各値はその特徴の値の総てを含む配列です。
  • ラベル – 総てのサンプルのための ラベル の値を含む配列。

入力関数の形式を単に実演するために、ここに単純な実装があります :

def input_evaluation_set():
    features = {'SepalLength': np.array([6.4, 5.0]),
                'SepalWidth':  np.array([2.8, 2.3]),
                'PetalLength': np.array([5.6, 3.3]),
                'PetalWidth':  np.array([2.2, 1.0])}
    labels = np.array([2, 1])
    return features, labels

貴方の入力関数は特徴辞書とラベルリストを貴方の好きな方法で生成するかもしれません。けれども、TensorFlow の Dataset API を使用することを勧めます、これは総ての種類のデータをパースできます。

Dataset API は貴方のために多くの一般的なケースを処理できます。例えば、Datset API を使用して、ファイルの巨大なコレクションから並列にレコードを容易に読み込むことができてそれらを単一のストリームに合流できます。

このサンプルで物事を単純に保持するためにデータを pandas でロードし、そしてこの in-メモリデータから入力パイプラインを構築していきます :

def input_fn(features, labels, training=True, batch_size=256):
    """An input function for training or evaluating"""
    # Convert the inputs to a Dataset.
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))

    # Shuffle and repeat if you are in training mode.
    if training:
        dataset = dataset.shuffle(1000).repeat()
    
    return dataset.batch(batch_size)

 

特徴カラムを定義する

特徴カラムはオブジェクトで、モデルが特徴辞書からの生入力データをどのように使用するべきかを記述します。Estimator モデルを構築するとき、モデルに使用することを望む特徴の各々を記述する特徴カラムのリストをそれに渡します。tf.feature_column モジュールはデータをモデルに表わすために多くのオプションを提供します。

アイリスのためには、4 生特徴は数値ですので、 4 つの特徴の各々を 32-bit 浮動小数点値として表わすように Estimator モデルに伝えるために特徴カラムのリストを構築します。従って、特徴カラムを作成するコードは :

# Feature columns describe how to use the input.
my_feature_columns = []
for key in train.keys():
    my_feature_columns.append(tf.feature_column.numeric_column(key=key))

特徴カラムはここで見せているものようりも遥かにより洗練されている可能性があります。このガイド で特徴カラムについて更に読むことができます。

モデルに生特徴をどのように表わすことを望むかの記述を持つ今、estimator を構築できます。

 

estimator をインスタンス化する

アイリス問題は古典的な分類問題です。幸い、TensorFlow は幾つかの pre-made 分類器 Estimator を提供しています、次を含みます :

このアイリス問題のためには、tf.estimator.DNNClassifier が最善の選択のようです。ここにこの Estimator をどのようにインスタンス化したかがあります :

# Build a DNN with 2 hidden layers with 30 and 10 hidden nodes each.
classifier = tf.estimator.DNNClassifier(
    feature_columns=my_feature_columns,
    # Two hidden layers of 10 nodes each.
    hidden_units=[30, 10],
    # The model must choose between 3 classes.
    n_classes=3)
INFO:tensorflow:Using default config.
WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmpy5w5zoj8
INFO:tensorflow:Using config: {'_service': None, '_device_fn': None, '_train_distribute': None, '_evaluation_master': '', '_master': '', '_tf_random_seed': None, '_session_creation_timeout_secs': 7200, '_global_id_in_cluster': 0, '_task_id': 0, '_num_ps_replicas': 0, '_is_chief': True, '_protocol': None, '_keep_checkpoint_max': 5, '_experimental_max_worker_delay_secs': None, '_eval_distribute': None, '_task_type': 'worker', '_save_summary_steps': 100, '_num_worker_replicas': 1, '_experimental_distribute': None, '_keep_checkpoint_every_n_hours': 10000, '_cluster_spec': , '_model_dir': '/tmp/tmpy5w5zoj8', '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_log_step_count_steps': 100, '_save_checkpoints_secs': 600, '_save_checkpoints_steps': None}

 

訓練、評価そして予測する

Estimator オブジェクトを持つ今、以下を行なうためにメソッドを呼び出せます :

  • モデルを訓練する。
  • 訓練されたモデルを評価する。
  • 予測を行なうため訓練されたモデルを使用する。

 

モデルを訓練する

Estimator の train メソッドを次のように呼び出してモデルを訓練します :

# Train the Model.
classifier.train(
    input_fn=lambda: input_fn(train, train_y, training=True),
    steps=5000)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.5/site-packages/tensorflow_core/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Layer dnn 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/keras/optimizer_v2/adagrad.py:108: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpy5w5zoj8/model.ckpt.
INFO:tensorflow:loss = 1.2197917, step = 0
INFO:tensorflow:global_step/sec: 238.94
INFO:tensorflow:loss = 1.0917794, step = 100 (0.420 sec)
INFO:tensorflow:global_step/sec: 301.312
INFO:tensorflow:loss = 1.0716088, step = 200 (0.332 sec)
INFO:tensorflow:global_step/sec: 303.674
INFO:tensorflow:loss = 1.0544529, step = 300 (0.329 sec)
INFO:tensorflow:global_step/sec: 302.426
INFO:tensorflow:loss = 1.0382756, step = 400 (0.331 sec)
INFO:tensorflow:global_step/sec: 302.738
INFO:tensorflow:loss = 1.027103, step = 500 (0.331 sec)
INFO:tensorflow:global_step/sec: 304.599
INFO:tensorflow:loss = 1.0103141, step = 600 (0.328 sec)
INFO:tensorflow:global_step/sec: 303.949
INFO:tensorflow:loss = 0.9966562, step = 700 (0.329 sec)
INFO:tensorflow:global_step/sec: 303.033
INFO:tensorflow:loss = 0.9852488, step = 800 (0.330 sec)
INFO:tensorflow:global_step/sec: 302.643
INFO:tensorflow:loss = 0.96979976, step = 900 (0.330 sec)
INFO:tensorflow:global_step/sec: 304.923
INFO:tensorflow:loss = 0.9661863, step = 1000 (0.328 sec)
INFO:tensorflow:global_step/sec: 323.831
INFO:tensorflow:loss = 0.9523607, step = 1100 (0.309 sec)
INFO:tensorflow:global_step/sec: 330.137
INFO:tensorflow:loss = 0.935673, step = 1200 (0.303 sec)
INFO:tensorflow:global_step/sec: 328.748
INFO:tensorflow:loss = 0.929138, step = 1300 (0.304 sec)
INFO:tensorflow:global_step/sec: 325.541
INFO:tensorflow:loss = 0.9089911, step = 1400 (0.307 sec)
INFO:tensorflow:global_step/sec: 324.871
INFO:tensorflow:loss = 0.9001589, step = 1500 (0.308 sec)
INFO:tensorflow:global_step/sec: 327.313
INFO:tensorflow:loss = 0.8927353, step = 1600 (0.305 sec)
INFO:tensorflow:global_step/sec: 329.062
INFO:tensorflow:loss = 0.88943803, step = 1700 (0.304 sec)
INFO:tensorflow:global_step/sec: 328.659
INFO:tensorflow:loss = 0.8707663, step = 1800 (0.304 sec)
INFO:tensorflow:global_step/sec: 314.002
INFO:tensorflow:loss = 0.86156833, step = 1900 (0.319 sec)
INFO:tensorflow:global_step/sec: 300.244
INFO:tensorflow:loss = 0.852653, step = 2000 (0.333 sec)
INFO:tensorflow:global_step/sec: 299.23
INFO:tensorflow:loss = 0.83402675, step = 2100 (0.334 sec)
INFO:tensorflow:global_step/sec: 304.725
INFO:tensorflow:loss = 0.82657015, step = 2200 (0.328 sec)
INFO:tensorflow:global_step/sec: 302.436
INFO:tensorflow:loss = 0.8211421, step = 2300 (0.330 sec)
INFO:tensorflow:global_step/sec: 301.456
INFO:tensorflow:loss = 0.8120619, step = 2400 (0.332 sec)
INFO:tensorflow:global_step/sec: 307.489
INFO:tensorflow:loss = 0.798753, step = 2500 (0.325 sec)
INFO:tensorflow:global_step/sec: 309.389
INFO:tensorflow:loss = 0.7921459, step = 2600 (0.323 sec)
INFO:tensorflow:global_step/sec: 309.822
INFO:tensorflow:loss = 0.7766729, step = 2700 (0.323 sec)
INFO:tensorflow:global_step/sec: 314.836
INFO:tensorflow:loss = 0.76089776, step = 2800 (0.318 sec)
INFO:tensorflow:global_step/sec: 310.84
INFO:tensorflow:loss = 0.7654529, step = 2900 (0.322 sec)
INFO:tensorflow:global_step/sec: 315.348
INFO:tensorflow:loss = 0.7533946, step = 3000 (0.317 sec)
INFO:tensorflow:global_step/sec: 313.578
INFO:tensorflow:loss = 0.7357384, step = 3100 (0.319 sec)
INFO:tensorflow:global_step/sec: 312.985
INFO:tensorflow:loss = 0.73263234, step = 3200 (0.319 sec)
INFO:tensorflow:global_step/sec: 311.498
INFO:tensorflow:loss = 0.72836924, step = 3300 (0.321 sec)
INFO:tensorflow:global_step/sec: 312.958
INFO:tensorflow:loss = 0.7124317, step = 3400 (0.319 sec)
INFO:tensorflow:global_step/sec: 312.767
INFO:tensorflow:loss = 0.70199186, step = 3500 (0.320 sec)
INFO:tensorflow:global_step/sec: 336.802
INFO:tensorflow:loss = 0.6960018, step = 3600 (0.297 sec)
INFO:tensorflow:global_step/sec: 332.888
INFO:tensorflow:loss = 0.6923122, step = 3700 (0.300 sec)
INFO:tensorflow:global_step/sec: 327.027
INFO:tensorflow:loss = 0.67529535, step = 3800 (0.306 sec)
INFO:tensorflow:global_step/sec: 322.62
INFO:tensorflow:loss = 0.678157, step = 3900 (0.310 sec)
INFO:tensorflow:global_step/sec: 322.949
INFO:tensorflow:loss = 0.6730201, step = 4000 (0.310 sec)
INFO:tensorflow:global_step/sec: 335.008
INFO:tensorflow:loss = 0.65053713, step = 4100 (0.298 sec)
INFO:tensorflow:global_step/sec: 332.504
INFO:tensorflow:loss = 0.64781785, step = 4200 (0.301 sec)
INFO:tensorflow:global_step/sec: 335.872
INFO:tensorflow:loss = 0.64207447, step = 4300 (0.298 sec)
INFO:tensorflow:global_step/sec: 335.598
INFO:tensorflow:loss = 0.6398175, step = 4400 (0.298 sec)
INFO:tensorflow:global_step/sec: 334.703
INFO:tensorflow:loss = 0.6255224, step = 4500 (0.299 sec)
INFO:tensorflow:global_step/sec: 337.713
INFO:tensorflow:loss = 0.62776095, step = 4600 (0.296 sec)
INFO:tensorflow:global_step/sec: 340.161
INFO:tensorflow:loss = 0.6233723, step = 4700 (0.294 sec)
INFO:tensorflow:global_step/sec: 335.719
INFO:tensorflow:loss = 0.6083272, step = 4800 (0.298 sec)
INFO:tensorflow:global_step/sec: 332.322
INFO:tensorflow:loss = 0.5927398, step = 4900 (0.301 sec)
INFO:tensorflow:Saving checkpoints for 5000 into /tmp/tmpy5w5zoj8/model.ckpt.
INFO:tensorflow:Loss for final step: 0.59226876.

<tensorflow_estimator.python.estimator.canned.dnn.DNNClassifierV2 at 0x7ff1da8fd438>

引数を取らない入力関数を提供する一方で、Estimator により想定される引数を捕捉するために貴方の input_fn 呼び出しを lambda でラップしていることに注意してください。steps 引数は訓練ステップの数の後訓練を停止することをメソッドに伝えます。

 

訓練されたモデルを評価する

モデルが訓練された今、そのパフォーマンス上の何某かの統計情報を得られます。次のコードブロックは訓練されたモデルの精度をテストデータ上で評価します :

eval_result = classifier.evaluate(
    input_fn=lambda: input_fn(test, test_y, training=False))

print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Layer dnn 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:Starting evaluation at 2019-10-01T01:28:45Z
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpy5w5zoj8/model.ckpt-5000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2019-10-01-01:28:46
INFO:tensorflow:Saving dict for global step 5000: accuracy = 0.56666666, average_loss = 0.6702302, global_step = 5000, loss = 0.6702302
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 5000: /tmp/tmpy5w5zoj8/model.ckpt-5000

Test set accuracy: 0.567

train メソッドへの呼び出しとは違い、evaluate には steps 引数は渡しませんでした。eval のための input_fn はデータの単一 エポック を生成するだけです。

eval_result 辞書はまた average_loss (サンプル毎の平均損失)、損失 (ミニバッチ毎の平均損失) そして estimator の global_step (それが受けた訓練反復の数) の値を含みます。

 

訓練されたモデルから予測 (推論) を行なう

今は良い評価結果を生成する訓練されたモデルを持ちます。今は幾つかのラベル付けされていない測定に基づいてアイリス花の種を予測するために訓練されたモデルを使用できます。訓練と評価と同様に、単一の関数呼び出しを使用して予測を行ないます :

# Generate predictions from the model
expected = ['Setosa', 'Versicolor', 'Virginica']
predict_x = {
    'SepalLength': [5.1, 5.9, 6.9],
    'SepalWidth': [3.3, 3.0, 3.1],
    'PetalLength': [1.7, 4.2, 5.4],
    'PetalWidth': [0.5, 1.5, 2.1],
}

def input_fn(features, batch_size=256):
    """An input function for prediction."""
    # Convert the inputs to a Dataset without labels.
    return tf.data.Dataset.from_tensor_slices(dict(features)).batch(batch_size)

predictions = classifier.predict(
    input_fn=lambda: input_fn(predict_x))

predict メソッドは Python iterable を返し、各サンプルのための予測の辞書を生成します。次のコードは 2, 3 の予測とそれらの確率をプリントします :

for pred_dict, expec in zip(predictions, expected):
    class_id = pred_dict['class_ids'][0]
    probability = pred_dict['probabilities'][class_id]

    print('Prediction is "{}" ({:.1f}%), expected "{}"'.format(
        SPECIES[class_id], 100 * probability, expec))
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpy5w5zoj8/model.ckpt-5000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
Prediction is "Setosa" (73.0%), expected "Setosa"
Prediction is "Virginica" (42.6%), expected "Versicolor"
Prediction is "Virginica" (49.0%), expected "Virginica"
 

以上



TensorFlow 2.0 Alpha : Tutorials : Estimator :- Estimator で線形モデルを構築する

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)

 

以上



TensorFlow 2.0 Alpha : Tutorials : Estimator :- 勾配ブースティング木: モデル理解

TensorFlow 2.0 Alpha : Beginner Tutorials : Estimator :- 勾配ブースティング木: モデル理解 (翻訳/解説)

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

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

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

 

 

Estimator :- 勾配ブースティング木: モデル理解

勾配ブースティング・モデルを訓練する end-to-end ウォークスルーについては ブースティング木チュートリアル を調べてください。このチュートリアルでは貴方は :

  • ブースティング木モデルをローカルとグルーバルの両者でどのように解釈するかを学習します。
  • ブースティング木モデルがデータセットにどのように fit するかについて直感を得ます。

 

ブースティング木モデルをローカルとグローバルの両者でどのように解釈するか

ローカル解釈可能性 (= interpretability) は個別のサンプルレベルでのモデルの予測の理解を参照し、その一方で、グルーバル解釈可能性は全体としてのモデルの理解を参照します。そのようなテクニックは機械学習 (ML) 実践者にモデル開発段階でバイアスとバグを検出する助けとなれます。

ローカル解釈可能性については、どのようにインスタンス毎の寄与を作成して可視化するかを学習します。これを特徴量重要度と区別するため、これらの値を DFC (directional feature contributions) として参照します。

グローバル解釈可能性については、gain-based 特徴量重要度、再配列 (= permutation) 特徴量重要度 を取得して可視化し、そしてまた総計 (= aggregated) DFC を示します。

 

タイタニック・データセットをロードします

タイタニック・データセットを使用します、そこでは (寧ろ憂鬱な) 目標は性別、年齢、クラス, etc. のような特質が与えられたときに乗客の生存を予測することです。

from __future__ import absolute_import, division, print_function

import numpy as np
import pandas as pd
from IPython.display import clear_output

# 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')

!pip install -q tensorflow==2.0.0-alpha0

import tensorflow as tf
tf.random.set_seed(123)

特徴の説明については、前のチュートリアルを見直してください。

 

feature columns, input_fn を作成して estimator を訓練する

データを前処理する

オリジナルの numeric column そのままと one-hot-エンコーディング categorical 変数を使用して feature column を作成します。

fc = tf.feature_column
CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck', 
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']
  
def one_hot_cat_column(feature_name, vocab):
  return fc.indicator_column(
      fc.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))
  
for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(fc.numeric_column(feature_name,
                                           dtype=tf.float32))

 

入力パイプラインを構築する

Pandas から直接データを読み込むために tf.data API の from_tensor_slices メソッドを使用して入力関数を作成します。

# Use entire batch since this is such a small dataset.
NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((X.to_dict(orient='list'), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).    
    dataset = (dataset
      .repeat(n_epochs)
      .batch(NUM_EXAMPLES)) 
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

 

モデルを訓練する

params = {
  'n_trees': 50,
  'max_depth': 3,
  'n_batches_per_layer': 1,
  # You must enable center_bias = True to get DFCs. This will force the model to 
  # make an initial prediction before using any features (e.g. use the mean of 
  # the training labels for regression or log odds for classification when
  # using cross entropy loss).
  'center_bias': True
}

est = tf.estimator.BoostedTreesClassifier(feature_columns, **params)
# Train model.
est.train(train_input_fn, max_steps=100)

# Evaluation.
results = est.evaluate(eval_input_fn)
clear_output()
pd.Series(results).to_frame()

accuracy 0.806818
accuracy_baseline 0.625000
auc 0.866606
auc_precision_recall 0.849128
average_loss 0.421549
global_step 100.000000
label/mean 0.375000
loss 0.421549
precision 0.755319
prediction/mean 0.384944
recall 0.717172

 

モデル解釈とプロット

import matplotlib.pyplot as plt
import seaborn as sns
sns_colors = sns.color_palette('colorblind')

 

ローカル解釈可能性

次に個々の予測を説明するために Palczewska et alInterpreting Random Forests で Saabas により概説されたアプローチを使用して DFC (directional feature contributions) を出力します (このメソッドはまた treeinterpreter パッケージで Random Forests のための scikit-learn でも利用可能です)。

DFC は次で生成されます :

pred_dicts = list(est.experimental_predict_with_explanations(pred_input_fn))

(Note: このメソッドは experimental として命名されていますがこれは experimental prefix を破棄する前に API を変更するかもしれないためです。)

pred_dicts = list(est.experimental_predict_with_explanations(eval_input_fn))
# Create DFC Pandas dataframe.
labels = y_eval.values
probs = pd.Series([pred['probabilities'][1] for pred in pred_dicts])
df_dfc = pd.DataFrame([pred['dfc'] for pred in pred_dicts])
df_dfc.describe().T

count mean std min 25% 50% 75% max
age 264.0 -0.027537 0.080741 -0.139372 -0.076765 -0.052056 0.002137 0.372113
sex 264.0 0.006734 0.106714 -0.119415 -0.072686 -0.071646 0.136922 0.179607
class 264.0 0.016440 0.091105 -0.054638 -0.045972 -0.045116 0.034190 0.227794
deck 264.0 -0.016943 0.029100 -0.060259 -0.041967 -0.029271 0.003616 0.135820
embark_town 264.0 -0.006554 0.025388 -0.050465 -0.013431 -0.012491 -0.002658 0.062315
fare 264.0 0.022725 0.083313 -0.238293 -0.023252 -0.005715 0.054752 0.221681
n_siblings_spouses 264.0 0.002379 0.018807 -0.120684 0.002746 0.003192 0.005547 0.066210
parch 264.0 0.000140 0.003230 -0.052090 0.000235 0.000285 0.000497 0.000574
alone 264.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

DFC の素晴らしい特性は寄与の合計 + bias が与えられたサンプルの予測に等しいことです。

# Sum of DFCs + bias == probabality.
bias = pred_dicts[0]['bias']
dfc_prob = df_dfc.sum(axis=1) + bias
np.testing.assert_almost_equal(dfc_prob.values,
                               probs.values)

個々の乗客のための DFC をプロットします。寄与の方向性に基づいたカラー・コーディングによりプロットを素晴らしくして図に特徴量値を追加しましょう。

# Boilerplate code for plotting : )
def _get_color(value):
    """To make positive DFCs plot green, negative DFCs plot red."""
    green, red = sns.color_palette()[2:4]
    if value >= 0: return green
    return red

def _add_feature_values(feature_values, ax):
    """Display feature's values on left of plot."""
    x_coord = ax.get_xlim()[0]
    OFFSET = 0.15
    for y_coord, (feat_name, feat_val) in enumerate(feature_values.items()):
        t = plt.text(x_coord, y_coord - OFFSET, '{}'.format(feat_val), size=12)
        t.set_bbox(dict(facecolor='white', alpha=0.5))
    from matplotlib.font_manager import FontProperties
    font = FontProperties()
    font.set_weight('bold')
    t = plt.text(x_coord, y_coord + 1 - OFFSET, 'feature\nvalue',
    fontproperties=font, size=12)
    
def plot_example(example):
  TOP_N = 8 # View top 8 features.
  sorted_ix = example.abs().sort_values()[-TOP_N:].index  # Sort by magnitude.
  example = example[sorted_ix]
  colors = example.map(_get_color).tolist()
  ax = example.to_frame().plot(kind='barh',
                          color=[colors],
                          legend=None,
                          alpha=0.75,
                          figsize=(10,6))
  ax.grid(False, axis='y')
  ax.set_yticklabels(ax.get_yticklabels(), size=14)

  # Add feature values.
  _add_feature_values(dfeval.iloc[ID][sorted_ix], ax)
  return ax
# Plot results.
ID = 182
example = df_dfc.iloc[ID]  # Choose ith example from evaluation set.
TOP_N = 8  # View top 8 features.
sorted_ix = example.abs().sort_values()[-TOP_N:].index
ax = plot_example(example)
ax.set_title('Feature contributions for example {}\n pred: {:1.2f}; label: {}'.format(ID, probs[ID], labels[ID]))
ax.set_xlabel('Contribution to predicted probability', size=14);

より大きな量の寄与がモデルの予測の上でより大きなインパクトを持ちます。ネガティブな寄与は与えられたサンプルに対する特徴量値がモデルの予測を減少させることを示し、その一方でポジティブな値は予測において増量に寄与します。

バイオリンプロットを使用して全体の分布と比較してサンプルの DFC をプロットすることもできます。

# Boilerplate plotting code.
def dist_violin_plot(df_dfc, ID):
  # Initialize plot.
  fig, ax = plt.subplots(1, 1, figsize=(10, 6))
  
  # Create example dataframe.
  TOP_N = 8  # View top 8 features.
  example = df_dfc.iloc[ID]
  ix = example.abs().sort_values()[-TOP_N:].index
  example = example[ix]
  example_df = example.to_frame(name='dfc')
  
  # Add contributions of entire distribution.
  parts=ax.violinplot([df_dfc[w] for w in ix],
                 vert=False,
                 showextrema=False,
                 widths=0.7,
                 positions=np.arange(len(ix)))
  face_color = sns_colors[0]
  alpha = 0.15
  for pc in parts['bodies']:
      pc.set_facecolor(face_color)
      pc.set_alpha(alpha)
  
  # Add feature values.
  _add_feature_values(dfeval.iloc[ID][sorted_ix], ax)

  # Add local contributions.
  ax.scatter(example,
              np.arange(example.shape[0]),
              color=sns.color_palette()[2],
              s=100,
              marker="s",
              label='contributions for example')
  
  # Legend
  # Proxy plot, to show violinplot dist on legend.
  ax.plot([0,0], [1,1], label='eval set contributions\ndistributions',
          color=face_color, alpha=alpha, linewidth=10)
  legend = ax.legend(loc='lower right', shadow=True, fontsize='x-large',
                     frameon=True)
  legend.get_frame().set_facecolor('white')
  
  # Format plot.
  ax.set_yticks(np.arange(example.shape[0]))
  ax.set_yticklabels(example.index)
  ax.grid(False, axis='y')
  ax.set_xlabel('Contribution to predicted probability', size=14)

このサンプルをプロットします。

dist_violin_plot(df_dfc, ID)
plt.title('Feature contributions for example {}\n pred: {:1.2f}; label: {}'.format(ID, probs[ID], labels[ID]));

最後に、LIMEshap のようなサードパーティのツールもまたモデルに対する個々の予測を理解する助けになれます。

 

グローバル特徴量重要度

追加として、個々の予測の研究よりもモデルを全体として理解することを望むかもしれません。下で、以下を計算して使用します :

  1. est.experimental_feature_importances を使用して gain-based 特徴量重要度
  2. 再配列 (= permutation) 重要度
  3. est.experimental_predict_with_explanations を使用して総計 DFC

gain-based 特徴量重要度は特定の特徴上で分割するときの損失変化を測定します、一方で再配列重要度は各特徴を一つずつシャッフルしてモデル性能の変化をシャッフルされた特徴に帰することによって検証セット上のモデル性能を評価することにより計算されます。

一般に、再配列特徴量重要度が gain-based 特徴量重要度より好まれます、両者のメソッドは潜在的予測変数が測定のスケールやカテゴリー数が変化する状況で特徴が相関関係があるときには信頼できない可能性はありますが (ソース)。異なる特徴量重要度タイプについての掘り下げた概要と素晴らしい議論については この記事 を調べてください。

 

1. Gain-based 特徴量重要度

grain-based 特徴量重要度は est.experimental_feature_importances を使用して TensorFlow Boosted Trees estimator に組み込まれます。

importances = est.experimental_feature_importances(normalize=True)
df_imp = pd.Series(importances)

# Visualize importances.
N = 8
ax = (df_imp.iloc[0:N][::-1]
    .plot(kind='barh',
          color=sns_colors[0],
          title='Gain feature importances',
          figsize=(10, 6)))
ax.grid(False, axis='y')

 

2. DFC の絶対値を平均する

グローバルレベルのインパクトを理解するために DFC の絶対値を平均することもできます。

# Plot.
dfc_mean = df_dfc.abs().mean()
N = 8
sorted_ix = dfc_mean.abs().sort_values()[-N:].index  # Average and sort by absolute.
ax = dfc_mean[sorted_ix].plot(kind='barh',
                       color=sns_colors[1],
                       title='Mean |directional feature contributions|',
                       figsize=(10, 6))
ax.grid(False, axis='y')

特徴量が変化するとき DFC がどのように変化するかを見ることもできます。

FEATURE = 'fare'
feature = pd.Series(df_dfc[FEATURE].values, index=dfeval[FEATURE].values).sort_index()
ax = sns.regplot(feature.index.values, feature.values, lowess=True);
ax.set_ylabel('contribution')
ax.set_xlabel(FEATURE);
ax.set_xlim(0, 100);

 

3. 再配列特徴量重要度

def permutation_importances(est, X_eval, y_eval, metric, features):
    """Column by column, shuffle values and observe effect on eval set.
    
    source: http://explained.ai/rf-importance/index.html
    A similar approach can be done during training. See "Drop-column importance"
    in the above article."""
    baseline = metric(est, X_eval, y_eval)
    imp = []
    for col in features:
        save = X_eval[col].copy()
        X_eval[col] = np.random.permutation(X_eval[col])
        m = metric(est, X_eval, y_eval)
        X_eval[col] = save
        imp.append(baseline - m)
    return np.array(imp)

def accuracy_metric(est, X, y):
    """TensorFlow estimator accuracy."""
    eval_input_fn = make_input_fn(X,
                                  y=y,
                                  shuffle=False,
                                  n_epochs=1)
    return est.evaluate(input_fn=eval_input_fn)['accuracy']
features = CATEGORICAL_COLUMNS + NUMERIC_COLUMNS
importances = permutation_importances(est, dfeval, y_eval, accuracy_metric,
                                      features)
df_imp = pd.Series(importances, index=features)

sorted_ix = df_imp.abs().sort_values().index
ax = df_imp[sorted_ix][-5:].plot(kind='barh', color=sns_colors[2], figsize=(10, 6))
ax.grid(False, axis='y')
ax.set_title('Permutation feature importance');

 

モデル fitting を可視化する

最初に次の式を使用して訓練データをシミュレート/ 作成しましょう :

\[
z=x* e^{-x^2 – y^2}
\]

ここで (z) は貴方が予測しようとする従属変数でそして (x) と (y) は特徴です。

from numpy.random import uniform, seed
from matplotlib.mlab import griddata

# Create fake data
seed(0)
npts = 5000
x = uniform(-2, 2, npts)
y = uniform(-2, 2, npts)
z = x*np.exp(-x**2 - y**2)
# Prep data for training.
df = pd.DataFrame({'x': x, 'y': y, 'z': z})

xi = np.linspace(-2.0, 2.0, 200),
yi = np.linspace(-2.1, 2.1, 210),
xi,yi = np.meshgrid(xi, yi);

df_predict = pd.DataFrame({
    'x' : xi.flatten(),
    'y' : yi.flatten(),
})
predict_shape = xi.shape
def plot_contour(x, y, z, **kwargs):
  # Grid the data.
  plt.figure(figsize=(10, 8))
  # Contour the gridded data, plotting dots at the nonuniform data points.
  CS = plt.contour(x, y, z, 15, linewidths=0.5, colors='k')
  CS = plt.contourf(x, y, z, 15,
                    vmax=abs(zi).max(), vmin=-abs(zi).max(), cmap='RdBu_r')
  plt.colorbar()  # Draw colorbar.
  # Plot data points.
  plt.xlim(-2, 2)
  plt.ylim(-2, 2)

関数をビジュアル化できます。より赤い色がより大きな関数値に対応します。

zi = griddata(x, y, z, xi, yi, interp='linear')
plot_contour(xi, yi, zi)
plt.scatter(df.x, df.y, marker='.')
plt.title('Contour on training data');

fc = [tf.feature_column.numeric_column('x'),
      tf.feature_column.numeric_column('y')]
def predict(est):
  """Predictions from a given estimator."""
  predict_input_fn = lambda: tf.data.Dataset.from_tensors(dict(df_predict))
  preds = np.array([p['predictions'][0] for p in est.predict(predict_input_fn)])
  return preds.reshape(predict_shape)

最初に線形モデルをデータに fit させてみましょう。

train_input_fn = make_input_fn(df, df.z)
est = tf.estimator.LinearRegressor(fc)
est.train(train_input_fn, max_steps=500);
plot_contour(xi, yi, predict(est))

それは非常に良い fit ではありません。

次に GBDT モデルをそれに fit させてみましょうそしてモデルがどのように関数に fit するか理解してみましょう。

n_trees = 22 #@param {type: "slider", min: 1, max: 80, step: 1}

est = tf.estimator.BoostedTreesRegressor(fc, n_batches_per_layer=1, n_trees=n_trees)
est.train(train_input_fn, max_steps=500)
clear_output()
plot_contour(xi, yi, predict(est))
plt.text(-1.8, 2.1, '# trees: {}'.format(n_trees), color='w', backgroundcolor='black', size=20);

木の数を増やすにつれて、モデルの予測は基礎となる関数をより良く近似します。

 

最後に

このチュートリアルでは DFC (directional feature contributions) と特徴量重要度テクニックを使用してブースティング木モデルをどのように解釈するかを学習しました。これらのテクニックは特徴量がモデルの予測にどのようにインパクトを与えるかの洞察を提供します。最後に、幾つかのモデルについて決定面を見ることによりブースティング木モデルが複雑な関数にどのように fit するかについての直感もまた得られました。

 

以上






TensorFlow 2.0 Alpha : Tutorials : Estimator :- TensorFlow 2.0 でブースティング木モデルをどのように訓練するか

TensorFlow 2.0 Alpha : Beginner Tutorials : Estimator :- TensorFlow 2.0 でブースティング木モデルをどのように訓練するか (翻訳/解説)

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

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

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

 

Estimator :- TensorFlow 2.0 でブースティング木モデルをどのように訓練するか

このチュートリアルは tf.estimator API で決定木を使用する勾配ブースティング木を訓練する end-to-end なウォークスルーです。ブースティング木モデルは回帰と分類の両者のための最も一般的で効果的な機械学習アプローチの一つです。それは幾つか (10s, 100s あるいは 1000s さえも考えます) の木モデルからの予測を連結するアンサンブル・テクニックです。

ブースト木モデルは多くの機械学習実践者により人気があります、何故ならばそれらは最小限のハイパーパラメータ調整で素晴らしいパフォーマンスを獲得できるからです。

 

タイタニック・データセットをロードする

タイタニック・データセットを使用します、そこでは (寧ろ憂鬱な) 目標は性別、年齢、クラス, etc. のような特質が与えられたときに乗客の生存を予測することです。

from __future__ import absolute_import, division, print_function

import numpy as np
import pandas as pd
from IPython.display import clear_output

# 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')
!pip install -q tensorflow==2.0.0-alpha0
import tensorflow as tf
tf.random.set_seed(123)

データセットは訓練セットと評価セットから成ります :

  • dftrain と y_train は訓練セットです — モデルが学習するために使用するデータです。
  • モデルは評価セット, dfeval と y_eval に対してテストされます。

訓練のために次の特徴を使用します :

Feature Name Description
sex 乗客の性別
age 乗客の年齢
n_siblings_spouses # 乗船した兄弟とパートナー
parch # of 乗船した両親と子供
fare 乗客が支払った運賃
class 船の乗客のクラス
deck 乗客がどのデッキ上にいたか
embark_town 乗客がどの町から乗船したか
alone 乗客が一人であるか否か

 

データを調査する

最初にデータの幾つかをプレビューして訓練セット上の簡易統計 (= summary statistics) を作成します。

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');

殆どの乗客は Southampton から乗船しました。

dftrain['embark_town'].value_counts().plot(kind='barh');

女性は男性に比較して遥かに高い生存のチャンスを持ちます。これは明らかにモデルのための予測的な特徴となるでしょう。

pd.concat([dftrain, y_train], axis=1).groupby('sex').survived.mean().plot(kind='barh').set_xlabel('% survive');

 

feature column と入力関数を作成する

勾配ブースティング estimator は numeric と categorical features の両者を利用できます。feature columns は総ての TensorFlow estimator とともに動作してそれらの目的はモデリングのために使用される特徴を定義することです。更にそれらは one-hot-エンコーディング、正規化そして bucketization のようなある特徴エンジニアリング機能を提供します。このチュートリアルでは、CATEGORICAL_COLUMNS のフィールドは categorical columns から one-hot-エンコードされた columns (indicator column) へ変形されます :

fc = tf.feature_column
CATEGORICAL_COLUMNS = ['sex', 'n_siblings_spouses', 'parch', 'class', 'deck', 
                       'embark_town', 'alone']
NUMERIC_COLUMNS = ['age', 'fare']
  
def one_hot_cat_column(feature_name, vocab):
  return tf.feature_column.indicator_column(
      tf.feature_column.categorical_column_with_vocabulary_list(feature_name,
                                                 vocab))
feature_columns = []
for feature_name in CATEGORICAL_COLUMNS:
  # Need to one-hot encode categorical features.
  vocabulary = dftrain[feature_name].unique()
  feature_columns.append(one_hot_cat_column(feature_name, vocabulary))
  
for feature_name in NUMERIC_COLUMNS:
  feature_columns.append(tf.feature_column.numeric_column(feature_name,
                                           dtype=tf.float32))

feature column が生成する変形を見ることができます。例えば、ここに単一のサンプル上で indicator_column を使用するときの出力があります :

example = dict(dftrain.head(1))
class_fc = tf.feature_column.indicator_column(tf.feature_column.categorical_column_with_vocabulary_list('class', ('First', 'Second', 'Third')))
print('Feature value: "{}"'.format(example['class'].iloc[0]))
print('One-hot encoded: ', tf.keras.layers.DenseFeatures([class_fc])(example).numpy())
Feature value: "Third"
One-hot encoded:  [[ 0.  0.  1.]]

更に、総ての feature column 変形も一緒に見ることができます :

tf.keras.layers.DenseFeatures(feature_columns)(example).numpy()
array([[ 22.  ,   1.  ,   0.  ,   1.  ,   0.  ,   0.  ,   1.  ,   0.  ,
          0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ,   1.  ,   0.  ,
          0.  ,   0.  ,   7.25,   1.  ,   0.  ,   0.  ,   0.  ,   0.  ,
          0.  ,   0.  ,   1.  ,   0.  ,   0.  ,   0.  ,   0.  ,   0.  ,
          1.  ,   0.  ]], dtype=float32)

次に入力関数を作成する必要があります。これらは訓練と推論の両者に対してデータがどのようにモデルに読まれるかを指定します。Pandas から直接データを読み込むために tf.data API の from_tensor_slices メソッドを使用します。これはより小さい、in-メモリなデータセットに対して適しています。より巨大なデータセットについては、メモリに収まらないデータセットを処理できるように tf.data API は (csv を含む) 様々な種類のファイルフォーマットをサポートします。

# Use entire batch since this is such a small dataset.
NUM_EXAMPLES = len(y_train)

def make_input_fn(X, y, n_epochs=None, shuffle=True):
  def input_fn():
    dataset = tf.data.Dataset.from_tensor_slices((dict(X), y))
    if shuffle:
      dataset = dataset.shuffle(NUM_EXAMPLES)
    # For training, cycle thru dataset as many times as need (n_epochs=None).    
    dataset = dataset.repeat(n_epochs)
    # In memory training doesn't use batching.
    dataset = dataset.batch(NUM_EXAMPLES)
    return dataset
  return input_fn

# Training and evaluation input functions.
train_input_fn = make_input_fn(dftrain, y_train)
eval_input_fn = make_input_fn(dfeval, y_eval, shuffle=False, n_epochs=1)

 

モデルを訓練して評価する

下では次のステップを行ないます :

  1. features とハイパーパラメータを指定して、モデルを初期化します。
  2. train_input_fn を使用してモデルに訓練データを供給して train 関数を使用してモデルを訓練します。
  3. 評価セット — この例では dfeval DataFrame を使用してモデル・パフォーマンスを評価します。予測が y_eval 配列からのラベルにマッチするか検証します。

ブースティング木モデルを訓練する前に、最初に線形分類器 (ロジスティック回帰モデル) を訓練しましょう。ベンチマークを確証するためにより単純なモデルで始めるのがベストプラクティスです。

linear_est = tf.estimator.LinearClassifier(feature_columns)

# Train model.
linear_est.train(train_input_fn, max_steps=100)

# Evaluation.
result = linear_est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.765152
accuracy_baseline         0.625000
auc                       0.832844
auc_precision_recall      0.789631
average_loss              0.478908
global_step             100.000000
label/mean                0.375000
loss                      0.478908
precision                 0.703297
prediction/mean           0.350790
recall                    0.646465
dtype: float64

次に、ブーティング木モデルを訓練しましょう。ブースティング木については、回帰 (BoostedTreesRegressor) と分類 (BoostedTreesClassifier) がサポートされます。目標はクラス – 生存か非生存かを推測することですから、BoostedTreesClassifier を使用します。

# Since data fits into memory, use entire dataset per layer. It will be faster.
# Above one batch is defined as the entire dataset. 
n_batches = 1
est = tf.estimator.BoostedTreesClassifier(feature_columns,
                                          n_batches_per_layer=n_batches)

# The model will stop training once the specified number of trees is built, not 
# based on the number of steps.
est.train(train_input_fn, max_steps=100)

# Eval.
result = est.evaluate(eval_input_fn)
clear_output()
print(pd.Series(result))
accuracy                  0.829545
accuracy_baseline         0.625000
auc                       0.872788
auc_precision_recall      0.857807
average_loss              0.411839
global_step             100.000000
label/mean                0.375000
loss                      0.411839
precision                 0.793478
prediction/mean           0.381942
recall                    0.737374
dtype: float64

今では評価セットからの乗客について予測を行なうために訓練モデルを使用できます。TensorFlow モデルはサンプルのバッチやコレクションの上で同時に予測を行なうために最適化されています。前に、eval_input_fn は評価セット全体を使用して定義されています。

pred_dicts = list(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');

最後に結果の ROC (receiver operating characteristic) もまた見ることができます、これは真陽性率 (= true positive rate) と偽陽性率 (= false positive rate) 間のトレードオフのより良い考えを与えます。

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,);

 

以上



TensorFlow : Guide : Estimators : カスタム Estimator の作成

TensorFlow : Guide : Estimators : カスタム Estimator の作成 (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/14/2018
作成日時 : 03/28/2018

* TensorFlow 1.9 でドキュメント構成が変わりましたので調整しました。
* 本ページは、TensorFlow の本家サイトの Guide – Estimators – Creating Custom Estimators を翻訳した上で適宜、補足説明したものです:

* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

このドキュメントはカスタム Estimator を紹介します。特に、このドキュメントはアイリス問題を解く際に pre-made Estimator DNNClassifier の挙動を模倣するカスタム Estimator をどのように作成するかを示します。アイリス問題の詳細は Pre-Made Estimators の章を見てください。

サンプル・コードをダウンロードしてアクセスするためには次の2つのコマンドを起動してください :

git clone https://github.com/tensorflow/models/
cd models/samples/core/get_started

このドキュメントでは custom_estimator.py を見ていきます。次のコマンドでそれを実行できます :

python custom_estimator.py

もし待ち遠しく感じるのであれば、custom_estimator.py を (同じディレクトリにある) premade_estimator.py と自由に比較・対比してください。

 

Pre-made vs. カスタム

次の図が示すように、pre-made Estimator は tf.estimator.Estimator 基底クラスのサブクラスで、一方でカスタム Estimator は tf.estimator.Estimator のインスタンスです :


Pre-made とカスタム Estimators は総て Estimator です。

Pre-made Estimator は完全に焼けて (= baked) います。けれども時には、Estimator の挙動についてより制御する必要があります。そこがカスタム Estimator が役に立つところです。殆どどのようなことを行なうためにもカスタム Estimator を作成できます。もし貴方が隠れ層にある普通ではない流儀で接続されることを望むのであれば、カスタム Estimator を書きましょう。もし貴方のモデルのために独特な メトリック を計算することを望むのであれば、カスタム Estimator を書きましょう。基本的には、貴方の特定の問題のために Estimator が最適化されることを望むのであれば、カスタム Estimator を書きましょう。

モデル関数 (または model_fn) は ML アルゴリズムを実装します。pre-made Estimator とカスタム Estimator で作業する間の唯一の違いは :

  • pre-made Estimator では、貴方のために誰かが既にモデル関数を書いています。
  • カスタム Estimator では、貴方がモデル関数を書かなければなりません。

貴方のモデル関数は、あらゆる種類の隠れ層とメトリクスを定義して、広い範囲のアルゴリズムを実装できるでしょう。入力関数のように、総てのモデル関数は入力パラメータの標準的なグループを受け取りそして出力値の標準的なグループを返さなければなりません。丁度入力関数が Dataset API を利用できるように、モデル関数は Layers API と Metrics API を利用できます。

アイリス問題をカスタム Estimator でどのように解くかを見てみましょう。簡単な覚書として — ここに模倣しようとしているアイリス・モデルの体系があります :


アイリスの私達の実装は4つの特徴、2つの隠れ層そしてロジット出力層を含みます。

 

入力関数を書く

私達のカスタム Estimator 実装は iris_data.py からの pre-made Estimator 実装 と同じ入力関数を仕様します。すなわち :

def train_input_fn(features, labels, batch_size):
    """An input function for training"""
    # Convert the inputs to a Dataset.
    dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))

    # Shuffle, repeat, and batch the examples.
    dataset = dataset.shuffle(1000).repeat().batch(batch_size)

    # Return the read end of the pipeline.
    return dataset.make_one_shot_iterator().get_next()

この入力関数は(features, labels) ペアのバッチを生成する入力パイプラインを構築します、そこでは特徴は辞書特徴です。

 

特徴カラムを作成する

Premade Estimators特徴カラム の章で詳述されましたように、モデルが各々の特徴をどのように使用するべきかを指定するために貴方のモデルの特徴カラムを定義しなければなりません。pre-made Estimator かカスタム Estimator のいずれかで作業するにせよ、貴方は同じ流儀で特徴カラムを定義します。

次のコードは各々の入力特徴のために単純な numeric_column を作成します、これは入力特徴の値はモデルへの入力として直接使用されるべきであることを示しています :

# Feature columns describe how to use the input.
my_feature_columns = []
for key in train_x.keys():
    my_feature_columns.append(tf.feature_column.numeric_column(key=key))

 

モデル関数を書く

私達が使用するモデル関数は次の呼び出しシグネチャ (= call signature) を持ちます :

def my_model_fn(
   features, # This is batch_features from input_fn
   labels,   # This is batch_labels from input_fn
   mode,     # An instance of tf.estimator.ModeKeys
   params):  # Additional configuration

最初の2つの引数は入力関数から返される特徴とラベルのバッチです ; つまり、features と labels は貴方のモデルが使用するデータへのハンドルです。mode 引数は呼び出し元が training, predicting, あるいは evaluation を要求しているかを示します。

呼び出し元は params を Estimator のコンストラクタに渡すこともできます。コンストラクタに渡された任意の params は model_fn 上に順番に渡されます。custom_estimator.py では次の行群が estimator を作成してモデルを構成するために params を設定します。この構成ステップは Getting Started with TensorFlowtf.estimator.DNNClassifier をどのように構成したかに類似しています。

classifier = tf.estimator.Estimator(
    model_fn=my_model,
    params={
        'feature_columns': my_feature_columns,
        # Two hidden layers of 10 nodes each.
        'hidden_units': [10, 10],
        # The model must choose between 3 classes.
        'n_classes': 3,
    })

典型的なモデル関数を実装するためには、次を行わなければなりません :

  • モデルを定義する。
  • 3つの異なるモードの各々のために追加の計算を指定します :
    • 予測する
    • 評価する
    • 訓練する

 

モデルを定義する

基本的な深層ニューラルネットワーク・モデルは次の3つのセクションを定義しなければなりません :

 

入力層を定義する

model_fn の最初の行は特徴辞書と feature_columns を貴方のモデルのための入力に変換するために tf.feature_column.input_layer を呼び出します、次のようにです :

    # Use `input_layer` to apply the feature columns.
    net = tf.feature_column.input_layer(features, params['feature_columns'])

前の行は貴方の特徴カラムで定義された変換を適用し、モデルの入力層を作成します。

 

隠れ層

もし貴方が深層ニューラルネットワークを作成している場合には、一つまたはそれ以上の隠れ層を定義しなければなりません。Layers API は、convolutional, pooling, と dropout 層を含む、総てのタイプの隠れ層を定義するための関数の豊富なセットを提供します。アイリスのためには、隠れ層を作成するために単に tf.layers.dense を呼び出します、これは params[‘hidden_layers’] で定義された次元を持ちます。dense 層では各ノードは前の層の総てのノードに接続されます。ここに関連するコードがあります :

    # Build the hidden layers, sized according to the 'hidden_units' param.
    for units in params['hidden_units']:
        net = tf.layers.dense(net, units=units, activation=tf.nn.relu)
  • units パラメータは与えられた層の出力ニューロンの数を定義します。
  • activation パラメータは 活性化関数 — この場合は Relu を定義します。

ここでの変数 net はネットワークの現在のトップ層を表します。最初の iteration の間、net は入力層を表します。各ループ iteration で tf.layers.dense は新しい層を作成して、これは、変数 net を使用して、その入力として前の層の出力を取ります。

2つの隠れ層を作成後、私達のネットワークは次のように見えます。単純化のため、図は各層の総てのユニットを表してはいません。

tf.layers.dense は、多数の正則化パラメータを設定するための機能を含む多くの追加の能力を提供することに注意してください。けれども単純化のために、他のパラメータのデフォルト値を単に受容します。

 

出力層

更にもう一度 tf.layers.dense を呼び出すことにより出力層を定義します、今回は活性化関数なしでです :

    # Compute logits (1 per class).
    logits = tf.layers.dense(net, params['n_classes'], activation=None)

ここで、net は最後の隠れ層を表します。従って、層の完全な層は今では次のように接続されています :


最後の隠れ層は出力層に流れ込みます。

出力層を定義するとき、units パラメータは出力の数を指定します。それで、units を params[‘n_classes’] に設定することで、モデルはクラス毎に一つの出力値を生成します。出力ベクトルの各要素は、それぞれアイリスの関連するクラス: セトサ, バージカラー, バージニカのために計算された、スコア、あるいは「ロジット」を含むでしょう。

後で、これらのロジットは tf.nn.softmax 関数により確率へと変換されるでしょう。

 

訓練、評価、そして予測を実装する

モデル関数を作成する最後のステップは予測、評価、そして訓練を実装する分岐コードを書くことです。

モデル関数は誰かが Estimator の train, evaluate, または predict メソッドを呼び出すときいつでも起動されます。モデル関数のためのシグネチャはこのように見えることを思い出してください :

def my_model_fn(
   features, # This is batch_features from input_fn
   labels,   # This is batch_labels from input_fn
   mode,     # An instance of tf.estimator.ModeKeys, see below
   params):  # Additional configuration

3番目の引数, mode に注目しましょう。次のテーブルが示すように、誰かが train, evaluate, または predict を呼び出すとき、Estimator フレームワークは次のように設定された mode パラメータとともに貴方のモデル関数を起動します :

Estimator メソッド

Estimator モード

train()

ModeKeys.TRAIN

evaluate()

ModeKeys.EVAL

predict()

ModeKeys.PREDICT

例えば、classifier と命名したオブジェクトを生成するためにカスタム Estimator をインスタンス化することを仮定します。それから次の呼び出しを行ないます :

classifier = tf.estimator.Estimator(...)
classifier.train(input_fn=lambda: my_input_fn(FILE_TRAIN, True, 500))

それから Estimator フレームワークは貴方のモデル関数を ModeKeys.TRAIN に設定された mode とともに呼び出します。

貴方のモデル関数は3つ総ての mode 値を処理するためのコードを提供しなければなりません。各 mode 値のために、貴方のコードは tf.estimator.EstimatorSpec のインスタンスを返さなければなりません、これは呼び出し元が必要とする情報を含みます。各モードを考察してみましょう。

 

予測する

Estimator の predict メソッドが呼び出されたとき、model_fn は mode = ModeKeys.PREDICT を受け取ります。この場合、モデル関数は予測を含む tf.estimator.EstimatorSpec を返さなければなりません。

モデルは予測を行なう前に訓練されていなければなりません。訓練されたモデルは、Estimator をインスタンス化したときに初期化された model_dir ディレクトリ内でディスク上にストアされます。

このモデルのために予測を生成するコードは次のようなものです :

# Compute predictions.
predicted_classes = tf.argmax(logits, 1)
if mode == tf.estimator.ModeKeys.PREDICT:
    predictions = {
        'class_ids': predicted_classes[:, tf.newaxis],
        'probabilities': tf.nn.softmax(logits),
        'logits': logits,
    }
    return tf.estimator.EstimatorSpec(mode, predictions=predictions)

prediction 辞書は prediction モードで実行するとき貴方のモデルが返すもの総てを含みます。

predictions は次の3つのキー/値ペアを保持します :

  • class_ids はこのサンプルに対するもっとも尤度の高い種のモデルの予測を表わすクラス id (0, 1, または 2) を保持します。
  • probabilities は3つの確率 (このサンプルでは、0.02, 0.95, と 0.03) を保持します。
  • logits は生のロジット値 (このサンプルでは、-1.3, 2.6, と -0.9) を保持します。

その辞書を tf.estimator.EstimatorSpec の predictions パラメータを通して呼び出し元に返します。Estimator の predict メソッドはこれらの辞書を生成します。

 

損失を計算する

訓練評価 の両者のためにモデルの損失を計算する必要があります。これは最適化される 目的 (= objective) です。

tf.losses.sparse_softmax_cross_entropy を呼び出すことにより損失を計算できます。この関数により返される値は最も低く、およそ 0 で、(インデックス・ラベルにおける) 正しいクラスの確率は 1.0 近くです。正しいクラスの確率が減少するとき返される損失値は徐々により大きくなります。

この関数はバッチ全体に渡る平均を返します。

# Compute loss.
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)

 

評価する

Estimator の evaluate メソッドが呼び出されたとき、model_fn は mode = ModeKeys.EVAL を受け取ります。この場合、モデル関数は、モデルの損失とオプションで一つまたはそれ以上のメトリクスを含む tf.estimator.EstimatorSpec を返さなければなりません。

メトリクスを返すのははオプションですが、多くのカスタム Estimator は少なくとも一つのメトリックを返します。TensorFlow は一般的なメトリクスを計算するための Metrics モジュール tf.metrics を提供します。簡潔さのために、私達は accuracy を返すだけです。tf.metrics.accuracy 関数は私達の予測を真の値に対して、つまり、入力関数により提供されるラベルに対して比較します。tf.metrics.accuracy 関数はラベルと予測が同じ shape を持つことを要求します。ここに tf.metrics.accuracy への呼び出しがあります :

# Compute evaluation metrics.
accuracy = tf.metrics.accuracy(labels=labels,
                               predictions=predicted_classes,
                               name='acc_op')

評価のために返される EstimatorSpec は典型的には次の情報を含みます :

  • loss, これはモデルの損失です。
  • eval_metric_ops、これはオプションのメトリクスの辞書です。

さて、ただ一つのメトリックを含む辞書を作成します。他のメトリクスを計算する場合には、同じ辞書に追加のキー/値ペアとしてそれらを追加します。それから、tf.estimator.EstimatorSpec の eval_metric_ops 引数に辞書を渡します。ここにコードがあります :

metrics = {'accuracy': accuracy}
tf.summary.scalar('accuracy', accuracy[1])

if mode == tf.estimator.ModeKeys.EVAL:
    return tf.estimator.EstimatorSpec(
        mode, loss=loss, eval_metric_ops=metrics)

tf.summary.scalar は TRAIN と EVAL モードの両者において accuracy を TensorBoard で利用可能にします。(More on this later).

 

訓練する

Estimator の train メソッドが呼び出されるとき、model_fn は mode = ModeKeys.TRAIN で呼び出されます。この場合、モデル関数は損失と訓練演算を含む EstimatorSpec を返さなければなりません。

訓練演算の構築は optimizer を必要とするでしょう。私達は tf.train.AdagradOptimizer を使用します、何故ならばデフォルトで Adagrad をまた使用している DNNClassifier を模倣しているからです。tf.train パッケージは多くの他の optimizer を提供します — それらで自由に実験してください。

ここに optimizer を構築するコードがあります :

optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)

次に、先に計算した損失上で optimizer の minimize メソッドを使用して訓練演算を構築します。

minimize メソッドはまた global_step パラメータを取ります。TensorFlow は (訓練実行をいつ終わらせるかを知るために) 処理された訓練ステップ数をカウントするためにこのパラメータを使用します。更に、global_step は TensorBoard グラフが正しく動作するために欠くことができません。単純に tf.train.get_global_step を呼び出して結果を minimize の global_step 引数に渡します。

ここにモデルを訓練するためのコードがあります :

train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())

訓練のために返される EstimatorSpec は次のフィールド集合を持たなければなりません :

  • loss, これは損失関数の値を含みます。
  • train_op, これは訓練ステップを実行します。

ここに EstimatorSpec を呼び出すコードがあります :

return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)

モデル関数は今では完成しています。

 

カスタム Estimator

Estimator 基底クラスを通してカスタム Estimator を次のようにインスタンス化します :

    # Build 2 hidden layer DNN with 10, 10 units respectively.
    classifier = tf.estimator.Estimator(
        model_fn=my_model,
        params={
            'feature_columns': my_feature_columns,
            # Two hidden layers of 10 nodes each.
            'hidden_units': [10, 10],
            # The model must choose between 3 classes.
            'n_classes': 3,
        })

ここで params 辞書は DNNClassifier の key-word 引数と同じ目的に役立ちます ; つまり、params 辞書は model_fn のコードを変更することなしに貴方の Estimator を構成することを可能にします。

私達の Estimator を使用して訓練、評価して予測を生成するための残りのコードは Premade Estimators の章と同様です。
例えば、次の行はモデルを訓練します :

# Train the Model.
classifier.train(
    input_fn=lambda:iris_data.train_input_fn(train_x, train_y, args.batch_size),
    steps=args.train_steps)

 

TensorBoard

貴方のカスタム Estimator のための訓練結果を TensorBoard で見ることができます。このレポートを見るためには、次のように TensorBoard をコマンドラインから開始します :

# Replace PATH with the actual path passed as model_dir
tensorboard --logdir=PATH

それから、http://localhost:6006 にブラウズすることで TensorBoard をオープンします。

総ての pre-made Estimators は TensorBoard への多くの情報を自動的にロギングします。けれども、カスタム Estimator では、TensorBoard は一つのデフォルト・ログと貴方が TensorBoard にロギングするように明示的に伝えた情報を提供するだけです。貴方が単に作成しただけのカスタム Estimator については、TensorBoard は次を生成します :


TensorBoard は3つのグラフを表示します。

簡単に言えば、3つのグラフが貴方に伝えるものがここにあります :

  • global_step/sec: パフォーマンス・インジケータで、モデルが訓練されるときにどれだけのバッチが毎秒処理されたか (勾配更新) を示します。
  • loss: レポートされる損失です。
  • accuracy: 精度は次の2行により記録されます :
  • eval_metric_ops={‘my_accuracy’: accuracy}), 評価の間。
  • tf.summary.scalar(‘accuracy’, accuracy[1]), 訓練の間。

これらの tensorboard グラフは、貴方の optimizer の minimize メソッドに global_step を渡すことが重要である多くの理由の一つです。それなしではモデルはこれらのグラフのために x-軸を記録できません。

my_accuracy と loss グラフにおいて以下に注意してください :

  • オレンジ色の線は訓練を表します。
  • 青色のドットは評価を表します。

訓練の間、要約 (オレンジの線) はバッチが処理されるにつれて定期的に記録され、それはそれが何故 x-軸範囲に渡るグラフになるかです。

対照的に、評価は evaluate への各呼び出しのためにグラフ上の単一ポイントを生成します。このポイントは evaluation 呼び出し全体に渡る平均を含みます。これはグラフ上で幅を持ちません、何故ならばそれは (単一のチェックポイントから) 特定の訓練ステップにおいてモデル状態から全体的に評価されるからです。

下の図で示されるように、レポーティングを見ることができ、また左側のコントロールを使用して選択的に無効/有効にすることができます。

 

以上



TensorFlow : Guide : 低位 API : セーブとリストア

TensorFlow : Guide : 低位 API : セーブとリストア (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/14/2018
作成日時 : 09/19/2017

* 本ページは、TensorFlow 本家サイトの Guide – Low Level APIs – Saving and Restoring を翻訳した上で
適宜、補足説明したものです:

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

 

本文

このドキュメントは 変数 とモデルをどのようにセーブしてリストアするするかについて説明します。

 

変数のセーブとリストア

TensorFlow 変数は貴方のプログラムで操作される共有され永続性のある状態を表わすための最善の方法です (詳細は 変数 を見てください)。このセクションは変数をどのようにセーブしてリストアするかを説明します。Estimator は変数を (model_dir に) 自動的にセーブしてリストアすることに注意してください。

tf.train.Saver クラスはモデルをセーブしてリストアするためのメソッドを提供します。tf.train.Saver コンストラクタはグラフの変数の総て、または指定されたリストのために save と restore ops をグラフに追加します。Saver オブジェクトは、読み書きするチェックポイントファイルのためのパスを指定し、これらの ops を実行するためのメソッドを提供します。

saver は貴方のモデルで既に定義された変数総てをリストアするでしょう。もしそのグラフをどのように構築したのか知らないでモデルをロードする場合は (例えば、モデルをロードする一般的なプログラムを書いている場合)、このドキュメントの後方の モデルのセーブとリストアの概要 セクションを読んでください。

TensorFlow は変数をバイナリ・チェックポイント・ファイルにセーブします、これは大雑把に言えば、変数名をテンソル値にマップします。

変数をセーブする

tf.train.Saver() でモデルの変数総てを管理する Saver を作成します。例えば、次のスニペットは変数をチェックポイント・ファイルにセーブする tf.train.Saver.save メソッドをどのように呼び出すかを示します :

# Create some variables.
v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer)
v2 = tf.get_variable("v2", shape=[5], initializer = tf.zeros_initializer)

inc_v1 = v1.assign(v1+1)
dec_v2 = v2.assign(v2-1)

# Add an op to initialize the variables.
init_op = tf.global_variables_initializer()

# Add ops to save and restore all the variables.
saver = tf.train.Saver()

# Later, launch the model, initialize the variables, do some work, and save the
# variables to disk.
with tf.Session() as sess:
  sess.run(init_op)
  # Do some work with the model.
  inc_v1.op.run()
  dec_v2.op.run()
  # Save the variables to disk.
  save_path = saver.save(sess, "/tmp/model.ckpt")
  print("Model saved in file: %s" % save_path)

変数をリストアする

tf.train.Saver オブジェクトは変数をチェックポイント・ファイルにセーブするだけでなく、変数をリストアもします。ファイルから変数をリストアするときそれらを予め初期化する必要はないことに注意してください。例えば、次のスニペットはチェックポイント・ファイルから変数をリストアするために tf.train.Saver.restore メソッドをどのように呼び出すかを示します :

tf.reset_default_graph()

# Create some variables.
v1 = tf.get_variable("v1", shape=[3])
v2 = tf.get_variable("v2", shape=[5])

# Add ops to save and restore all the variables.
saver = tf.train.Saver()

# Later, launch the model, use the saver to restore variables from disk, and
# do some work with the model.
with tf.Session() as sess:
  # Restore variables from disk.
  saver.restore(sess, "/tmp/model.ckpt")
  print("Model restored.")
  # Check the values of the variables
  print("v1 : %s" % v1.eval())
  print("v2 : %s" % v2.eval())

どの変数をセーブしてリストアするかを選択する

tf.train.Saver() にどのような引数も渡さない場合には、saver はグラフの総ての変数を処理します。変数が作成されたときに渡された名前に基づいて各変数はセーブされます。

チェックポイント・ファイルの変数に対して名前を明示的に指定するのは時々有用です。例えば、”weights” という名前の変数を持つ訓練されたモデルを持ち、その値を “params” という名前の変数にリストアすることを望むかもしれません。

モデルで使用される変数のサブセットだけをセーブまたはリストアすることも時々有用です。例えば、貴方は 5 層のニューラルネットを訓練したかもしれません、そして今、5つの訓練された層の既存の重みを再利用した 6 層で新しいモデルを訓練することを望みます。最初の 5 層だけの重みをリストアするために saver を使用できます。

次のいずれかを tf.train.Saver() コンストラクタに渡すことによりセーブまたはロードするために名前と変数を簡単に指定してできます :

  • 変数のリスト (それらはそれら自身の名前の下にストアされます)。
  • Python 辞書、そこではキーは使用するための名前で値は管理するための変数です。

先に示した save/resotre サンプルからの続きです :

tf.reset_default_graph()
# Create some variables.
v1 = tf.get_variable("v1", [3], initializer = tf.zeros_initializer)
v2 = tf.get_variable("v2", [5], initializer = tf.zeros_initializer)

# Add ops to save and restore only `v2` using the name "v2"
saver = tf.train.Saver({"v2": v2})

# Use the saver object normally after that.
with tf.Session() as sess:
  # Initialize v1 since the saver will not.
  v1.initializer.run()
  saver.restore(sess, "/tmp/model.ckpt")

  print("v1 : %s" % v1.eval())
  print("v2 : %s" % v2.eval())

Notes:

  • モデル変数の異なるサブセットをセーブしてリストアする必要がある場合には望むだけの数の Saver オブジェクトを作成することができます。同じ変数は複数の saver オブジェクトでリストされることができます ; その値は Saver.restore() メソッドが実行されるときに変更されるだけです。
  • セッション開始時にモデル変数のサブセットだけをリストアする場合、他の変数のために初期化 op を実行しなければなりません。更なる情報のためには tf.variables_initializer を見てください。
  • チェックポイントの変数を調べるためには、inspect_checkpoint ライブラリ、特に print_tensors_in_checkpoint_file 関数を使用できます。
  • デフォルトでは、Saver は各変数のために tf.Variable.name プロパティの値を使用できます。けれども、Saver オブジェクトを作成するとき、チェックポイント・ファイルの変数のためにオプションで名前を選択しても良いです。

 

モデルのセーブとリストアの概要

変数、グラフ、そしてグラフのメタデータをセーブそしてロードすることを望むとき — 基本的に、貴方のモデルをセーブまたはリストアすることを望むとき — SavedModel を使用することを推奨します。

SavedModel は言語ニュートラルで、復旧可能で、密封された (= hermetic) シリアライゼーション形式です。SavedModel は高位システムとツールに TensorFlow モデルを生成し、消費し (= consume)、そして変換することを可能にします。TensorFlow は、tf.saved_model API, Estimator API そして CLI を含む、SavedModel と相互作用するための幾つかのメカニズムを提供します。

 

SavedModel を構築してロードするための API

このセクションは SavedModel を構築してロードするための API にフォーカスを当てます、特に低位 TensorFlow API を使用するときです。

SavedModel を構築する

SavedModel builder の Python 実装を提供します。SavedModelBuilder クラスは複数の MetaGraphDef をセーブするための機能を提供します。MetaGraph はデータフロー・グラフ、加えてそれに関連する変数、アセット、そして signature です。MetaGraphDef は MetaGraph のプロトコル・バッファ表現です。signature はグラフへの入力とグラフからの出力のセットです。

アセットがディスクにセーブされて書き出されるかコピーされる必要がある場合には、最初の MetaGraphDef が追加されたときにそれらは提供されます。複数の MetaGraphDef が同じ名前のアセットに関連付けられる場合には、最初のバージョンだけが保持されます。

SavedModel に追加された各 MetaGraphDef はユーザ指定のタグでアノテートされなければなりません。タグは、変数とアセットの共有されたセットと一緒に、ロードしてリストアするための特定の MetaGraphDef を識別するための方法を提供します。これらのタグは典型的にはその機能性 (例えば、サービングまたは訓練)、そしてオプションでハードウェア仕様的な局面 (例えば、GPU) で MetaGraphDef をアノテートします。

例えば、次のコードは SavedModel を構築するために SavedModelBuilder を使用する典型的な方法を提案します :

export_dir = ...
...
builder = tf.saved_model_builder.SavedModelBuilder(export_dir)
with tf.Session(graph=tf.Graph()) as sess:
  ...
  builder.add_meta_graph_and_variables(sess,
                                       [tag_constants.TRAINING],
                                       signature_def_map=foo_signatures,
                                       assets_collection=foo_assets)
...
# Add a second MetaGraphDef for inference.
with tf.Session(graph=tf.Graph()) as sess:
  ...
  builder.add_meta_graph([tag_constants.SERVING])
...
builder.save()

Python で SavedModel をロードする

SavedModel loader の Python バージョンは SavedModel のためのロードとリストアの性能を提供します。ロード演算は次の情報を必要とします :

  • セッション、そこでグラフ定義と変数をリストアします。
  • タグ、ロードする MegaGraphDef を識別するために使用されます。
  • SavedModel の位置 (ディレクトリ)。

ロード時、特定の MetaGraphDef の一部として供給される変数、アセット、そして signature のサブセットは
供給されるセッション内にリストアされます。

export_dir = ...
...
with tf.Session(graph=tf.Graph()) as sess:
  tf.saved_model.loader.load(sess, [tag_constants.TRAINING], export_dir)
  ...

C++ で SavedModel をロードする

SavedModel loader の C++ バージョンは SessionOptions と RunOptions を許可し、パスから SavedModel をロードするための API を提供します。ロードされるグラフに関連付けられたタグを指定しなければなりません。SavedModel のロードされたバージョンは SavedModelBundle として参照されて MetaGraphDef とそれが内部にロードされるセッションを含みます。

const string export_dir = ...
SavedModelBundle bundle;
...
LoadSavedModel(session_options, run_options, export_dir, {kSavedModelTagTrain},
               &bundle);

標準的な constants

SavedModel は様々なユースケースのために TensorFlow グラフを構築してロードする柔軟性を提供します。最も一般的なユースケースのために、SavedModel の API は Python と C++ で constants のセットを提供します、これはツールの一貫性に渡り再利用して共有することを容易にします。

標準的な MetaGraphDef タグ

SavedModel にセーブされた MetaGraphDef を一意に識別するためにタグのセットを使用するかもしれません。一般に使用されるタグのサブセットは以下で指定されます :

標準的な SignatureDef constants

SignatureDef はグラフによりサポートされる計算の signature を定義するプロトコル・バッファです。一般的に使用される入力キー、出力キー、そしてメソッド名は以下で定義されます :

 

Estimator で SavedModel を使用する

Estimator モデルを訓練した後、リクエストを取り結果を返すような、モデルからのサービスを作成することを望むかもしれません、そのようなサービスを貴方のマシン上でローカルに実行したりクラウドでそれをスケーラブルにデプロイすることができます。

サービングのための訓練された Estimator を用意するためには、標準的な SavedModel フォーマットでそれをエクスポートしなければなりません。このセクションはどのように以下を行なうかを説明します :

  • 出力ノードとサーブ可能な相当する API を指定する(分類、回帰、または予測する)。
  • 貴方のモデルを SavedModel 形式にエクスポートする。
  • ローカル・サーバからモデルをサーブして予測を要求する。

サービング入力を準備する

訓練中、input_fn() はデータを摂取してそれをモデルによる使用のために準備します。サービス提供時には、同様に、serving_input_receiver_fn() は推論リクエストを受け取りそれらをモデルのために準備します。この関数は次の目的を持ちます :

  • グラフに placeholder を追加する、これにはサービング・システムが推論リクエストを供給します。
  • データを入力フォーマットからモデルにより期待される特徴テンソルに変換するために必要な、任意の追加の ops を追加する

関数は tf.estimator.export.ServingInputReceiver オブジェクトを返します、これは placeholder と結果の特徴テンソルを一緒にまとめます。

典型的なパターンは推論リクエストはシリアライズ化された tf.Examples の形式で到着します、そのため serving_input_receiver_fn() はそれらを受け取るために単一の文字列 placeholder を作成します。そして serving_input_receiver_fn() はまたグラフに tf.parse_example op を追加することにより tf.Examples を構文解析する責任も負います。

そのような serving_input_receiver_fn() を書くとき、解析器 (= parser) にどんな特徴名を期待するかそしてどのようにそれらをテンソルにマップするかを教えてるために tf.parse_example に解析仕様 (= parsing specification) を渡さなければなりません。解析仕様は特徴名から tf.FixedLenFeature, tf.VarLenFeature, と tf.SparseFeature への辞書の形式を取ります。この解析仕様はどのようなラベルあるいは重みカラムも含むべきではないことに注意してください、何故ならばそれらはサービング時には利用可能ではないからです — 訓練時に input_fn() で使用される解析使用とは対照的です。

組み合わせて、そして :

feature_spec = {'foo': tf.FixedLenFeature(...),
                'bar': tf.VarLenFeature(...)}

def serving_input_receiver_fn():
  """An input receiver that expects a serialized tf.Example."""
  serialized_tf_example = tf.placeholder(dtype=tf.string,
                                         shape=[default_batch_size],
                                         name='input_example_tensor')
  receiver_tensors = {'examples': serialized_tf_example}
  features = tf.parse_example(serialized_tf_example, feature_spec)
  return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)

tf.estimator.export.build_parsing_serving_input_receiver_fn ユティリティ関数は一般的なケースのためにその入力レシーバーを提供します。

Note: ローカルサーバで Predict API を使用してサーブされるモデルを訓練するとき、解析ステップは必要ありません、何故ならばモデルは生の (= raw) 特徴データを受け取るからです。

解析や他の入力処理を必要としない場合でさえも — つまり、もしサービング・システムが特徴テンソルを直接供給する場合でも — 依然として serving_input_receiver_fn() を提供しなければなりません、これは特徴テンソルのための placeholder を作成してそれらを通り抜けさせます。tf.estimator.export.build_raw_serving_input_receiver_fn ユティリティはこれのために提供します。

もしこれらのユティリティが貴方のニーズに合わない場合には、貴方は貴方自身の serving_input_receiver_fn() を自由に書くことができます。これが必要となるかもしれない一つのケースは貴方の訓練 input_fn() がサービング時に要約 (recapitulated) されなければならない何某かの前処理ロジックを組み入れる場合です。訓練-サービングの歪みのリスクを軽減するためには、そのような処理を、input_fn() and serving_input_receiver_fn() の両者から呼び出される関数内にカプセル化することを推奨します。

serving_input_receiver_fn() はまた signature の入力部分を決定することに注意してください。つまり、serving_input_receiver_fn() を書くとき、どのような signature を期待してそれらを貴方のモデルの期待する入力にどのようにマップするかを解析器 (= parser) に知らせなければなりません。対照的に、signature の出力部分はモデルにより決定されます。

エクスポートを遂行する

訓練された Estimator をエクスポートするためには、tf.estimator.Estimator.export_savedmodel を export ベース・パスと serving_input_receiver_fn と一緒に呼び出します。

estimator.export_savedmodel(export_dir_base, serving_input_receiver_fn)

このメソッドは、特徴テンソルを得るために最初に serving_input_receiver_fn() を呼び出し、そしてそれらの特徴に基づくモデル・グラフを生成するためにこの Estimator の model_fn() を呼び出すことにより、新しいグラフを構築します。それはフレッシュなセッションを開始し、そしてデフォルトでは、最も最近のチェックポイントをそれにリストアします。(必要であれば、異なるチェックポイントが渡されるかもしれません。)
最終的にそれは与えられた export_dir_base の下にタイムスタンプつきの export ディレクトリを作成し (i.e., export_dir_base/) 、そしてこのセッションからセーブされた単一の MetaGraphDef を含む SavedModel をその内に書きます。

Note: 古い exports をガベージコレクトするのは貴方の責任です。さもなければ、続く export は export_dir_base 下に蓄積されるでしょう。

カスタム・モデルの出力を指定する

カスタム model_fn を書くとき、tf.estimator.EstimatorSpec の export_outputs 要素を戻り値として populate しなければなりません。これは {name: output} の辞書で、エクスポートされてサービングの間に使用される出力 signature を記述します。

単一の予測を行なう通常のケースでは、この辞書は一つの要素を含み、名前は重要ではありません。マルチ・ヘッドのモデルでは、各ヘッドはこの辞書のエントリとして表わされます。名前は貴方の選択の文字列でサービング時に特定のヘッドをリクエストするために使用できます。

各出力値は tf.estimator.export.ClassificationOutput, tf.estimator.export.RegressionOutput, または tf.estimator.export.PredictOutput のような ExportOutput オブジェクトでなければなりません。

これらの出力型は率直に TensorFlow Serving API にマップされてどのリクエスト型が重視されるかを決定します。

Note: マルチ・ヘッドなケースでは、SignatureDef は、model_fn から返される、同じキーで命名された、export_outputs 辞書の各要素のために生成されるでしょう。これらの SignatureDefs は、相当する ExportOutput エントリで定められているように、それらの出力の点のみ異なります。入力は常に serving_input_receiver_fn により提供されるものです。推論リクエストは名前でヘッドを指定するかもしれません。一つのヘッドは、推論リクエストが一つを指定していないときにどの SignatureDef がサーブされるかを示す signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY を使用して命名されなければなりません。

エクスポートされたモデルをローカルでサーブする

ローカル・デプロイメントのためには、TensorFlow Serving を使用して貴方のモデルをサーブできます、これは SavedModel をロードしてそれを gRPC サービスとして公開するオープンソース・プロジェクトです。

最初に、TensorFlow Serving をインストール します。

それから、$export_dir_base を上でエクスポートした SavedModel へのパスで置き換えてローカル model server を構築して実行します :

bazel build //tensorflow_serving/model_servers:tensorflow_model_server
bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --model_base_path=$export_dir_base

 
今ではポート 9000 上の gRPC 経由で推論リクエストのためにリスンするサーバを持ちます!

ローカルサーバから予測をリクエストする

サーバは PredictionService gRPC API サービス定義に従って gRPC リクエストに応答します。(ネストされたプロトコル・バッファは様々な 近接したファイル で定義されています。)

API サービス定義から、gRPC フレームワークは API へのリモートアクセスを提供するために様々な言語のクライアント・ライブラリを生成します。Bazel ビルドツールを使用したプロジェクトでは、これらのライブラリは自動的にビルドされて (例として Python を使用して) これらのように依存を通して提供されます :

  deps = [
    "//tensorflow_serving/apis:classification_proto_py_pb2",
    "//tensorflow_serving/apis:regression_proto_py_pb2",
    "//tensorflow_serving/apis:predict_proto_py_pb2",
    "//tensorflow_serving/apis:prediction_service_proto_py_pb2"
  ]

それから Python クライアント・コードはこのようにしてライブラリをインポートできます :

from tensorflow_serving.apis import classification_pb2
from tensorflow_serving.apis import regression_pb2
from tensorflow_serving.apis import predict_pb2
from tensorflow_serving.apis import prediction_service_pb2

Note: prediction_service_pb2 はサービス全体を定義していますので常に必要です。けれども典型的なクライアントは行なわれるリクエストの型に依存して、classification_pb2, regression_pb2, そして predict_pb2 の一つだけを必要とするでしょう。

 
そして gRPC リクエストの送信はリクエスト・データを含むプロトコルバッファを集めてそれをサービス・スタブに渡すことによって成されます。リクエスト・プロトコルバッファがどのように空で作成されてそして generated protocol buffer API を通して populate されるかに注意してください。

from grpc.beta import implementations

channel = implementations.insecure_channel(host, int(port))
stub = prediction_service_pb2.beta_create_PredictionService_stub(channel)

request = classification_pb2.ClassificationRequest()
example = request.input.example_list.examples.add()
example.features.feature['x'].float_list.value.extend(image[0].astype(float))

result = stub.Classify(request, 10.0)  # 10 secs timeout

このサンプルで返される結果は ClassificationResponse プロトコルバッファです。

これはスケルトンのサンプルです ; 更なる詳細のためには TensorFlow Serving 文書と サンプル を見てください。

Note: ClassificationRequest と RegressionRequest は tensorflow.serving.Input プロトコルバッファを含み、これは tensorflow.Example プロトコルバッファのリストを順番に含みます。PredictRequest は対照的に、特徴名から TensorProto を通してエンコードされる値へのマッピングを含みます。相応して: Classify と Regress API を使用するとき、TensorFlow Serving はシリアライズ化された tf.Examples をグラフに供給しますので、serving_input_receiver_fn() は tf.parse_example() Op を含むべきです。一般的な Predict API を使用するときは、けれども、TensorFlow Serving は生の特徴データをグラフに供給しますので、serving_input_receiver_fn() の通り抜けが使用さえるべきです。

 

SavedModel を探求して実行する CLI

SavedModel を探求して実行するために SavedModel コマンドライン・インターフェイス (CLI, Command Line Interface) を使用することができます。例えば、モデルの SignatureDefs を探求するために CLI を使用できます。CLI は入力 テンソルの dtype と shape がモデルに適合しているかを迅速に確かめることを可能にします。更に、貴方のモデルをテストすることを望むのであれば、様々な形式 (例えば、Python 式) のサンプル入力を渡してそれから出力を取得することでサニティ・チェックを行なうために CLI を使用できます。

SavedModel CLI をインストールする

大まかに言えば、TensorFlow を次の2つの方法のどちらかでインストールできます :

  • 事前ビルドされた TensorFlow バイナリをインストールする。
  • ソースコードから TensorFlow をビルドする。

もし事前ビルドされた TensorFlow ライブラリを通して TensorFlow をインストールしたのであれば、SavedModel CLI は貴方のシステムにパス名 bin\saved_model_cli で既にインストールされています。

もしソースコードから TensorFlow をビルドした場合には、saved_model_cli をビルドするために次の追加のコマンドを実行しなければなりません :

$ bazel build tensorflow/python/tools:saved_model_cli

コマンドの概要

SavedModel CLI は SavedModel の MetaGraphDef 上の次の2つのコマンドをサポートします :

  • show, これは SavedModel の MetaGraphDef 上の計算を表示します。
  • run, これは MetaGraphDef 上の計算を実行します。

show コマンド

SavedModel は、タグセットで識別される一つまたはそれ以上の MetaGraphDefs を含みます。モデルをサーブするために、どのような種類の SignatureDefs が各モデルにあり、そしてそれらの入力と出力が何であるか知りたいと思うかもしれません。show コマンドは SavedModel の内容を階層順で調べることを許します。ここに構文があります :

usage: saved_model_cli show [-h] --dir DIR [--all]
[--tag_set TAG_SET] [--signature_def SIGNATURE_DEF_KEY]

例えば、次のコマンドは SavedModel の総ての利用可能な MetaGraphDef タグセットを表示します :

$ saved_model_cli show --dir /tmp/saved_model_dir
The given SavedModel contains the following tag-sets:
serve
serve, gpu

次のコマンドは MetaGraphDef の総ての利用可能な SignatureDef キーを表示します :

$ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve
The given SavedModel `MetaGraphDef` contains `SignatureDefs` with the
following keys:
SignatureDef key: "classify_x2_to_y3"
SignatureDef key: "classify_x_to_y"
SignatureDef key: "regress_x2_to_y3"
SignatureDef key: "regress_x_to_y"
SignatureDef key: "regress_x_to_y2"
SignatureDef key: "serving_default"

MetaGraphDef がタグセットの複数のタグを持つ場合には、各タグがカンマ区切りの、総てのタグを指定しなければなりません。例えば :

$ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve,gpu

特定の SignatureDef のための総ての入力と出力 TensorInfo を表示するためには、signature_def オプションに SignatureDef キーを渡します。これは、計算グラフを後で実行するために入力テンソルのテンソル・キー値、dtype と shape を知りたいときに非常に有用です。例えば :

$ saved_model_cli show --dir \
/tmp/saved_model_dir --tag_set serve --signature_def serving_default
The given SavedModel SignatureDef contains the following input(s):
inputs['x'] tensor_info:
    dtype: DT_FLOAT
    shape: (-1, 1)
    name: x:0
The given SavedModel SignatureDef contains the following output(s):
outputs['y'] tensor_info:
    dtype: DT_FLOAT
    shape: (-1, 1)
    name: y:0
Method name is: tensorflow/serving/predict

SavedModel で利用可能な総ての情報を表示するためには、–all オプションを使用します。例えば :

$ saved_model_cli show --dir /tmp/saved_model_dir --all
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs:

signature_def['classify_x2_to_y3']:
The given SavedModel SignatureDef contains the following input(s):
inputs['inputs'] tensor_info:
    dtype: DT_FLOAT
    shape: (-1, 1)
    name: x2:0
The given SavedModel SignatureDef contains the following output(s):
outputs['scores'] tensor_info:
    dtype: DT_FLOAT
    shape: (-1, 1)
    name: y3:0
Method name is: tensorflow/serving/classify

...

signature_def['serving_default']:
The given SavedModel SignatureDef contains the following input(s):
inputs['x'] tensor_info:
    dtype: DT_FLOAT
    shape: (-1, 1)
    name: x:0
The given SavedModel SignatureDef contains the following output(s):
outputs['y'] tensor_info:
    dtype: DT_FLOAT
    shape: (-1, 1)
    name: y:0
Method name is: tensorflow/serving/predict

run コマンド

グラフ計算を実行するためには run コマンドを起動します、入力を渡してそれから出力を表示します (そしてオプションでセーブ)。ここに構文があります :

usage: saved_model_cli run [-h] --dir DIR --tag_set TAG_SET --signature_def
                           SIGNATURE_DEF_KEY [--inputs INPUTS]
                           [--input_exprs INPUT_EXPRS] [--outdir OUTDIR]
                           [--overwrite] [--tf_debug]

run コマンドは入力をモデルに渡す次の2つの方法を提供します :

  • –inputs オプションはファイルの numpy ndarray を渡すことを可能にします。
  • –input_exprs オプションは Python 式を渡すことを可能にします。

–inputs

ファイルで入力データを渡すためには、–inputs オプションを指定します、これは次の一般的な形式を取ります :

--inputs <INPUTS>

ここで INPUTS は次の形式のいずれかです :

  • <input_key>=<filename>

  • <input_key>=<filename>[<variable_name>]

複数の INPUTS を渡しても良いです。複数の inputs を渡す場合には、INPUTS の各々を分割するためにセミコロンを使用してください。

saved_model_cli はファイル名をロードするために numpy.load を使用します。ファイル名は次の形式のどれでも良いです :

  • .npy
  • .npz
  • pickle 形式

.npy ファイルは常に numpy ndarray を含みます。従って、.npy ファイルからロードするときは、内容は指定された入力テンソルに直接的に割り当てられます。もし variable_name をその .npy ファイルで指定した場合には、variable_name は無視されて警告が発行されるでしょう。

.npz (zip) ファイルからロードするときは、入力テンソル・キーに対してロードするために zip ファイル内の変数を識別するための variable_name をオプションで指定しても良いです。variable_name を指定しない場合には、SavedModel CLI は zip ファイルに一つのファイルだけが含まれていることを確認して指定された入力テンソル・キーのためにそれをロードします。

pickle ファイルからロードするときは、角括弧 (= square brackets) で variable_name が指定されない場合、pickle ファイル内が何であれそれが指定された入力テンソル・キーに渡されます。そうでなければ、SavedModel CLI は辞書が pickle ファイルにストアされていると仮定して variable_name に相当する値が使用されるでしょう。

–inputs_exprs

Python 式を通して入力を渡す場合には、–input_exprs オプションを指定します。これは、転がっているデータファイルを持たないが、しかし依然として (モデルの SignatureDefs の dtype と shape に適合する) 何某かの単純な入力でモデルをサニティ・チェックすることを望むときのために有用です。例えば :

`input_key=[[1], [2], [3]]`

Python 式に加えて、numpy 関数を渡しても良いです。例えば :

input_key=np.ones((32, 32, 3))

(numpy モジュールは np として既に利用可能であることに注意してください。)

出力をセーブする

デフォルトでは、SavedModel CLI は出力を stdout に書きます。もしディレクトリが –outdir オプションで渡された場合は、出力は出力テンソル・キーにちなんで命名された npy ファイルとして与えられたディレクトリ下にセーブされます。

既存の出力ファイルに上書きするためには –overwrite を使用します。

TensorFlow デバッガー (tfdbg) 統合

–tf_debug オプションがセットされた場合は、SavedModel CLI は TensorFlow デバッガー (tfdbg) を使用して SavedModel を実行する間、中間テンソルと実行時グラフまたはサブグラフを監視します。

完全なサンプル

以下を仮定した場合 :

  • モデルは単に x1 と x2 を加算して出力 y を得ます。
  • モデルの総てのテンソルは shape (-1, 1) を持ちます。
  • 2つの npy ファイルを持ちます :
  • /tmp/my_data1.npy, これは numpy ndarray [[1], [2], [3]] を含みます。
  • /tmp/my_data2.npy, これは他の numpy ndarray [[0.5], [0.5], [0.5]] を含みます。

出力 y を得るためのモデルを通してこれら2つの npy ファイルを実行するには、 次のコマンドを発行します ;

$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \
--signature_def x1_x2_to_y --inputs x1=/tmp/my_data1.npy;x2=/tmp/my_data2.npy \
--outdir /tmp/out
Result for output key y:
[[ 1.5]
 [ 2.5]
 [ 3.5]]

先のサンプルを少し変更しましょう。今度は、2つの .npy ファイルの代わりに、今は .npz ファイルと pickle ファイルを持ちます。更に、既存の出力ファイルに上書きしたいとします。ここにコマンドがあります :

$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \
--signature_def x1_x2_to_y \
--inputs x1=/tmp/my_data1.npz[x];x2=/tmp/my_data2.pkl --outdir /tmp/out \
--overwrite
Result for output key y:
[[ 1.5]
 [ 2.5]
 [ 3.5]]

入力ファイルの代わりに python 式を指定しても良いです。例えば、次のコマンドは入力 x2 を Python 式で置き換えます :

$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \
--signature_def x1_x2_to_y --inputs x1=/tmp/my_data1.npz[x] \
--input_exprs 'x2=np.ones((3,1))'
Result for output key y:
[[ 2]
 [ 3]
 [ 4]]

モデルを TensorFlow デバッガー on で実行するためには、次のコマンドを発行します :

$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \
--signature_def serving_default --inputs x=/tmp/data.npz[x] --tf_debug

 

SavedModel ディレクトリの構造

SavedModel 形式でモデルをセーブするとき、TensorFlow は次のサブディレクトリとファイルから成る SavedModel ディレクトリを作成します :

assets/
assets.extra/
variables/
    variables.data-?????-of-?????
    variables.index
saved_model.pb|saved_model.pbtxt

ここで :

  • assets は語彙のような補助 (外部) ファイルを含むサブフォルダです。assets は特定の MetaGraphDef をロードするときに SavedModel 位置へコピーされ読まれます。
  • assets.extra はサブフォルダでここでは高位ライブラリとユーザがそれら自身のモデルと共存するアセットを追加できますが、グラフによりロードされません。このサブフォルダは SavedModel ライブラリにより管理されません。
  • variables は tf.train.Saver からの出力を含むサブフォルダです。
  • saved_model.pb または saved_model.pbtxt は SavedModel プロトコルバッファです。それは MetaGraphDef プロトコルバッファとしてグラフ定義を含みます。

単一の SavedModel は複数のグラフを表わすことができます。この場合、SavedModel の総てのグラフはチェックポイント (variables) と assets の単一のセットを共有します。例えば、次のダイアグラムは3つの MetaGraphDefs を含む一つの SavedModel を示します、それらの3つ総てはチェックポイントと assets の同じセットを共有します :

 
以上



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