![]() | ![]() | ![]() | ![]() |
このチュートリアルでは、Estimatorを使用してTensorFlowのアイリス分類問題を解決する方法を示します。 Estimatorは、TensorFlowによる完全なモデルの高レベルの表現であり、簡単なスケーリングと非同期トレーニング用に設計されています。詳細については、 Estimatorsを参照してください。
TensorFlow 2.0では、Keras APIはこれらの同じタスクの多くを実行でき、習得が容易なAPIであると考えられていることに注意してください。新しく始める場合は、Kerasから始めることをお勧めします。 TensorFlow 2.0で利用可能な高レベルAPIの詳細については、Kerasでの標準化を参照してください。
まず最初に
開始するには、最初にTensorFlowと必要ないくつかのライブラリをインポートします。
import tensorflow as tf
import pandas as pd
データセット
このドキュメントのサンプルプログラムは、がく片と花びらのサイズに基づいて、アイリスの花を3つの異なる種に分類するモデルを構築してテストします。
アイリスデータセットを使用してモデルをトレーニングします。アイリスデータセットには、4つの機能と1つのラベルが含まれています。 4つの特徴は、個々のアイリスの花の次の植物学的特徴を識別します。
- がく片の長さ
- がく片の幅
- 花びらの長さ
- 花びらの幅
この情報に基づいて、データを解析するためのいくつかの有用な定数を定義できます。
CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']
次に、KerasとPandasを使用してIrisデータセットをダウンロードして解析します。トレーニングとテストのために個別のデータセットを保持していることに注意してください。
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()
データセットごとに、モデルが予測するようにトレーニングされるラベルを分割します。
train_y = train.pop('Species')
test_y = test.pop('Species')
# The label column has now been removed from the features.
train.head()
Estimatorを使用したプログラミングの概要
データを設定したので、TensorFlowEstimatorを使用してモデルを定義できます。 Estimatorは、 tf.estimator.Estimator
から派生した任意のクラスtf.estimator.Estimator
。 TensorFlowは、一般的なMLアルゴリズムを実装するためのtf.estimator
コレクション(たとえば、 LinearRegressor
)を提供します。それらを超えて、独自のカスタムEstimatorを作成できます。開始するときは、事前に作成されたEstimatorを使用することをお勧めします。
事前に作成されたEstimatorに基づいてTensorFlowプログラムを作成するには、次のタスクを実行する必要があります。
- 1つ以上の入力関数を作成します。
- モデルのフィーチャ列を定義します。
- 特徴列とさまざまなハイパーパラメータを指定して、Estimatorをインスタンス化します。
- Estimatorオブジェクトで1つ以上のメソッドを呼び出し、適切な入力関数をデータのソースとして渡します。
これらのタスクがアイリス分類のためにどのように実装されているかを見てみましょう。
入力関数を作成する
トレーニング、評価、および予測のためのデータを提供するための入力関数を作成する必要があります。
入力関数は、次の2要素タプルを出力するtf.data.Dataset
オブジェクトを返す関数です。
入力関数のフォーマットを示すために、簡単な実装を次に示します。
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
入力関数は、 features
辞書とlabel
リストを好きなように生成できます。しかし、我々はTensorFlowの使用をお勧めしますデータセットのAPIデータのすべての種類を解析することができ、。
Dataset APIは、多くの一般的なケースを処理できます。たとえば、Dataset APIを使用すると、ファイルの大規模なコレクションからレコードを簡単に並行して読み込み、単一のストリームに結合できます。
この例では物事を単純にするために、パンダを使用してデータをロードし、このメモリ内データから入力パイプラインを構築します。
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
モジュールは、モデルにデータを表すための多くのオプションを提供します。
Irisの場合、4つの生の特徴は数値であるため、特徴列のリストを作成して、4つの特徴のそれぞれを32ビット浮動小数点値として表すように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))
特徴列は、ここで示しているものよりもはるかに洗練されている可能性があります。このガイドで特徴列の詳細を読むことができます。
モデルに生の特徴をどのように表現させるかについての説明ができたので、推定量を作成できます。
推定量をインスタンス化する
虹彩問題は古典的な分類問題です。幸い、TensorFlowには、次のようないくつかの事前に作成された分類子推定器が用意されています。
- マルチクラス分類を実行するディープモデルの
tf.estimator.DNNClassifier
。 - ワイドモデルとディープモデルの
tf.estimator.DNNLinearCombinedClassifier
。 - 線形モデルに基づく分類器の
tf.estimator.LinearClassifier
。
アイリスの問題については、 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 30 and 10 nodes respectively.
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/tmpbhg2uvbr INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpbhg2uvbr', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true graph_options { rewrite_options { meta_optimizer_iterations: ONE } } , '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
トレーニング、評価、および予測
Estimatorオブジェクトができたので、メソッドを呼び出して次のことを実行できます。
- モデルをトレーニングします。
- トレーニング済みモデルを評価します。
- トレーニング済みモデルを使用して予測を行います。
モデルをトレーニングする
次のようにEstimatorのtrain
メソッドを呼び出して、モデルを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.6/site-packages/tensorflow/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 its 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.6/site-packages/tensorflow/python/keras/optimizer_v2/adagrad.py:83: 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:Calling checkpoint listeners before saving checkpoint 0... INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpbhg2uvbr/model.ckpt. INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0... INFO:tensorflow:loss = 1.1140382, step = 0 INFO:tensorflow:global_step/sec: 312.415 INFO:tensorflow:loss = 0.8781501, step = 100 (0.321 sec) INFO:tensorflow:global_step/sec: 375.535 INFO:tensorflow:loss = 0.80712265, step = 200 (0.266 sec) INFO:tensorflow:global_step/sec: 372.712 INFO:tensorflow:loss = 0.7615077, step = 300 (0.268 sec) INFO:tensorflow:global_step/sec: 368.782 INFO:tensorflow:loss = 0.733555, step = 400 (0.271 sec) INFO:tensorflow:global_step/sec: 372.689 INFO:tensorflow:loss = 0.6983943, step = 500 (0.268 sec) INFO:tensorflow:global_step/sec: 370.308 INFO:tensorflow:loss = 0.67940104, step = 600 (0.270 sec) INFO:tensorflow:global_step/sec: 373.374 INFO:tensorflow:loss = 0.65386146, step = 700 (0.268 sec) INFO:tensorflow:global_step/sec: 368.335 INFO:tensorflow:loss = 0.63730353, step = 800 (0.272 sec) INFO:tensorflow:global_step/sec: 371.575 INFO:tensorflow:loss = 0.61313766, step = 900 (0.269 sec) INFO:tensorflow:global_step/sec: 371.975 INFO:tensorflow:loss = 0.6123625, step = 1000 (0.269 sec) INFO:tensorflow:global_step/sec: 369.615 INFO:tensorflow:loss = 0.5957534, step = 1100 (0.270 sec) INFO:tensorflow:global_step/sec: 374.054 INFO:tensorflow:loss = 0.57203, step = 1200 (0.267 sec) INFO:tensorflow:global_step/sec: 369.713 INFO:tensorflow:loss = 0.56556034, step = 1300 (0.270 sec) INFO:tensorflow:global_step/sec: 366.202 INFO:tensorflow:loss = 0.547443, step = 1400 (0.273 sec) INFO:tensorflow:global_step/sec: 361.407 INFO:tensorflow:loss = 0.53326523, step = 1500 (0.277 sec) INFO:tensorflow:global_step/sec: 367.461 INFO:tensorflow:loss = 0.51837724, step = 1600 (0.272 sec) INFO:tensorflow:global_step/sec: 364.181 INFO:tensorflow:loss = 0.5281174, step = 1700 (0.275 sec) INFO:tensorflow:global_step/sec: 368.139 INFO:tensorflow:loss = 0.5139683, step = 1800 (0.271 sec) INFO:tensorflow:global_step/sec: 366.277 INFO:tensorflow:loss = 0.51073176, step = 1900 (0.273 sec) INFO:tensorflow:global_step/sec: 366.634 INFO:tensorflow:loss = 0.4949246, step = 2000 (0.273 sec) INFO:tensorflow:global_step/sec: 364.732 INFO:tensorflow:loss = 0.49381495, step = 2100 (0.274 sec) INFO:tensorflow:global_step/sec: 365.006 INFO:tensorflow:loss = 0.48916715, step = 2200 (0.274 sec) INFO:tensorflow:global_step/sec: 366.902 INFO:tensorflow:loss = 0.48790723, step = 2300 (0.273 sec) INFO:tensorflow:global_step/sec: 362.232 INFO:tensorflow:loss = 0.47671652, step = 2400 (0.276 sec) INFO:tensorflow:global_step/sec: 368.592 INFO:tensorflow:loss = 0.47324088, step = 2500 (0.271 sec) INFO:tensorflow:global_step/sec: 371.611 INFO:tensorflow:loss = 0.46822113, step = 2600 (0.269 sec) INFO:tensorflow:global_step/sec: 362.345 INFO:tensorflow:loss = 0.4621966, step = 2700 (0.276 sec) INFO:tensorflow:global_step/sec: 362.788 INFO:tensorflow:loss = 0.47817266, step = 2800 (0.275 sec) INFO:tensorflow:global_step/sec: 368.473 INFO:tensorflow:loss = 0.45853442, step = 2900 (0.271 sec) INFO:tensorflow:global_step/sec: 360.944 INFO:tensorflow:loss = 0.44062576, step = 3000 (0.277 sec) INFO:tensorflow:global_step/sec: 370.982 INFO:tensorflow:loss = 0.4331399, step = 3100 (0.269 sec) INFO:tensorflow:global_step/sec: 366.248 INFO:tensorflow:loss = 0.45120597, step = 3200 (0.273 sec) INFO:tensorflow:global_step/sec: 371.703 INFO:tensorflow:loss = 0.4403404, step = 3300 (0.269 sec) INFO:tensorflow:global_step/sec: 362.176 INFO:tensorflow:loss = 0.42405623, step = 3400 (0.276 sec) INFO:tensorflow:global_step/sec: 363.283 INFO:tensorflow:loss = 0.41672814, step = 3500 (0.275 sec) INFO:tensorflow:global_step/sec: 363.529 INFO:tensorflow:loss = 0.42626005, step = 3600 (0.275 sec) INFO:tensorflow:global_step/sec: 367.348 INFO:tensorflow:loss = 0.4089098, step = 3700 (0.272 sec) INFO:tensorflow:global_step/sec: 363.067 INFO:tensorflow:loss = 0.41276374, step = 3800 (0.275 sec) INFO:tensorflow:global_step/sec: 364.771 INFO:tensorflow:loss = 0.4112524, step = 3900 (0.274 sec) INFO:tensorflow:global_step/sec: 363.167 INFO:tensorflow:loss = 0.39261794, step = 4000 (0.275 sec) INFO:tensorflow:global_step/sec: 362.082 INFO:tensorflow:loss = 0.41160905, step = 4100 (0.276 sec) INFO:tensorflow:global_step/sec: 364.979 INFO:tensorflow:loss = 0.39620766, step = 4200 (0.274 sec) INFO:tensorflow:global_step/sec: 363.323 INFO:tensorflow:loss = 0.39696264, step = 4300 (0.275 sec) INFO:tensorflow:global_step/sec: 361.25 INFO:tensorflow:loss = 0.38196522, step = 4400 (0.277 sec) INFO:tensorflow:global_step/sec: 365.666 INFO:tensorflow:loss = 0.38667366, step = 4500 (0.274 sec) INFO:tensorflow:global_step/sec: 361.202 INFO:tensorflow:loss = 0.38149032, step = 4600 (0.277 sec) INFO:tensorflow:global_step/sec: 365.038 INFO:tensorflow:loss = 0.37832782, step = 4700 (0.274 sec) INFO:tensorflow:global_step/sec: 366.375 INFO:tensorflow:loss = 0.3726803, step = 4800 (0.273 sec) INFO:tensorflow:global_step/sec: 366.474 INFO:tensorflow:loss = 0.37167495, step = 4900 (0.273 sec) INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 5000... INFO:tensorflow:Saving checkpoints for 5000 into /tmp/tmpbhg2uvbr/model.ckpt. INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 5000... INFO:tensorflow:Loss for final step: 0.36297452. <tensorflow_estimator.python.estimator.canned.dnn.DNNClassifierV2 at 0x7fc9983ed470>
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 its 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 2020-09-10T01:40:47Z INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from /tmp/tmpbhg2uvbr/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Inference Time : 0.21153s INFO:tensorflow:Finished evaluation at 2020-09-10-01:40:47 INFO:tensorflow:Saving dict for global step 5000: accuracy = 0.96666664, average_loss = 0.42594802, global_step = 5000, loss = 0.42594802 INFO:tensorflow:Saving 'checkpoint_path' summary for global step 5000: /tmp/tmpbhg2uvbr/model.ckpt-5000 Test set accuracy: 0.967
train
メソッドの呼び出しとは異なり、評価するためにsteps
引数を渡しませんでした。 evalのinput_fn
は、データの単一のエポックのみを生成します。
eval_result
ディクショナリには、 average_loss
(サンプルあたりの平均損失)、 loss
(ミニバッチあたりの平均損失)、および推定量の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の反復可能オブジェクトを返し、各例の予測結果のディクショナリを生成します。次のコードは、いくつかの予測とその確率を出力します。
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/tmpbhg2uvbr/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. Prediction is "Setosa" (91.3%), expected "Setosa" Prediction is "Versicolor" (52.0%), expected "Versicolor" Prediction is "Virginica" (63.5%), expected "Virginica"