ホーム » 「TensorFlow 2.0 Tutorials」タグがついた投稿

タグアーカイブ: TensorFlow 2.0 Tutorials

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 : Tutorials : データのロードと前処理 :- TFRecord と tf.Example

TensorFlow 2.0 : Beginner Tutorials : データのロードと前処理 :- TFRecord と tf.Example (翻訳/解説)

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

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

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、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/

 

データのロードと前処理 :- TFRecord と tf.Example

データを効率的に読むにはデータをシリアライズしてそれをそれぞれ線形に読めるファイルのセット (それぞれ 100-200MB) にストアすることが役立つかもしれません。これはデータがネットワークを通してストリームされている場合に特に真です。これはまた任意のデータ前処理をキャッシュするためにも有用かもしれません。

TFRecord 形式はバイナリ・レコードのシークエンスをストアするための単純な形式です。

protocol buffer は構造化データの効率的なシリアライゼーションのためのクロスプラットフォーム、クロス言語なライブラリです。

protocol message は .proto ファイルで定義されます、これらはしばしばメッセージ型を理解するための最も容易な方法です。

tf.Example メッセージ (or protobuf) は {“string”: value} マッピングを表わす柔軟なメッセージ型です。それは TensorFlow での利用のために設計されてそして TFX のような高位レベル API を通して使用されます。

このノートブックは tf.Example メッセージをどのように作成し、パースし、そして使用するか、そしてそれから .tfrecord ファイル to/from tf.Example メッセージをシリアライズし、書き、そして読むかを実演します。

Note: 有用である一方で、これらの構造はオプションです。既存のコードを TFRecords を使用するように変換する必要はありません、貴方が tf.data を使用していてそしてデータが依然として訓練のボトルネックでない限りは。データセットのパフォーマンス tips のためには Data Input Pipeline Performance を見てください。

 

セットアップ

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf

import numpy as np
import IPython.display as display

 

tf.Example

tf.Example のためのデータ型

根本的には、tf.Example は {“string”: tf.train.Feature} マッピングです。

tf.train.Feature メッセージ型は次の 3 つの型の一つを受け取れます (リファレンスとして .proto ファイル 参照)。
殆どの他の generic 型はこれらの一つに強制できます :

  1. tf.train.BytesList (次の型が強制可能です)
    • string
    • byte
  2. tf.train.FloatList (次の型が強制可能です)
    • float (float32)
    • double (float64)
  3. tf.train.Int64List (次の型が強制可能です)
    • bool
    • enum
    • int32
    • uint32
    • int64
    • uint64

標準的な TensorFlow 型を tf.Example-互換 tf.train.Feature に変換するためには、下のショートカット関数を使用できます。各関数はスカラー入力値を取りそして上の 3 つのリスト型の一つを含む tf.train.Feature を返すことに注意してください :

# The following functions can be used to convert a value to a type compatible
# with tf.Example.

def _bytes_feature(value):
  """Returns a bytes_list from a string / byte."""
  if isinstance(value, type(tf.constant(0))):
    value = value.numpy() # BytesList won't unpack a string from an EagerTensor.
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

def _float_feature(value):
  """Returns a float_list from a float / double."""
  return tf.train.Feature(float_list=tf.train.FloatList(value=[value]))

def _int64_feature(value):
  """Returns an int64_list from a bool / enum / int / uint."""
  return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))

Note: 単純であるために、このサンプルはスカラー入力を使用しているだけです。非スカラー特徴を処理する最も単純な方法は tensor をバイナリ文字列に変換するために tf.serialize_tensor を使用することです。文字列は tensorflow ではスカラーです。バイナリ文字列を tensor に変換し戻すためには tf.parse_tensor を使用します。

下はこれらの関数がどのように動作するかの幾つかのサンプルです。変化する入力型と標準化された出力型に注意してください。関数のための入力型が上で述べた強制可能な型の一つに適合しない場合には、関数は例外をあげます (e.g. _int64_feature(1.0) はエラーを出します、何故ならば 1.0 は float であるからです、従って代わりに _float_feature 関数により使用されるべきです) :

print(_bytes_feature(b'test_string'))
print(_bytes_feature(u'test_bytes'.encode('utf-8')))

print(_float_feature(np.exp(1)))

print(_int64_feature(True))
print(_int64_feature(1))
bytes_list {
  value: "test_string"
}

bytes_list {
  value: "test_bytes"
}

float_list {
  value: 2.7182817459106445
}

int64_list {
  value: 1
}

int64_list {
  value: 1
}

総ての proto メッセージは .SerializeToString メソッドを使用してバイナリ文字列にシリアライズできます :

feature = _float_feature(np.exp(1))

feature.SerializeToString()
b'\x12\x06\n\x04T\xf8-@'

 

tf.Example メッセージを作成する

既存のデータから tf.Example メッセージを作成することを望むとします。実際に、データセットはどこから由来することもできますが、単一の観測 (= observation) から tf.Example メッセージを作成する手続きは同じです :

  1. 各観測内で、各値は上の関数の一つを使用して、3 つの互換な型の一つを含む tf.train.Feature に変換される必要があります。
  2. 特徴名文字列から #1 で生成されたエンコードされた特徴値へのマップ (辞書) を作成します。
  3. ステップ 2 で生成されたマップは Features メッセージ に変換されます。

このノートブックでは、NumPy を使用してデータセットを作成します。

データセットは 4 つの特徴を持ちます : * boolean 特徴、同じ確率で False か True * 整数特徴、[0, 5] から一様にランダムに選択されます * 文字列特徴、整数特徴をインデックスとして使用して文字列テーブルから生成されます * float 特徴、標準正規分布から

各々の上の分布からの 10,000 の i.i.d. (独立同一分布) 観測から成るサンプルを考えます :

# The number of observations in the dataset.
n_observations = int(1e4)

# Boolean feature, encoded as False or True.
feature0 = np.random.choice([False, True], n_observations)

# Integer feature, random from 0 to 4.
feature1 = np.random.randint(0, 5, n_observations)

# String feature
strings = np.array([b'cat', b'dog', b'chicken', b'horse', b'goat'])
feature2 = strings[feature1]

# Float feature, from a standard normal distribution
feature3 = np.random.randn(n_observations)

これらの特徴の各々は _bytes_feature, _float_feature, _int64_feature の一つを使用して tf.Example-互換型に強制できます。それからこれらのエンコードされた特徴から tf.Example メッセージを作成できます :

def serialize_example(feature0, feature1, feature2, feature3):
  """
  Creates a tf.Example message ready to be written to a file.
  """
  # Create a dictionary mapping the feature name to the tf.Example-compatible
  # data type.
  feature = {
      'feature0': _int64_feature(feature0),
      'feature1': _int64_feature(feature1),
      'feature2': _bytes_feature(feature2),
      'feature3': _float_feature(feature3),
  }

  # Create a Features message using tf.train.Example.

  example_proto = tf.train.Example(features=tf.train.Features(feature=feature))
  return example_proto.SerializeToString()

例えば、データセットから単一の観測を持つと仮定します, [False, 4, bytes(‘goat’), 0.9876]。create_message() を使用して観測のための tf.Example メッセージを作成してプリントすることができます。各単一の観測は上のように Features メッセージとして書かれます。tf.Example メッセージ は Features メッセージ回りの単なるラッパーであることに注意してください :

# This is an example observation from the dataset.

example_observation = []

serialized_example = serialize_example(False, 4, b'goat', 0.9876)
serialized_example
b'\nR\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04[\xd3|?'

メッセージをデコードするために tf.train.Example.FromString メソッドを使用します。

example_proto = tf.train.Example.FromString(serialized_example)
example_proto
features {
  feature {
    key: "feature0"
    value {
      int64_list {
        value: 0
      }
    }
  }
  feature {
    key: "feature1"
    value {
      int64_list {
        value: 4
      }
    }
  }
  feature {
    key: "feature2"
    value {
      bytes_list {
        value: "goat"
      }
    }
  }
  feature {
    key: "feature3"
    value {
      float_list {
        value: 0.9876000285148621
      }
    }
  }
}

 

TFRecords 形式詳細

TFRecord ファイルはレコードのシークエンスを含みます。ファイルはシーケンシャルにのみ読むことができます。

各レコードはデータ・ペイロードのためのバイト文字列、 更にデータ長、そして整合性チェックのための CRC32 (Castagnoli polynomial を使用する 32-bit CRC) ハッシュを含みます。

各レコードは次の形式でストアされます :

uint64 length
uint32 masked_crc32_of_length
byte   data[length]
uint32 masked_crc32_of_data

レコードはファイルを生成するために一緒に結合されます。CRC は ここで説明されます、そして CRC のマスクは :

masked_crc = ((crc >> 15) | (crc << 17)) + 0xa282ead8ul

Note: TFRecord ファイルで tf.Example を使用する必要性はありません。tf.Example は辞書をバイト文字列にシリアライズするための単なる方法です。テキスト行、エンコードされた画像データ、あるいはシリアライズされた tensor (ロードするとき tf.io.serialize_tensortf.io.parse_tensor を使用して)。より多くのオプションについては tf.io モジュールを見てください。

 

tf.data を使用する TFRecord ファイル

tf.data モジュールはまた TensorFlow でデータを読み書きするためのツールも提供します。

 

TFRecord ファイルを書く

データをデータセットに得る最も容易な方法は from_tensor_slices メソッドを使用することです。

配列に適用されれば、それはスカラーのデータセットを返します :

tf.data.Dataset.from_tensor_slices(feature1)
<TensorSliceDataset shapes: (), types: tf.int64>

配列のタプルに適用されると、それはタプルのデータセットを返します :

features_dataset = tf.data.Dataset.from_tensor_slices((feature0, feature1, feature2, feature3))
features_dataset
<TensorSliceDataset shapes: ((), (), (), ()), types: (tf.bool, tf.int64, tf.string, tf.float64)>
# Use `take(1)` to only pull one example from the dataset.
for f0,f1,f2,f3 in features_dataset.take(1):
  print(f0)
  print(f1)
  print(f2)
  print(f3)
tf.Tensor(True, shape=(), dtype=bool)
tf.Tensor(4, shape=(), dtype=int64)
tf.Tensor(b'goat', shape=(), dtype=string)
tf.Tensor(1.6098582698561394, shape=(), dtype=float64)

Dataset の各要素に関数を適用するために tf.data.Dataset.map メソッドを使用します。

mapped 関数は TensorFlow グラフモードで作用しなければなりません — それは作用して tf.Tensor を返さなければなりません。create_example のような非 tensor 関数はそれを互換にするために tf.py_function でラップできます。

tf.py_function は (そうしないと利用可能でない) shape と型情報を指定することを必要とします :

def tf_serialize_example(f0,f1,f2,f3):
  tf_string = tf.py_function(
    serialize_example,
    (f0,f1,f2,f3),  # pass these args to the above function.
    tf.string)      # the return type is `tf.string`.
  return tf.reshape(tf_string, ()) # The result is a scalar
tf_serialize_example(f0,f1,f2,f3)
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xd6\x0f\xce?'>

この関数を dataset の各要素に適用します :

serialized_features_dataset = features_dataset.map(tf_serialize_example)
serialized_features_dataset
<MapDataset shapes: (), types: tf.string>
def generator():
  for features in features_dataset:
    yield serialize_example(*features)
serialized_features_dataset = tf.data.Dataset.from_generator(
    generator, output_types=tf.string, output_shapes=())
serialized_features_dataset
<FlatMapDataset shapes: (), types: tf.string>

そしてそれらを TFRecord ファイルに書きます :

filename = 'test.tfrecord'
writer = tf.data.experimental.TFRecordWriter(filename)
writer.write(serialized_features_dataset)

 

TFRecord ファイルを読む

tf.data.TFRecordDataset クラスを使用して TFRecord ファイルを読むこともできます。

tf.data を使用して TFRecord ファイルを消費するためのより多くの情報は ここ で見つかります。

TFRecordDatasets の使用は入力データを標準化してパフォーマンスを最適化するために有用かもしれません。

filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 shapes: (), types: tf.string>

この時点で dataset はシリアライズされた tf.train.Example メッセージを含みます。反復されたときそれはこれらをスカラー文字列 tensor として返します。

最初の 10 レコードを示すだけのために .take メソッドを使用します。

Note: tf.data.Dataset に渡る反復は eager execution が有効なときにだけ動作します。

for raw_record in raw_dataset.take(10):
  print(repr(raw_record))
<tf.Tensor: shape=(), dtype=string, numpy=b'\nR\n\x14\n\x08feature2\x12\x08\n\x06\n\x04goat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xd6\x0f\xce?\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x04'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\x04d\xa1?\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\tf.Tensor: shape=(), dtype=string, numpy=b'\nS\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x03\n\x15\n\x08feature2\x12\t\n\x07\n\x05horse\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xf7\xcb\xd3?'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xc9\x07\xaf?'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04a\xd4\xdb\xbd'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nS\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x03\n\x15\n\x08feature2\x12\t\n\x07\n\x05horse\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xfd\xb7\xb1\xbf'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xf8\x0e\x07@'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x00\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xee\x0f\xa4\xbf'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nU\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x02\n\x17\n\x08feature2\x12\x0b\n\t\n\x07chicken\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04\xf0\xa0\xb3>'>
<tf.Tensor: shape=(), dtype=string, numpy=b'\nQ\n\x13\n\x08feature2\x12\x07\n\x05\n\x03cat\n\x14\n\x08feature3\x12\x08\x12\x06\n\x04CX\xd6>\n\x11\n\x08feature0\x12\x05\x1a\x03\n\x01\x01\n\x11\n\x08feature1\x12\x05\x1a\x03\n\x01\x00'>

これらの tensor は下の関数を使用してパースされます。ここで feature_description が必要であることに注意してください、何故ならば dataset がグラフ実行を使用し、そしてそれらの shape と型シグネチャーを構築するためにこの記述を必要とするためです :

# Create a description of the features.
feature_description = {
    'feature0': tf.io.FixedLenFeature([], tf.int64, default_value=0),
    'feature1': tf.io.FixedLenFeature([], tf.int64, default_value=0),
    'feature2': tf.io.FixedLenFeature([], tf.string, default_value=''),
    'feature3': tf.io.FixedLenFeature([], tf.float32, default_value=0.0),
}

def _parse_function(example_proto):
  # Parse the input `tf.Example` proto using the dictionary above.
  return tf.io.parse_single_example(example_proto, feature_description)

代わりに、バッチ全体を一度にパースするために "tf.parse example" を使用します。tf.data.Dataset.map メソッドを使用してこの関数を dataset で各項目に適用します :

parsed_dataset = raw_dataset.map(_parse_function)
parsed_dataset
<MapDataset shapes: {feature0: (), feature1: (), feature2: (), feature3: ()}, types: {feature0: tf.int64, feature1: tf.int64, feature2: tf.string, feature3: tf.float32}>

dataset で観測を表示するために eager execution を使用します。この dataset には 10,000 観測がありますが、最初の 10 を表示するだけです。データは特徴の辞書として表示されます。各項目は tf.Tensor で、そしてこの tensor の numpy 要素は特徴の値を表示します :

for parsed_record in parsed_dataset.take(10):
  print(repr(parsed_record))
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=4>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'goat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.6098583>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=2>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'chicken'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.2608647>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.654662>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=1.3674251>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-0.107338674>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=3>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'horse'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-1.3884274>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=2>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'chicken'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=2.1102886>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=-1.2817361>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=2>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'chicken'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.35083723>}
{'feature0': <tf.Tensor: shape=(), dtype=int64, numpy=1>, 'feature1': <tf.Tensor: shape=(), dtype=int64, numpy=0>, 'feature2': <tf.Tensor: shape=(), dtype=string, numpy=b'cat'>, 'feature3': <tf.Tensor: shape=(), dtype=float32, numpy=0.41864213>}

ここで、tf.parse_example 関数は tf.Example フィールドを標準 tensor にアンパックします。

 

Python の TFRecord ファイル

tf.io モジュールはまた TFRecord ファイルを読み書きするために pure-Python 関数もまた含みます。

 

TFRecord ファイルを書く

次に、10,000 観測をファイル test.tfrecord に書きます。各観測は tf.Example メッセージに変換されて、それからファイルに書かれます。それからファイル test.tfrecord が作成されたことを確認できます :

# Write the `tf.Example` observations to the file.
with tf.io.TFRecordWriter(filename) as writer:
  for i in range(n_observations):
    example = serialize_example(feature0[i], feature1[i], feature2[i], feature3[i])
    writer.write(example)
!du -sh {filename}
984K    test.tfrecord

 

TFRecord ファイルを読む

これらのシリアライズされた tensor は tf.train.Example.ParseFromString を使用して容易にパースできます :

filenames = [filename]
raw_dataset = tf.data.TFRecordDataset(filenames)
raw_dataset
<TFRecordDatasetV2 shapes: (), types: tf.string>
for raw_record in raw_dataset.take(1):
  example = tf.train.Example()
  example.ParseFromString(raw_record.numpy())
  print(example)
features {
  feature {
    key: "feature0"
    value {
      int64_list {
        value: 1
      }
    }
  }
  feature {
    key: "feature1"
    value {
      int64_list {
        value: 4
      }
    }
  }
  feature {
    key: "feature2"
    value {
      bytes_list {
        value: "goat"
      }
    }
  }
  feature {
    key: "feature3"
    value {
      float_list {
        value: 1.6098582744598389
      }
    }
  }
}

 

ウォークスルー : 画像データを読み書きする

これは TFRecord を使用してどのように画像データを読み書きするかのサンプルです。これの目的はどのように入力データ (この場合は画像) を TFRecord ファイルとして書いて、それからファイルを読み戻して画像を表示するかを end-to-end で示すことです。

これは有用です、例えば、同じ入力データセット上で幾つかのモデルを使用することを望むのであれば。画像データを生でストアする代わりに、それは TFRecord 形式に前処理できて、そしれそれは総てのそれ以上の処理とモデリングで使用できます。

最初に雪の中の猫の この画像 と建設中の Williamsburg Bridge, NYC の この写真 をダウンロードしましょう。

 

画像を取得する

cat_in_snow  = tf.keras.utils.get_file('320px-Felis_catus-cat_on_snow.jpg', 'https://storage.googleapis.com/download.tensorflow.org/example_images/320px-Felis_catus-cat_on_snow.jpg')
williamsburg_bridge = tf.keras.utils.get_file('194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg','https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg')
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/320px-Felis_catus-cat_on_snow.jpg
24576/17858 [=========================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/194px-New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg
16384/15477 [===============================] - 0s 0us/step
display.display(display.Image(filename=cat_in_snow))
display.display(display.HTML('Image cc-by: <a "href=https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg">Von.grzanka'))

Image cc-by: Von.grzanka
display.display(display.Image(filename=williamsburg_bridge))
display.display(display.HTML('<a "href=https://commons.wikimedia.org/wiki/File:New_East_River_Bridge_from_Brooklyn_det.4a09796u.jpg">From Wikimedia'))

From Wikimedia

 

TFRecord ファイルを書く

前のように、特徴を tf.Example と互換な型としてエンコードします。これは生画像文字列特徴に加えて高さ、幅、depth、そして任意のラベル特徴をストアします。後者は猫画像と橋画像の間を識別するためにファイルを書くときに使用されます。猫画像のために 0、そして橋画像のために 1 を使用します :

image_labels = {
    cat_in_snow : 0,
    williamsburg_bridge : 1,
}
# This is an example, just using the cat image.
image_string = open(cat_in_snow, 'rb').read()

label = image_labels[cat_in_snow]

# Create a dictionary with features that may be relevant.
def image_example(image_string, label):
  image_shape = tf.image.decode_jpeg(image_string).shape

  feature = {
      'height': _int64_feature(image_shape[0]),
      'width': _int64_feature(image_shape[1]),
      'depth': _int64_feature(image_shape[2]),
      'label': _int64_feature(label),
      'image_raw': _bytes_feature(image_string),
  }

  return tf.train.Example(features=tf.train.Features(feature=feature))

for line in str(image_example(image_string, label)).split('\n')[:15]:
  print(line)
print('...')
features {
  feature {
    key: "depth"
    value {
      int64_list {
        value: 3
      }
    }
  }
  feature {
    key: "height"
    value {
      int64_list {
        value: 213
      }
...

特徴の総てが今は tf.Example メッセージにストアされていることに気付いてください。次に、上のコードを機能的にして example メッセージを images.tfrecords という名前のファイルに書きます :

# Write the raw image files to `images.tfrecords`.
# First, process the two images into `tf.Example` messages.
# Then, write to a `.tfrecords` file.
record_file = 'images.tfrecords'
with tf.io.TFRecordWriter(record_file) as writer:
  for filename, label in image_labels.items():
    image_string = open(filename, 'rb').read()
    tf_example = image_example(image_string, label)
    writer.write(tf_example.SerializeToString())
!du -sh {record_file}
36K images.tfrecords

 

TFRecord ファイルを読む

貴方は今はファル —images.tfrecords— を持ちます、そして貴方が書いたものを読む戻すためにその中のレコードに渡り反復できます。このサンプルで画像を再生成するだけとすれば、必要な唯一の特徴は生画像文字列です。上で説明された getter を使用してそれを抽出します、つまり example.features.feature['image_raw'].bytes_list.value[0] です。どこレコードが猫でそしてどれが橋であるかを決定するためにラベルも使用できます :

raw_image_dataset = tf.data.TFRecordDataset('images.tfrecords')

# Create a dictionary describing the features.
image_feature_description = {
    'height': tf.io.FixedLenFeature([], tf.int64),
    'width': tf.io.FixedLenFeature([], tf.int64),
    'depth': tf.io.FixedLenFeature([], tf.int64),
    'label': tf.io.FixedLenFeature([], tf.int64),
    'image_raw': tf.io.FixedLenFeature([], tf.string),
}

def _parse_image_function(example_proto):
  # Parse the input tf.Example proto using the dictionary above.
  return tf.io.parse_single_example(example_proto, image_feature_description)

parsed_image_dataset = raw_image_dataset.map(_parse_image_function)
parsed_image_dataset
<MapDataset shapes: {depth: (), height: (), image_raw: (), label: (), width: ()}, types: {depth: tf.int64, height: tf.int64, image_raw: tf.string, label: tf.int64, width: tf.int64}>

TFRecord ファイルから画像をリカバーします :

for image_features in parsed_image_dataset:
  image_raw = image_features['image_raw'].numpy()
  display.display(display.Image(data=image_raw))
 

以上



TensorFlow 2.0 : Tutorials : データのロードと前処理 :- TF.Text

TensorFlow 2.0 : Beginner Tutorials : データのロードと前処理 :- TF.Text (翻訳/解説)

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

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

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、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/

 

データのロードと前処理 :- TF.Text

イントロダクション

TensorFlow Text は TensorFlow 2.0 ですぐに使えるテキスト関連クラスと ops のコレクションを提供します。ライブラリはテキスト・ベースのモデルにより通常必要な前処理を遂行できてそしてコア TensorFlow で提供されないシークエンス・モデリングに有用な他の特徴を含みます。

貴方のテキスト前処理でこれらの ops を使用することの優位点はそれらは TensorFlow グラフで行なわれることです。推論時のトークン化とは異なる訓練のトークン化、あるいは前処理スクリプトの管理について心配する必要はありません、

 

Eager Execution

TensorFlow Text は TensorFlow 2.0 を必要とし、そして eager モードと graph モードと完全に互換です。

Note: 稀なケースとして、このインポートは TF ライブラリを探して失敗するかもしれません。ランタイムをリセットして上の (訳注: 原文ママ) pip install -q を再実行してください。

!pip install -q tensorflow-text
DEPRECATION: Python 3.4 support has been deprecated. pip 19.1 will be the last one supporting it. Please upgrade your Python as Python 3.4 won't be maintained after March 2019 (cf PEP 429).
import tensorflow as tf
import tensorflow_text as text

 

Unicode

殆どの ops は文字列が UTF-8 にあることを想定しています。異なるエンコーディングを使用している場合、UTF-8 にコード変換するためにコア tensorflow transcode op を使用できます。もし貴方の入力が妥当でないかもしれない場合には、文字列を構造的に妥当な UTF-8 に強制するために同じ op を使用することもできます。

docs = tf.constant([u'Everything not saved will be lost.'.encode('UTF-16-BE'), u'Sad☹'.encode('UTF-16-BE')])
utf8_docs = tf.strings.unicode_transcode(docs, input_encoding='UTF-16-BE', output_encoding='UTF-8')

 

トークン化

トークン化は文字列をトークンに分解するプロセスです。一般には、これらのトークンは単語、数字、and/or 句読点です。

主要なインターフェイスは Tokenizer と TokenizerWithOffsets です、これらはそれぞれ単一のメソッド tokenize と tokenize_with_offsets を持ちます。現在利用可能な複数の tokenizer があります。これらの各々は TokenizerWithOffsets (これは Tokenizer を拡張します) を実装します、これは元の文字列へのバイトオフセットを得るためのオプションを含みます。これは呼び出し側にトークンがそれから作成された元の文字列でのバイトを知ることを可能にします。

tokenizer の総ては元の個々の文字列へマッピングするトークンの最奥の次元を持つ RaggedTensor を返します。その結果、結果としての shape の rank は一つ増やされます。ragged tensor ガイドをレビューしてください、それらに馴染みがないのであれば。https://www.tensorflow.org/guide/ragged_tensors

 

WhitespaceTokenizer

これは ICU 定義された空白文字 (eg. スペース、タブ、改行) 上で UTF-8 文字列を分割する基本的な tokenizer です。

tokenizer = text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(['everything not saved will be lost.', u'Sad☹'.encode('UTF-8')])
print(tokens.to_list())
WARNING: Logging before flag parsing goes to stderr.
W0701 13:16:14.667488 140633166759744 deprecation.py:323] From /tmpfs/src/tf_docs_env/lib/python3.4/site-packages/tensorflow/python/util/dispatch.py:180: batch_gather (from tensorflow.python.ops.array_ops) is deprecated and will be removed after 2017-10-25.
Instructions for updating:
`tf.batch_gather` is deprecated, please use `tf.gather` with `batch_dims` instead.
W0701 13:16:14.671800 140633166759744 deprecation.py:323] From /tmpfs/src/tf_docs_env/lib/python3.4/site-packages/tensorflow/python/ops/array_ops.py:1340: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where

[[b'everything', b'not', b'saved', b'will', b'be', b'lost.'], [b'Sad\xe2\x98\xb9']]

 

UnicodeScriptTokenizer

tokenizer は Unicode スクリプト境界に基づいて UTF-8 文字列を分割します。使用されるスクリプトコードは International Components for Unicode (ICU) UScriptCode 値に対応します。参照: http://icu-project.org/apiref/icu4c/uscript_8h.html

実際には、これは WhitespaceTokenizer に類似しています、最も明白な差異はそれは言語テキスト (eg. USCRIPT_LATIN, USCRIPT_CYRILLIC, etc) から句読点 (USCRIPT_COMMON) を分割することです、互いに言語テキストもまた分ける一方で。

tokenizer = text.UnicodeScriptTokenizer()
tokens = tokenizer.tokenize(['everything not saved will be lost.', u'Sad☹'.encode('UTF-8')])
print(tokens.to_list())
[[b'everything', b'not', b'saved', b'will', b'be', b'lost', b'.'], [b'Sad', b'\xe2\x98\xb9']]

 

Unicode 分割 (= split)

単語をセグメントするための空白なしで言語をトークン化するとき、文字で単に分割することは一般的です、これはコアで見つかる unicode_split op を使用して成されます。

tokens = tf.strings.unicode_split([u"仅今年前".encode('UTF-8')], 'UTF-8')
print(tokens.to_list())
[[b'\xe4\xbb\x85', b'\xe4\xbb\x8a', b'\xe5\xb9\xb4', b'\xe5\x89\x8d']]

 

オフセット

文字列をトークン化するとき、トークンが元の文字列のどこに由来するかを知ることはしばしば望まれます。このため、TokenizerWithOffsets を実装する各 tokenizer は tokenize_with_offsets メソッドを持ちます、これはトークンと一緒にバイトオフセットを返します。offset_starts は元の文字列で各トークンが始まるバイトをリストして、offset_limits は各トークンが終わるバイトをリストします。

tokenizer = text.UnicodeScriptTokenizer()
(tokens, offset_starts, offset_limits) = tokenizer.tokenize_with_offsets(['everything not saved will be lost.', u'Sad☹'.encode('UTF-8')])
print(tokens.to_list())
print(offset_starts.to_list())
print(offset_limits.to_list())
[[b'everything', b'not', b'saved', b'will', b'be', b'lost', b'.'], [b'Sad', b'\xe2\x98\xb9']]
[[0, 11, 15, 21, 26, 29, 33], [0, 3]]
[[10, 14, 20, 25, 28, 33, 34], [3, 6]]

 

TF.Data サンプル

tokenizer は tf.data API と共に期待どおりに動作します。下で単純な例が提供されます。

docs = tf.data.Dataset.from_tensor_slices([['Never tell me the odds.'], ["It's a trap!"]])
tokenizer = text.WhitespaceTokenizer()
tokenized_docs = docs.map(lambda x: tokenizer.tokenize(x))
iterator = iter(tokenized_docs)
print(next(iterator).to_list())
print(next(iterator).to_list())
[[b'Never', b'tell', b'me', b'the', b'odds.']]
[[b"It's", b'a', b'trap!']]

 

他の Text ops

TF.Text は他の有用な前処理 ops をパッケージ化しています。下で 2, 3 をレビューします。

 

Wordshape

幾つかの自然言語理解モデルで使用される一般的な特徴はテキスト文字列が特定のプロパティを持つかを見ることです。例えば、センテンス分解モデルは単語の大文字化 (= capitalization) や句読点文字が文字列の最後にあるかを確認する特徴を含むかもしれません。

Wordshape は貴方の入力テキストの様々な関連パターンのための様々な有用な正規表現ベースのヘルパー関数を定義します。ここに 2, 3 のサンプルがあります。

tokenizer = text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(['Everything not saved will be lost.', u'Sad☹'.encode('UTF-8')])

# Is capitalized?
f1 = text.wordshape(tokens, text.WordShape.HAS_TITLE_CASE)
# Are all letters uppercased?
f2 = text.wordshape(tokens, text.WordShape.IS_UPPERCASE)
# Does the token contain punctuation?
f3 = text.wordshape(tokens, text.WordShape.HAS_SOME_PUNCT_OR_SYMBOL)
# Is the token a number?
f4 = text.wordshape(tokens, text.WordShape.IS_NUMERIC_VALUE)

print(f1.to_list())
print(f2.to_list())
print(f3.to_list())
print(f4.to_list())
[[True, False, False, False, False, False], [True]]
[[False, False, False, False, False, False], [False]]
[[False, False, False, False, False, True], [True]]
[[False, False, False, False, False, False], [False]]

 

N-gram & スライディング・ウィンドウ

N-gram はスライディング・ウィンドウのサイズ n が与えられたときのシーケンシャルな単語です。トークンを結合するとき、サポートされる 3 つのリダクション・メカニズムがあります。テキストのためには、Reduction.STRING_JOIN を使用することを望むでしょう、これは文字列を互いに付加します。デフォルトのセパレータ文字はスペースですが、これは string_separater 引数で変更できます。

他の 2 つのリダクション・メソッドは殆どの場合数値とともに使用されます、そしてこれらは Reduction.SUM と Reduction.MEAN です。

tokenizer = text.WhitespaceTokenizer()
tokens = tokenizer.tokenize(['Everything not saved will be lost.', u'Sad☹'.encode('UTF-8')])

# Ngrams, in this case bi-gram (n = 2)
bigrams = text.ngrams(tokens, 2, reduction_type=text.Reduction.STRING_JOIN)

print(bigrams.to_list())
[[b'Everything not', b'not saved', b'saved will', b'will be', b'be lost.'], []]
 

以上



TensorFlow 2.0 : Tutorials : データのロードと前処理 :- Unicode 文字列

TensorFlow 2.0 : Beginner Tutorials : データのロードと前処理 :- Unicode 文字列 (翻訳/解説)

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

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

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、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/

 

データのロードと前処理 :- Unicode 文字列

イントロダクション

自然言語を処理するモデルはしばしば異なる文字セットを持つ異なる言語を扱います。Unicode は殆ど総ての言語からの文字を表わすために使用される標準エンコーディング・システムです。各文字は 0 と 0x10FFFF の間の一意な整数 コードポイント を使用してエンコードされます。Unicode 文字列はゼロまたはそれ以上のコードポイントのシークエンスです。

このチュートリアルはどのように TensorFlow で Unicode 文字列を表して標準文字列 ops の Unicode 同値を使用してそれらを操作するかを示します。それは Unicode 文字列を script detection に基づいてトークンに分類します。

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf

 

tf.string データ型

基本的な TensorFlow tf.string dtype はバイト文字列の tensor を構築することを可能にします。Unicode 文字列はデフォルトでは utf-8 エンコードされます。

tf.constant(u"Thanks 😊")
<tf.Tensor: id=0, shape=(), dtype=string, numpy=b'Thanks \xf0\x9f\x98\x8a'>

tf.string tensor は変化する長さのバイト文字列を保持できます、何故ならばバイト文字列は atomic 単位として扱われるからです。文字列長は tensor 次元には含まれません。

tf.constant([u"You're", u"welcome!"]).shape
TensorShape([2])

Note: 文字列を構築するために python を使用するとき、unicode の扱いは v2 と v3 の間で異なります。v2 では、unicode 文字列は上のように “u” prefix で示されます。v3 では、文字列はデフォルトで unicode-エンコードされます。

 

Unicode を表わす

TensorFlow で Unicode 文字列を表わすには 2 つの標準的な方法があります :

  • string scalar — そこではコードポイントのシークエンスが既知の文字エンコーディングを使用してエンコードされます。
  • int32 vector — そこでは各位置がシングル・コードポイントを含みます。

例えば、次の 3 つの値は総て Unicode 文字列 “语言处理” (これは中国語で「言語処理」を意味します) を表します :

# Unicode string, represented as a UTF-8 encoded string scalar.
text_utf8 = tf.constant(u"语言处理")
text_utf8
<tf.Tensor: id=2, shape=(), dtype=string, numpy=b'\xe8\xaf\xad\xe8\xa8\x80\xe5\xa4\x84\xe7\x90\x86'>
# Unicode string, represented as a UTF-16-BE encoded string scalar.
text_utf16be = tf.constant(u"语言处理".encode("UTF-16-BE"))
text_utf16be
<tf.Tensor: id=3, shape=(), dtype=string, numpy=b'\x8b\xed\x8a\x00Y\x04t\x06'>
# Unicode string, represented as a vector of Unicode code points.
text_chars = tf.constant([ord(char) for char in u"语言处理"])
text_chars
<tf.Tensor: id=4, shape=(4,), dtype=int32, numpy=array([35821, 35328, 22788, 29702], dtype=int32)>

 

表現間の変換

TensorFlow はこれらの異なる表現間で変換する演算を提供します :

  • tf.strings.unicode_decode: エンコードされた文字列スカラーをコードポイントのベクトルに変換します。
  • tf.strings.unicode_encode: コードポイントのベクトルをエンコードされた文字列スカラーに変換します。
  • tf.strings.unicode_transcode: エンコードされた文字列スカラーを異なるエンコーディングに変換します。
tf.strings.unicode_decode(text_utf8,
                          input_encoding='UTF-8')
<tf.Tensor: id=8, shape=(4,), dtype=int32, numpy=array([35821, 35328, 22788, 29702], dtype=int32)>
tf.strings.unicode_encode(text_chars,
                          output_encoding='UTF-8')
<tf.Tensor: id=18, shape=(), dtype=string, numpy=b'\xe8\xaf\xad\xe8\xa8\x80\xe5\xa4\x84\xe7\x90\x86'>
tf.strings.unicode_transcode(text_utf8,
                             input_encoding='UTF8',
                             output_encoding='UTF-16-BE')
<tf.Tensor: id=19, shape=(), dtype=string, numpy=b'\x8b\xed\x8a\x00Y\x04t\x06'>

 

バッチ次元

マルチ文字列をデコードするとき、各文字列の文字数は同じではないかもしれません。return 結果は tf.RaggedTensor で、そこでは最内部 (= innermost) の次元は各文字列の文字数に依拠して変化します :

# A batch of Unicode strings, each represented as a UTF8-encoded string.
batch_utf8 = [s.encode('UTF-8') for s in
              [u'hÃllo',  u'What is the weather tomorrow',  u'Göödnight', u'😊']]
batch_chars_ragged = tf.strings.unicode_decode(batch_utf8,
                                               input_encoding='UTF-8')
for sentence_chars in batch_chars_ragged.to_list():
  print(sentence_chars)
[104, 195, 108, 108, 111]
[87, 104, 97, 116, 32, 105, 115, 32, 116, 104, 101, 32, 119, 101, 97, 116, 104, 101, 114, 32, 116, 111, 109, 111, 114, 114, 111, 119]
[71, 246, 246, 100, 110, 105, 103, 104, 116]
[128522]

この tf.RaggedTensor を直接使用することができますし、あるいはパディングか (メソッド tf.RaggedTensor.to_tensortf.RaggedTensor.to_sparse を使用して) tf.SparseTensor でそれを密な tf.Tensor に変換できます。

batch_chars_padded = batch_chars_ragged.to_tensor(default_value=-1)
print(batch_chars_padded.numpy())
[[   104    195    108    108    111     -1     -1     -1     -1     -1
      -1     -1     -1     -1     -1     -1     -1     -1     -1     -1
      -1     -1     -1     -1     -1     -1     -1     -1]
 [    87    104     97    116     32    105    115     32    116    104
     101     32    119    101     97    116    104    101    114     32
     116    111    109    111    114    114    111    119]
 [    71    246    246    100    110    105    103    104    116     -1
      -1     -1     -1     -1     -1     -1     -1     -1     -1     -1
      -1     -1     -1     -1     -1     -1     -1     -1]
 [128522     -1     -1     -1     -1     -1     -1     -1     -1     -1
      -1     -1     -1     -1     -1     -1     -1     -1     -1     -1
      -1     -1     -1     -1     -1     -1     -1     -1]]
batch_chars_sparse = batch_chars_ragged.to_sparse()

マルチ文字列を同じ長さでエンコードするとき、tf.Tensor は入力として使用されるかもしれません :

tf.strings.unicode_encode([[99, 97, 116], [100, 111, 103], [ 99, 111, 119]],
                          output_encoding='UTF-8')
<tf.Tensor: id=119, shape=(3,), dtype=string, numpy=array([b'cat', b'dog', b'cow'], dtype=object)>

様々な長さのマルチ文字列をエンコードするとき、tf.RaggedTensor が入力として使用されるべきです :

tf.strings.unicode_encode(batch_chars_ragged, output_encoding='UTF-8')
<tf.Tensor: id=120, shape=(4,), dtype=string, numpy=
array([b'h\xc3\x83llo', b'What is the weather tomorrow',
       b'G\xc3\xb6\xc3\xb6dnight', b'\xf0\x9f\x98\x8a'], dtype=object)>

パッドされたか sparse 形式のマルチ文字列を持つ tensor を持つ場合、unicode_encode を呼び出す前にそれを tf.RaggedTensor に変換します :

tf.strings.unicode_encode(
    tf.RaggedTensor.from_sparse(batch_chars_sparse),
    output_encoding='UTF-8')

tf.strings.unicode_encode(
    tf.RaggedTensor.from_tensor(batch_chars_padded, padding=-1),
    output_encoding='UTF-8')

 

Unicode 演算

文字長 (= Character length)

tf.strings.length 演算はパラメータ・ユニットを持ち、これは長さがどのように計算されるべきであるかを示します。ユニットのデフォルトは “BYTE” ですが、これは各エンコードされた文字列で Unicode コードポイントの数を決定するために “UTF8_CHAR” や “UTF16_CHAR” のような他の値に設定できます。

# Note that the final character takes up 4 bytes in UTF8.
thanks = u'Thanks 😊'.encode('UTF-8')
num_bytes = tf.strings.length(thanks).numpy()
num_chars = tf.strings.length(thanks, unit='UTF8_CHAR').numpy()
print('{} bytes; {} UTF-8 characters'.format(num_bytes, num_chars))
11 bytes; 8 UTF-8 characters

 

文字部分文字列 (= Character substrings)

同様に、tf.strings.substr 演算は “unit” パラメータを受け取り、そして “pos” と “len” パラメータがどのような種類のオフセットを含むかを決定するためにそれを使用します。

# default: unit='BYTE'. With len=1, we return a single byte.
tf.strings.substr(thanks, pos=7, len=1).numpy()
b'\xf0'
# Specifying unit='UTF8_CHAR', we return a single character, which in this case
# is 4 bytes.
print(tf.strings.substr(thanks, pos=7, len=1, unit='UTF8_CHAR').numpy())
b'\xf0\x9f\x98\x8a'

 

Unicode 文字列を分割する

tf.strings.unicode_split 演算は unicode 文字列を個々の文字の部分文字列に分割します :

tf.strings.unicode_split(thanks, 'UTF-8').numpy()
array([b'T', b'h', b'a', b'n', b'k', b's', b' ', b'\xf0\x9f\x98\x8a'],
      dtype=object)

 

文字のためのバイト・オフセット

元の文字列で tf.strings.unicode_decode により生成された文字 tensor をアラインするには、どこで文字が始まるかのためのオフセットを知ることは有用です。メソッド tf.strings.unicode_decode_with_offsets は unicode_decode に類似しています、それが各文字の開始オフセットを含む 2 番目の tensor を返すことを除いて。

codepoints, offsets = tf.strings.unicode_decode_with_offsets(u"🎈🎉🎊", 'UTF-8')

for (codepoint, offset) in zip(codepoints.numpy(), offsets.numpy()):
  print("At byte offset {}: codepoint {}".format(offset, codepoint))
At byte offset 0: codepoint 127880
At byte offset 4: codepoint 127881
At byte offset 8: codepoint 127882

 

Unicode スクリプト

各 Unicode コードポイントは スクリプト として知られるコードポイントの単一コレクションに属します。文字のスクリプトは文字がどの言語にあるかを決定するのに役立ちます。例えば、’Б’ がキリル文字のスクリプトにあることを知ることはその文字を含む現代のテキストはロシア語やウクライナ語のようなスラヴ語 (= Slavic language) に由来することを示します。

TensorFlow は与えられたコードポイントがどのスクリプトを使用するかを決定するために tf.strings.unicode_script 演算を提供します。スクリプト・コードは International Components for Unicode (ICU) UScriptCode 値に対応する int32 値です。

uscript = tf.strings.unicode_script([33464, 1041])  # ['芸', 'Б']

print(uscript.numpy())  # [17, 8] == [USCRIPT_HAN, USCRIPT_CYRILLIC]
[17  8]

tf.strings.unicode_script 演算はまたコードポイントのマルチ次元 tf.Tensors や tf.RaggedTensors にも適用できます :

print(tf.strings.unicode_script(batch_chars_ragged))
<tf.RaggedTensor [[25, 25, 25, 25, 25], [25, 25, 25, 25, 0, 25, 25, 0, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 0, 25, 25, 25, 25, 25, 25, 25, 25], [25, 25, 25, 25, 25, 25, 25, 25, 25], [0]]>

 

例: 単純なセグメンテーション

セグメンテーションはテキストを単語ライクな単位に分割するタスクです。これは単語を分離するためにスペース文字が使用されるときはしばしば容易ですが、(中国語や日本語のような) 幾つかの言語はスペースを使用せず、そして (ドイツ語のような) 幾つかの言語はそれらの意味を解析するために分割されなかればならない長い複合 (= compound) を含みます。web テキストでは、異なる言語とスクリプトは頻繁に一緒に混合されます、”NY株価” (New York Stock Exchange) 内のように。

単語境界を見積もるためにスクリプト内の変更を使用して (どのような ML モデルも実装することなく) 非常に大雑把なセグメンテーションを遂行できます。これは上の “NY株価” サンプルのような文字列のために動作します。それはまたスペースを使用する殆どの言語のためにも動作します、何故ならば様々なスクリプトのスペース文字は総て USCRIPT_COMMON、任意の実際のテキストのコードとは異なる特殊なスクリプトコード、として総て分類されるからです。

# dtype: string; shape: [num_sentences]
#
# The sentences to process.  Edit this line to try out different inputs!
sentence_texts = [u'Hello, world.', u'世界こんにちは']

最初に、センテンスを文字コードポイントにデコードします、そして各文字のためのスクリプト識別子を見つけます。


# dtype: int32; shape: [num_sentences, (num_chars_per_sentence)]
#
# sentence_char_codepoint[i, j] is the codepoint for the j'th character in
# the i'th sentence.
sentence_char_codepoint = tf.strings.unicode_decode(sentence_texts, 'UTF-8')
print(sentence_char_codepoint)

# dtype: int32; shape: [num_sentences, (num_chars_per_sentence)]
#
# sentence_char_scripts[i, j] is the unicode script of the j'th character in
# the i'th sentence.
sentence_char_script = tf.strings.unicode_script(sentence_char_codepoint)
print(sentence_char_script)
<tf.RaggedTensor [[72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 46], [19990, 30028, 12371, 12435, 12395, 12385, 12399]]>
<tf.RaggedTensor [[25, 25, 25, 25, 25, 0, 0, 25, 25, 25, 25, 25, 0], [17, 17, 20, 20, 20, 20, 20]]>

次に、単語境界がどこに追加されるべきかを決定するためにこれらのスクリプト識別子を使用します。単語境界を各センテンスの最初、そしてスクリプトが前の文字と異なる各文字のために追加します :

# dtype: bool; shape: [num_sentences, (num_chars_per_sentence)]
#
# sentence_char_starts_word[i, j] is True if the j'th character in the i'th
# sentence is the start of a word.
sentence_char_starts_word = tf.concat(
    [tf.fill([sentence_char_script.nrows(), 1], True),
     tf.not_equal(sentence_char_script[:, 1:], sentence_char_script[:, :-1])],
    axis=1)

# dtype: int64; shape: [num_words]
#
# word_starts[i] is the index of the character that starts the i'th word (in
# the flattened list of characters from all sentences).
word_starts = tf.squeeze(tf.where(sentence_char_starts_word.values), axis=1)
print(word_starts)
tf.Tensor([ 0  5  7 12 13 15], shape=(6,), dtype=int64)

それからこれらの開始オフセットを総てのバッチからの単語のリストを含む RaggedTensor を構築するために使用できます :

# dtype: int32; shape: [num_words, (num_chars_per_word)]
#
# word_char_codepoint[i, j] is the codepoint for the j'th character in the
# i'th word.
word_char_codepoint = tf.RaggedTensor.from_row_starts(
    values=sentence_char_codepoint.values,
    row_starts=word_starts)
print(word_char_codepoint)
<tf.RaggedTensor [[72, 101, 108, 108, 111], [44, 32], [119, 111, 114, 108, 100], [46], [19990, 30028], [12371, 12435, 12395, 12385, 12399]]>

そして最後に、単語コードポイント RaggedTensor をセンテンスにセグメントし戻すことができます :

# dtype: int64; shape: [num_sentences]
#
# sentence_num_words[i] is the number of words in the i'th sentence.
sentence_num_words = tf.reduce_sum(
    tf.cast(sentence_char_starts_word, tf.int64),
    axis=1)

# dtype: int32; shape: [num_sentences, (num_words_per_sentence), (num_chars_per_word)]
#
# sentence_word_char_codepoint[i, j, k] is the codepoint for the k'th character
# in the j'th word in the i'th sentence.
sentence_word_char_codepoint = tf.RaggedTensor.from_row_lengths(
    values=word_char_codepoint,
    row_lengths=sentence_num_words)
print(sentence_word_char_codepoint)
<tf.RaggedTensor [[[72, 101, 108, 108, 111], [44, 32], [119, 111, 114, 108, 100], [46]], [[19990, 30028], [12371, 12435, 12395, 12385, 12399]]]>

最後の結果を読みやすくするために、それを UTF-8 文字列にエンコードし戻すことができます :

tf.strings.unicode_encode(sentence_word_char_codepoint, 'UTF-8').to_list()
[[b'Hello', b', ', b'world', b'.'],
 [b'\xe4\xb8\x96\xe7\x95\x8c',
  b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf']]
 

以上



TensorFlow 2.0 : Tutorials : データのロードと前処理 :- テキストをロードする

TensorFlow 2.0 : Beginner Tutorials : データのロードと前処理 :- テキストをロードする (翻訳/解説)

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

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

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、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/

 

データのロードと前処理 :- テキストをロードする

このチュートリアルはテキストファイルからのサンプルをロードするために tf.data.TextLineDataset をどのように使用するかのサンプルを提供します。TextLineDataset はテキストファイルからのデータセットを作成するために設計されています、そこでは各サンプルは元のファイルからのテキストの 1 行です。これは主として行ベースの任意のテキストデータ (例えば、詩やエラーログ) のために潜在的に有用です。

このチュートリアルでは、同じワーク Homer’s Illiad の 3 つの異なる英語翻訳を使用します、そしてテキストのシングル行が与えられたとき翻訳者を識別するためにモデルを訓練します。

 

セットアップ

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf

import tensorflow_datasets as tfds
import os

3 つの翻訳のテキストは次によります :

このチュートリアルで使用されるテキストファイルは幾つかの典型的な前処理タスクを受けています、殆どは何かを除去しています — ドキュメント・ヘッダとフッタ、行番号、章タイトルです。これらの軽く変換された (= munged) ファイルをローカルにダウンロードします。

DIRECTORY_URL = 'https://storage.googleapis.com/download.tensorflow.org/data/illiad/'
FILE_NAMES = ['cowper.txt', 'derby.txt', 'butler.txt']

for name in FILE_NAMES:
  text_dir = tf.keras.utils.get_file(name, origin=DIRECTORY_URL+name)
  
parent_dir = os.path.dirname(text_dir)

parent_dir
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/cowper.txt
819200/815980 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/derby.txt
811008/809730 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/illiad/butler.txt
811008/807992 [==============================] - 0s 0us/step

'/home/kbuilder/.keras/datasets'

 

テキストをデータセットにロードする

ファイルを通して反復して、各一つをそれ自身のデータセットにロードします。

各サンプルは個々にラベル付けされる必要がありますので、各一つに labeler 関数を適用するために tf.data.Dataset.map を使用します。これはデータセットの総てのサンプルに渡り反復し、 (example, label) ペアを返します。

def labeler(example, index):
  return example, tf.cast(index, tf.int64)  

labeled_data_sets = []

for i, file_name in enumerate(FILE_NAMES):
  lines_dataset = tf.data.TextLineDataset(os.path.join(parent_dir, file_name))
  labeled_dataset = lines_dataset.map(lambda ex: labeler(ex, i))
  labeled_data_sets.append(labeled_dataset)

これらのラベル付けされたデータセットを単一のデータセットに結合して、そしてそれをシャッフルします。

BUFFER_SIZE = 50000
BATCH_SIZE = 64
TAKE_SIZE = 5000
all_labeled_data = labeled_data_sets[0]
for labeled_dataset in labeled_data_sets[1:]:
  all_labeled_data = all_labeled_data.concatenate(labeled_dataset)
  
all_labeled_data = all_labeled_data.shuffle(
    BUFFER_SIZE, reshuffle_each_iteration=False)

tf.data.Dataset.take を使用して (example, label) ペアがどのようなものか見るためにプリントすることができます。numpy プロパティは各 Tensor の値を表示します。

for ex in all_labeled_data.take(5):
  print(ex)
(<tf.Tensor: id=74, shape=(), dtype=string, numpy=b'Fulfilling some, in others he shall fail,'>, <tf.Tensor: id=75, shape=(), dtype=int64, numpy=1>)
(<tf.Tensor: id=76, shape=(), dtype=string, numpy=b"Of straight-horn'd oxen, and your flowing cups">, <tf.Tensor: id=77, shape=(), dtype=int64, numpy=1>)
(<tf.Tensor: id=78, shape=(), dtype=string, numpy=b'him by the head, while Patroclus kept fast hold of his feet, and <tf.Tensor: id=79, shape=(), dtype=int64, numpy=2>)
(<tf.Tensor: id=80, shape=(), dtype=string, numpy=b"So thick and dark, about th' Ajaces stirr'd,">, <tf.Tensor: id=81, shape=(), dtype=int64, numpy=1>)
(<tf.Tensor: id=82, shape=(), dtype=string, numpy=b'Then, as the life ebbed out of you, you answered, O knight Patroclus:'>, <tf.Tensor: id=83, shape=(), dtype=int64, numpy=2>)

 

テキスト行を数値としてエンコードする

機械学習モデルは数値上で動作します、単語上ではありませんので、文字列値は数値のリストに変換される必要があります。それを行なうために、各一意の単語を一意の整数にマップします。

 

語彙を構築する

最初に、テキストを個々の一意な単語のコレクションにトークン化して語彙を構築します。TensorFlow と Python の両者でこれを行なう 2, 3 の方法があります。このチュートリアルのためには :

  1. 各サンプルの numpy 値に渡り反復する。
  2. tfds.features.text.Tokenizer を使用してそれをトークンに分割する。
  3. これらのトークンを Python set に集めます、重複を除去するためです。
  4. 後で使用するために語彙のサイズを得ます。
tokenizer = tfds.features.text.Tokenizer()

vocabulary_set = set()
for text_tensor, _ in all_labeled_data:
  some_tokens = tokenizer.tokenize(text_tensor.numpy())
  vocabulary_set.update(some_tokens)

vocab_size = len(vocabulary_set)
vocab_size
17178

 

サンプルをエンコードする

vocabulary_set を tfds.features.text.TokenTextEncoder に渡すことによりエンコーダを作成します。エンコーダの encode メソッドはテキストの文字列を取り整数のリストを返します。

encoder = tfds.features.text.TokenTextEncoder(vocabulary_set)

これを単一行の上で出力がどのようなものか見るために試すことができます。

example_text = next(iter(all_labeled_data))[0].numpy()
print(example_text)
b'Fulfilling some, in others he shall fail,'
encoded_example = encoder.encode(example_text)
print(encoded_example)
[8801, 4457, 10895, 9164, 12881, 7887, 2100]

今はデータセットの上でエンコーダをそれを tf.py_function にラッピングしてそれをデータセットの map メソッドに渡すことにより実行します。

def encode(text_tensor, label):
  encoded_text = encoder.encode(text_tensor.numpy())
  return encoded_text, label

def encode_map_fn(text, label):
  return tf.py_function(encode, inp=[text, label], Tout=(tf.int64, tf.int64))

all_encoded_data = all_labeled_data.map(encode_map_fn)

 

データセットをテストと訓練バッチに分割する

小さいテスト・データセットとより大きな訓練セットを作成するために tf.data.Dataset.taketf.data.Dataset.skip を使用します。

モデルに渡される前に、データセットはバッチ化される必要があります。典型的には、バッチ内部のサンプルは同じサイズと shape である必要があります。しかし、これらのデータセットのサンプルは総てが同じサイズではありません — テキストの各行は単語の異なる数を持っていました。そこでサンプルを同じサイズにパッドするために (batch の代わりに) tf.data.Dataset.padded_batch を使用します。

train_data = all_encoded_data.skip(TAKE_SIZE).shuffle(BUFFER_SIZE)
train_data = train_data.padded_batch(BATCH_SIZE, padded_shapes=([-1],[]))

test_data = all_encoded_data.take(TAKE_SIZE)
test_data = test_data.padded_batch(BATCH_SIZE, padded_shapes=([-1],[]))

今では、test_data と train_data は (example, label) ペアのコレクションではなく、バッチのコレクションです。各バッチは配列として現れる (多くのサンプル, 多くのラベル) のペアです。

例示するために :

sample_text, sample_labels = next(iter(test_data))

sample_text[0], sample_labels[0]
(<tf.Tensor: id=99547, shape=(16,), dtype=int64, numpy=
 array([ 8801,  4457, 10895,  9164, 12881,  7887,  2100,     0,     0,
            0,     0,     0,     0,     0,     0,     0])>,
 <tf.Tensor: id=99551, shape=(), dtype=int64, numpy=1>)

新しいトークン・エンコーディングを導入したので (パディングのために使用されるゼロ)、語彙サイズは 1 つ増えました。

vocab_size += 1

 

モデルを構築する

model = tf.keras.Sequential()

最初の層は整数表現を密ベクトル埋め込みに変換します。より多くの詳細については Word Embeddings チュートリアルを見てください。

model.add(tf.keras.layers.Embedding(vocab_size, 64))

次の層は Long Short-Term Memory 層で、これはモデルに単語をそれらの他の単語とのコンテキストで理解させます。LSTM 上の双方向ラッパーはその前とその後に来たデータポイントとの関係でデータポイントについて学習します。

model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)))

最後に一つまたはそれ以上の密結合層のシリーズを持ちます、最後の一つは出力層です。出力層は総てのラベルのための確率を生成します。最も高い確率を持つ一つはサンプルのラベルのモデル予測です。

# One or more dense layers.
# Edit the list in the `for` line to experiment with layer sizes.
for units in [64, 64]:
  model.add(tf.keras.layers.Dense(units, activation='relu'))

# Output layer. The first argument is the number of labels.
model.add(tf.keras.layers.Dense(3, activation='softmax'))

最後に、モデルをコンパイルします。softmax カテゴリー化モデルのためには、損失関数として sparse_categorical_crossentropy を使用します。他の optimizer も試すことができますが、adam は非常に一般的です。

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

 

モデルを訓練する

このデータ上で実行するこのモデルは妥当な結果を生成します (約 83%)。

model.fit(train_data, epochs=3, validation_data=test_data)
Epoch 1/3
697/697 [==============================] - 32s 46ms/step - loss: 0.5213 - accuracy: 0.7403 - val_loss: 0.0000e+00 - val_accuracy: 0.0000e+00
Epoch 2/3
697/697 [==============================] - 26s 37ms/step - loss: 0.2968 - accuracy: 0.8667 - val_loss: 0.3581 - val_accuracy: 0.8400
Epoch 3/3
697/697 [==============================] - 26s 37ms/step - loss: 0.2214 - accuracy: 0.9019 - val_loss: 0.3703 - val_accuracy: 0.8428

<tensorflow.python.keras.callbacks.History at 0x7efb903020f0>
eval_loss, eval_acc = model.evaluate(test_data)

print('\nEval loss: {:.3f}, Eval accuracy: {:.3f}'.format(eval_loss, eval_acc))
79/79 [==============================] - 3s 40ms/step - loss: 0.3703 - accuracy: 0.8428

Eval loss: 0.370, Eval accuracy: 0.843
 

以上



TensorFlow 2.0 : Tutorials : データのロードと前処理 :- 画像をロードする

TensorFlow 2.0 : Beginner Tutorials : データのロードと前処理 :- 画像をロードする (翻訳/解説)

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

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

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、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/

 

データのロードと前処理 :- 画像をロードする

このチュートリアルは tf.data を使用してどのように画像データセットをロードするかの単純なサンプルを提供します。

このサンプルで使用されるデータセットは画像のディレクトリとして分配されます、ディレクトリ毎に画像の 1 クラスです。

 

セットアップ

from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
AUTOTUNE = tf.data.experimental.AUTOTUNE
import IPython.display as display
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
tf.__version__
'2.1.0-dev20191003'

 

画像を取得する

どのような訓練を始める前でも、認識させたい新しいクラスについてネットワークに教えるために画像のセットが必要です。貴方は Google からの creative-commons ライセンスの花の画像のアーカイブを利用できます。

Note: 総ての画像は licensed CC-BY です、クリエイターは LICENSE.txt ファイルにリストされています。

import pathlib
data_dir = tf.keras.utils.get_file(origin='https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
                                         fname='flower_photos', untar=True)
data_dir = pathlib.Path(data_dir)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz
228818944/228813984 [==============================] - 5s 0us/step

ダウンロード後 (218 MB)、今は利用可能な花の写真のコピーを持つはずです。

ディレクトリは 5 つのサブディレクトリを含みます、クラス毎に一つです :

image_count = len(list(data_dir.glob('*/*.jpg')))
image_count
3670
CLASS_NAMES = np.array([item.name for item in data_dir.glob('*') if item.name != "LICENSE.txt"])
CLASS_NAMES
array(['daisy', 'roses', 'dandelion', 'sunflowers', 'tulips'],
      dtype='<U10')

各ディレクトリは花のそのタイプの画像を含みます。ここに幾つかのバラ (= roses) があります :

roses = list(data_dir.glob('roses/*'))

for image_path in roses[:3]:
    display.display(Image.open(str(image_path)))



 

keras.preprocessing を使用してロードする

画像をロードする単純な方法は keras.preprocessing を使用することです。

# The 1./255 is to convert from uint8 to float32 in range [0,1].
image_generator = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255)

ローダのために幾つかパラメータを定義します :

BATCH_SIZE = 32
IMG_HEIGHT = 224
IMG_WIDTH = 224
STEPS_PER_EPOCH = np.ceil(image_count/BATCH_SIZE)
train_data_gen = image_generator.flow_from_directory(directory=str(data_dir),
                                                     batch_size=BATCH_SIZE,
                                                     shuffle=True,
                                                     target_size=(IMG_HEIGHT, IMG_WIDTH),
                                                     classes = list(CLASS_NAMES))
Found 3670 images belonging to 5 classes.

バッチを調べます :

def show_batch(image_batch, label_batch):
  plt.figure(figsize=(10,10))
  for n in range(25):
      ax = plt.subplot(5,5,n+1)
      plt.imshow(image_batch[n])
      plt.title(CLASS_NAMES[label_batch[n]==1][0].title())
      plt.axis('off')
image_batch, label_batch = next(train_data_gen)
show_batch(image_batch, label_batch)

 

tf.data を使用してロードする

上の keras.preprocessing は便利ですが、2 つの欠点を持ちます :

  1. それは遅いです。パフォーマンス・セクション を見てください。
  2. それは細かい制御を欠きます。
  3. それは TensorFlow の残りの部分と上手く統合されていません。

ファイルを tf.data.Dataset としてロードするには最初にファイルパスの dataset を作成します :

list_ds = tf.data.Dataset.list_files(str(data_dir/'*/*'))
for f in list_ds.take(5):
  print(f.numpy())
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/7199968650_72afc16d31_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/14381787252_e8e12e277a_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/898102603_2d5152f09a.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/roses/568715474_bdb64ccc32.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/13539384593_23449f7332_n.jpg'

ファイルパスを (image_data, label) ペアに変換する短い pure-tensorflow 関数を書きます :

def get_label(file_path):
  # convert the path to a list of path components
  parts = tf.strings.split(file_path, '/')
  # The second to last is the class-directory
  return parts[-2] == CLASS_NAMES
def decode_img(img):
  # convert the compressed string to a 3D uint8 tensor
  img = tf.image.decode_jpeg(img, channels=3)
  # Use `convert_image_dtype` to convert to floats in the [0,1] range.
  img = tf.image.convert_image_dtype(img, tf.float32)
  # resize the image to the desired size.
  return tf.image.resize(img, [IMG_WIDTH, IMG_HEIGHT])
def process_path(file_path):
  label = get_label(file_path)
  # load the raw data from the file as a string
  img = tf.io.read_file(file_path)
  img = decode_img(img)
  return img, label

画像、ラベルのペアのデータセットを作成するために Dataset.map を使用します :

# Set `num_parallel_calls` so multiple images are loaded/processed in parallel.
labeled_ds = list_ds.map(process_path, num_parallel_calls=AUTOTUNE)
for image, label in labeled_ds.take(1):
  print("Image shape: ", image.numpy().shape)
  print("Label: ", label.numpy())
Image shape:  (224, 224, 3)
Label:  [False False False False  True]

 

訓練のための基本メソッド

このデータセットでモデルを訓練するためにデータに次を望むでしょう :

  • 上手くシャッフルされること。
  • バッチ化されること。
  • できる限り速くバッチが利用可能になること。

これらの特徴は tf.data api を使用して容易に追加できます。

def prepare_for_training(ds, cache=True, shuffle_buffer_size=1000):
  # This is a small dataset, only load it once, and keep it in memory.
  # use `.cache(filename)` to cache preprocessing work for datasets that don't
  # fit in memory.
  if cache:
    if isinstance(cache, str):
      ds = ds.cache(cache)
    else:
      ds = ds.cache()

  ds = ds.shuffle(buffer_size=shuffle_buffer_size)

  # Repeat forever
  ds = ds.repeat()

  ds = ds.batch(BATCH_SIZE)

  # `prefetch` lets the dataset fetch batches in the background while the model
  # is training.
  ds = ds.prefetch(buffer_size=AUTOTUNE)

  return ds
train_ds = prepare_for_training(labeled_ds)

image_batch, label_batch = next(iter(train_ds))
show_batch(image_batch.numpy(), label_batch.numpy())

 

パフォーマンス

Note: このセクションはパフォーマンスに役立つかもしれない 2, 3 の容易なトリックを単に示します。深いガイドについては、入力パイプライン・パフォーマンス を見てください。

調べるために、データセットのパフォーマンスを確認するための関数が最初にここにあります :

import time
default_timeit_steps = 1000

def timeit(ds, steps=default_timeit_steps):
  start = time.time()
  it = iter(ds)
  for i in range(steps):
    batch = next(it)
    if i%10 == 0:
      print('.',end='')
  print()
  end = time.time()

  duration = end-start
  print("{} batches: {} s".format(steps, duration))
  print("{:0.5f} Images/s".format(BATCH_SIZE*steps/duration))

2 つのデータ generator のスピードを比較しましょう :

# `keras.preprocessing`
timeit(train_data_gen)
....................................................................................................
1000 batches: 86.93303561210632 s
368.09942 Images/s
# `tf.data`
timeit(train_ds)
....................................................................................................
1000 batches: 7.023545026779175 s
4556.10377 Images/s

パフォーマンス獲得の大きか部分は .cache の使用に由来します。

uncached_ds = prepare_for_training(labeled_ds, cache=False)
timeit(uncached_ds)
....................................................................................................
1000 batches: 24.807150840759277 s
1289.95064 Images/s

データセットがメモリに収まらない場合には優位点の幾つかを維持するためにキャッシュファイルを使用します :

filecache_ds = prepare_for_training(labeled_ds, cache="./flowers.tfcache")
timeit(filecache_ds)
....................................................................................................
1000 batches: 16.97942090034485 s
1884.63436 Images/s
 

以上



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