TensorFlow : Guide : Estimators : Premade Estimators (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/14/2018
作成日時 : 03/06/2018
* TensorFlow 1.9 でドキュメント構成が変わりましたので調整しました。
* 本ページは、TensorFlow の本家サイトの Guide – Estimators – Premade Estimators を翻訳した上で
適宜、補足説明したものです:
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ |
Facebook: https://www.facebook.com/ClassCatJP/ |
このドキュメントでは TensorFlow プログラミング環境を紹介して、アイリス分類問題を TensorFlow でどのように書くのかを貴方に示します。
このドキュメントを読むに先立って、次を行なってください :
- TensorFlow をインストールします。
- TensorFlow を virtualenv か Anaconda でインストールした場合は、貴方の TensorFlow 環境を activate します。
- データのインポートを単純に保持するために、私達のアイリス・サンプルは Pandas を利用します。次でPandas をインストールできます : pip install pandas
サンプル・コードを取得する
次のステップを取ってこのプログラムのためのサンプル・コードを取得します :
- 次のコマンドで github から TensorFlow Models レポジトリを clone します :
git clone https://github.com/tensorflow/models
- その branch 内部でこのドキュメントで使用するサンプルを含む位置にディレクトリを変更します :
cd models/samples/core/get_started/
このドキュメントで説明されるプログラムは premade_estimator.py です。このプログラムはその訓練データを取得するために iris_data.py を使用します。
プログラムを実行する
貴方は TensorFlow プログラムを任意の Python プログラムを実行するように実行します。例えば :
python premade_estimator.py
このプログラムは訓練ログに続いてテストセットに対する幾つかの予測を出力するはずです。例えば、次の出力の最初の行はモデルはテストセットの最初のサンプルがセトサである 99.6 % の可能性があることを示します。テストセットは「セトサ」を期待していましたから、これは良い予測であるようです。
... Prediction is "Setosa" (99.6%), expected "Setosa" Prediction is "Versicolor" (99.8%), expected "Versicolor" Prediction is "Virginica" (97.9%), expected "Virginica"
もしプログラムが答えの代わりにエラーを生成する場合は、次の質問を貴方自身に尋ねてください :
- TensorFlow を正しくインストールしましたか?
- TensorFlow の正しいバージョンを使用していますか?
- TensorFlow をインストールした環境を activate しましたか? (これはある種のインストール機構においてのみ関連します。)
プログラミング・スタック
プログラム自身の詳細に入る前に、プログラミング環境を探究しましょう。次のイラストが示すように、TensorFlow は複数の API 層から成るプログラミング・スタックを提供します :
私達は次の API で TensorFlow プログラムを書くことを強く推奨します :
- Estimators, これは完全なモデルを表します。Estimator API はモデルを訓練し、モデルの精度を判断し、そして予測を生成するためのメソッドを提供します。
- Datasets, これはデータ入力パイプラインを構築します。Dataset API はデータをロードして操作するためのメソッドを持ち、それを貴方のモデルに供給します。Dataset API は Estimators API と上手く調和しています。
アイリスを分類する: 概要
このドキュメントのサンプル・プログラムはアイリス花をそれらのがく片 (= sepal) と花弁 (= petal) のサイズに基づいて3つの異なる種 (= species) に分類するモデルを構築してテストします。
左から右へ、アイリス・セトサ (by Radomil, CC BY-SA 3.0)、アイリス・バージカラー (by Dlanglois, CC BY-SA 3.0)、そして アイリス・バージニカ (by Frank Mayfield, CC BY-SA 2.0) です。
データセット
アイリス・データセットは4つの特徴と一つの ラベル を含みます。4つの特徴は個々のアイリス花の次の植物学的特性を識別します :
- がく片長さ
- がく片幅
- 花弁長さ
- 花弁幅
私達のモデルはこれらの特徴を float32 数値データとして表します。
ラベルはアイリス種を識別し、これは次の一つでなけれなりません :
- アイリス・セトサ (0)
- アイリス・バージカラー (1)
- アイリス・バージニカ (2)
私達のモデルはラベルを int32 カテゴリー・データとして表します。
次のテーブルはデータセットの3つのサンプルを示します :
がく片長さ | がく片幅 | 花弁長さ | 花弁幅 | 種 (ラベル) |
---|---|---|---|---|
5.1 | 3.3 | 1.7 | 0.5 | 0 (Setosa) |
5.0 | 2.3 | 3.3 | 1.0 | 1 (versicolor) |
6.4 | 2.8 | 2.2 | 2.2 | 2 (virginica) |
アルゴリズム
プログラムは次のトポロジーを持つ深層ニューラルネットワーク分類モデルを訓練します :
- 2 隠れ層。
- 各隠れ層は 10 ノードを含みます。
次の図は特徴、隠れ層、そして予測を図示します (隠れ層の総てのノードが表示されてはいません) :
推論
ラベル付けされていないサンプル上で訓練されたモデルを実行すると3つの予測を生成します、つまり、この花が与えられたアイリス種である尤度 (ゆうど、確からしさ) です。これらの出力予測の総和は 1.0 になるでしょう。例えば、ラベル付けされていないサンプル上の予測は次のようなものになるでしょう :
- アイリス・セトサのために 0.03
- アイリス・バージカラーのために 0.95
- アイリス・バージニカのために 0.02
上の予測は、与えられたラベル付けされていないサンプルがアイリス・バージカラーである 95 % の確率を示します。
Estimators によるプログラミングの概要
Estimator は TensorFlow の完全なモデルの高位な表現です。それは初期化、ロギング、セービングとリストアリング、そして多くの他の特徴を処理しますので、貴方は貴方のモデルに集中することができます。より詳細は Estimators を見てください。
Estimator は tf.estimator.Estimator から派生した任意のクラスです。TensorFlow は一般的な ML アルゴリズムを実装するために 事前作成された (= pre-made) Estimator (例えば、LinearRegressor) のコレクションを提供します。これらを越えて、貴方は貴方自身の カスタム Estimator を書くかもしれません。TensorFlow で単に始めるときには pre-made Estimator を使用することを推奨します。pre-made Estimator での経験を得た後、貴方自身のカスタム Estimator を作成することにより貴方のモデルを最適化することを勧めます。
pre-made Estimator に基づいて TensorFlow プログラムを書くためには、次のタスクを遂行しなければなりません :
- 一つまたはそれ以上の入力関数を作成する。
- モデルの特徴カラムを定義する。
- 特徴カラムと各種ハイパーパラメータを指定して、Estimator をインスタンス化する。
- データ・ソースとして適切な入力関数を渡して、Estimator オブジェクト上の一つまたはそれ以上のメソッドを呼び出す。
これらのタスクがアイリス分類のためにどのように実装されるかを見てみましょう。
入力関数を作成する
訓練、評価、そして予測のためのデータを供給するためには入力関数を作成しなければなりません。
入力関数 は次の 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
貴方の入力関数は特徴辞書とラベル・リストを好きなように生成して良いです。けれども、TensorFlow の Dataset API を使用することを推奨します、これは総ての種類のデータを解析できます。高位では、Dataset API は次のクラスから成ります :
ここで個々のメンバーは :
- Dataset – データセットを作成して変換するためのメソッドを含む基底クラスです。またメモリのデータから、あるいは Python ジェネレータからのデータセットを初期化することを可能にします。
- TextLineDataset – テキスト行から行を読みます。
- TFRecordDataset – TFRecord ファイルからレコードを読みます。
- FixedLengthRecordDataset – バイナリファイルから固定サイズのレコードを読みます。
- Iterator – 一つのデータセット要素に一度にアクセスする方法を提供します。
Dataset API は貴方のために多くの一般的なケースを処理します。例えば、Dataset API を使用して、ファイルの巨大なコレクションから並列にレコードを簡単に読んでそれらを単一のストリームに結合することができます。
このサンプルで簡単さを保持するためにデータを pandas でロードし、そしてこの in-memory データから私達の入力パイプラインを構築します。
ここにこのプログラムで訓練のために使用される入力関数があります、これは iris_data.py で利用可能です :
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. return dataset.shuffle(1000).repeat().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_x.keys(): my_feature_columns.append(tf.feature_column.numeric_column(key=key))
特徴カラムはここで示しているものよりも遥かにより洗練させることができます。私達は 後で Getting Started ガイドで特徴カラムについて詳述します。
モデルに生の特徴をどのように表現することを望むかの記述を持ちましたので、estimator を構築することができます。
estimator をインスタンス化する
アイリス問題は古典的な分類問題です。幸い、TensorFlow は各種の pre-made な分類器 Estimator を提供し、以下を含みます :
- 深層モデルのための tf.estimator.DNNClassifier は多クラス分類を遂行します。
- 汎用 (= wide) & 深層モデルのための tf.estimator.DNNLinearCombinedClassifier。
- 線形モデルベースの分類器のための tf.estimator.LinearClassifier。
アイリス問題に対しては、tf.estimator.DNNClassifier が最善の選択であるようです。ここにこの Estimator をどのようにインスタンス化するかがあります :
# Build a DNN with 2 hidden layers and 10 nodes in each hidden layer. classifier = tf.estimator.DNNClassifier( 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)
訓練、評価、そして予測
Estimator オブジェクトを持った今、以下を行なうためにメソッドを呼び出すことができます :
- モデルを訓練する。
- 訓練されたモデルを評価する。
- 予測するために訓練されたモデルを使用する。
モデルを訓練する
Estimator の train メソッドを呼び出すことでモデルを次のように訓練します :
# Train the Model. classifier.train( input_fn=lambda:iris_data.train_input_fn(train_x, train_y, args.batch_size), steps=args.train_steps)
ここで Estimator が期待するように、引数を取らない入力関数を提供する際に引数を捉えるために input_fn を lambda でラップします。steps 引数は訓練ステップの数の後で訓練を停止することをメソッドに伝えます。
訓練されたモデルを評価する
モデルが訓練されれば、その性能について何某かの統計情報を得ることができます。次のコードブロックはテストデータ上で訓練されたモデルの精度を評価します :
# Evaluate the model. eval_result = classifier.evaluate( input_fn=lambda:iris_data.eval_input_fn(test_x, test_y, args.batch_size)) print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
train メソッドへの呼び出しとは違って、evaluate に steps 引数を渡しません。eval_input_fn はデータの単一の エポック だけを生成します。
このコードの実行は次の出力 (または類似のもの) を生成します :
Test set accuracy: 0.967
訓練されたモデルから予測 (推論) します
良い評価結果を生成する訓練されたモデルを今は持っています。私達は幾つかのラベル付けされていない測定に基づいてアイリス花の種を予測するためにこの訓練されたモデルを使用することができます。訓練と評価と同様に、単一の関数呼び出しを使用して予測を行ないます :
# 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], } predictions = classifier.predict( input_fn=lambda:iris_data.eval_input_fn(predict_x, batch_size=args.batch_size))
predict メソッドは Python iterable を返し、各サンプルに対する予測結果の辞書を生成します。次のコードは 2, 3 の予測とそれらの確率を出力表示します :
for pred_dict, expec in zip(predictions, expected): template = ('\nPrediction is "{}" ({:.1f}%), expected "{}"') class_id = pred_dict['class_ids'][0] probability = pred_dict['probabilities'][class_id] print(template.format(iris_data.SPECIES[class_id], 100 * probability, expec))
上のコードの実行は次の出力を生成します :
... Prediction is "Setosa" (99.6%), expected "Setosa" Prediction is "Versicolor" (99.8%), expected "Versicolor" Prediction is "Virginica" (97.9%), expected "Virginica"
以上