<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Copyright 2018 The TensorFlow Authors.
Step1:  tf.dataを使って画像をロードする
<table class="tfo-notebook-buttons" align="left">
  <td>
    <a target="_blank" href="https
Step2:  データセットのダウンロードと検査
画像の取得
訓練を始める前に、ネットワークに認識すべき新しいクラスを教えるために画像のセットが必要です。最初に使うためのクリエイティブ・コモンズでライセンスされた花の画像のアーカイブを作成してあります。
Step3:  218MBをダウンロードすると、花の画像のコピーが使えるようになっているはずです。
Step4:  画像の検査
扱っている画像について知るために、画像のいくつかを見てみましょう。
Step5:  各画像のラベルの決定
ラベルを一覧してみます。
Step6:  ラベルにインデックスを割り当てます。
Step7:  ファイルとラベルのインデックスの一覧を作成します。
Step8:  画像の読み込みと整形
TensorFlowには画像を読み込んで処理するために必要なツールが備わっています。
Step9:  以下は生のデータです。
Step10:  画像のテンソルにデコードします。
Step11:  モデルに合わせてリサイズします。
Step12:  このあと使用するために、簡単な関数にまとめます。
Step13:  tf.data.Datasetの構築
画像のデータセット
tf.data.Datasetを構築する最も簡単な方法は、from_tensor_slicesメソッドを使うことです。
文字列の配列をスライスすると、文字列のデータセットが出来上がります。
Step14:  output_shapesとoutput_typesという2つのフィールドが、データセット中の要素の中身を示しています。この場合には、バイナリ文字列というスカラーのセットです。
Step15:  preprocess_imageをファイルパスのデータセットにマップすることで、画像を実行時にロードし整形する新しいデータセットを作成します。
Step16:  (image, label)のペアのデータセット
同じfrom_tensor_slicesメソッドを使ってラベルのデータセットを作ることができます。
Step17:  これらのデータセットは同じ順番なので、zipすることで(image, label)というペアのデータセットができます。
Step18:  新しいデータセットのshapesとtypesは、それぞれのフィールドを示すシェイプと型のタプルです。
Step19:  注：all_image_labelsやall_image_pathsのような配列がある場合、tf.data.dataset.Dataset.zipメソッドの代わりとなるのは、配列のペアをスライスすることです。
Step20:  基本的な訓練手法
このデータセットを使ってモデルの訓練を行うには、データが
よくシャッフルされ
バッチ化され
限りなく繰り返され
バッチが出来るだけ早く利用できる
ことが必要です。
これらの特性はtf.dataAPIを使えば簡単に付け加えることができます。
Step21:  注意すべきことがいくつかあります。
順番が重要です。
.repeatの前に.shuffleすると、エポックの境界を越えて要素がシャッフルされます。（他の要素がすべて出現する前に2回出現する要素があるかもしれません）
.batchの後に.shuffleすると、バッチの順番がシャッフルされますが、要素がバッチを越えてシャッフルされることはありません。
完全なシャッフルのため、buffer_sizeをデータセットと同じサイズに設定しています。データセットのサイズ未満の場合、値が大きいほど良くランダム化されますが、より多くのメモリーを使用します。
シャッフルバッファがいっぱいになってから要素が取り出されます。そのため、大きなbuffer_sizeがDatasetを使い始める際の遅延の原因になります。
シャッフルされたデータセットは、シャッフルバッファが完全に空になるまでデータセットが終わりであることを伝えません。.repeatによってDatasetが再起動されると、シャッフルバッファが一杯になるまでもう一つの待ち時間が発生します。
最後の問題は、tf.data.Dataset.applyメソッドを、融合されたtf.data.experimental.shuffle_and_repeat関数と組み合わせることで対処できます。
Step22:  データセットをモデルにつなぐ
tf.keras.applicationsからMobileNet v2のコピーを取得します。
これを簡単な転移学習のサンプルに使用します。
MobileNetの重みを訓練不可に設定します。
Step23:  このモデルは、入力が[-1,1]の範囲に正規化されていることを想定しています。
help(keras_applications.mobilenet_v2.preprocess_input)
<pre>
...
This function applies the "Inception" preprocessing which converts
the RGB values from [0, 255] to [-1, 1] 
...
</pre>
このため、データをMobileNetモデルに渡す前に、入力を[0,1]の範囲から[-1,1]の範囲に変換する必要があります。
Step24:  MobileNetは画像ごとに6x6の特徴量の空間を返します。
バッチを１つ渡してみましょう。
Step25:  MobileNetをラップしたモデルを作り、出力層であるtf.keras.layers.Denseの前に、tf.keras.layers.GlobalAveragePooling2Dで空間の軸に沿って平均値を求めます。
Step26:  期待したとおりの形状の出力が得られます。
Step27:  訓練手法を記述するためにモデルをコンパイルします。
Step28:  訓練可能な変数は2つ、全結合層のweightsとbiasです。
Step29:  モデルを訓練します。
普通は、エポックごとの本当のステップ数を指定しますが、ここではデモの目的なので3ステップだけとします。
Step30:  性能
注：このセクションでは性能の向上に役立ちそうな簡単なトリックをいくつか紹介します。詳しくは、Input Pipeline Performanceを参照してください。
上記の単純なパイプラインは、エポックごとにそれぞれのファイルを一つずつ読み込みます。これは、CPUを使ったローカルでの訓練では問題になりませんが、GPUを使った訓練では十分ではなく、いかなる分散訓練でも使うべきではありません。
調査のため、まず、データセットの性能をチェックする簡単な関数を定義します。
Step31:  現在のデータセットの性能は次のとおりです。
Step32:  キャッシュ
tf.data.Dataset.cacheを使うと、エポックを越えて計算結果を簡単にキャッシュできます。特に、データがメモリに収まるときには効果的です。
ここでは、画像が前処理（デコードとリサイズ）された後でキャッシュされます。
Step33:  メモリキャッシュを使う際の欠点のひとつは、実行の都度キャッシュを再構築しなければならないことです。このため、データセットがスタートするたびに同じだけ起動のための遅延が発生します。
Step34:  データがメモリに収まらない場合には、キャッシュファイルを使用します。
Step35:  キャッシュファイルには、キャッシュを再構築することなくデータセットを再起動できるという利点もあります。2回めがどれほど早いか見てみましょう。
Step36:  TFRecord ファイル
生の画像データ
TFRecordファイルは、バイナリの大きなオブジェクトのシーケンスを保存するための単純なフォーマットです。複数のサンプルを同じファイルに詰め込むことで、TensorFlowは複数のサンプルを一度に読み込むことができます。これは、特にGCSのようなリモートストレージサービスを使用する際の性能にとって重要です。
最初に、生の画像データからTFRecordファイルを構築します。
Step37:  次に、TFRecordファイルを読み込み、以前定義したpreprocess_image関数を使って画像のデコード/リフォーマットを行うデータセットを構築します。
Step38:  これを、前に定義済みのラベルデータセットとzipし、期待通りの(image,label)のペアを得ます。
Step39:  これは、cacheバージョンよりも低速です。前処理をキャッシュしていないからです。
シリアライズしたテンソル
前処理をTFRecordファイルに保存するには、前やったように前処理した画像のデータセットを作ります。
Step40:  .jpeg文字列のデータセットではなく、これはテンソルのデータセットです。
これをTFRecordファイルにシリアライズするには、まず、テンソルのデータセットを文字列のデータセットに変換します。
Step41:  前処理をキャッシュしたことにより、データはTFRecordファイルから非常に効率的にロードできます。テンソルを使用する前にデシリアライズすることを忘れないでください。
Step42:  次にラベルを追加し、以前と同じような標準的な処理を適用します。
<ASSISTANT_TASK:>
Python Code:
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
Explanation: Copyright 2018 The TensorFlow Authors.
End of explanation
import tensorflow.compat.v1 as tf
tf.__version__
AUTOTUNE = tf.data.experimental.AUTOTUNE
Explanation: tf.dataを使って画像をロードする
<table class="tfo-notebook-buttons" align="left">
  <td>
    <a target="_blank" href="https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/r1/tutorials/load_data/images.ipynb"><img src="https://www.tensorflow.org/images/colab_logo_32px.png" />Run in Google Colab</a>
  </td>
  <td>
    <a target="_blank" href="https://github.com/tensorflow/docs-l10n/blob/master/site/ja/r1/tutorials/load_data/images.ipynb"><img src="https://www.tensorflow.org/images/GitHub-Mark-32px.png" />View source on GitHub</a>
  </td>
</table>
Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳はベストエフォートであるため、この翻訳が正確であることや英語の公式ドキュメントの 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリtensorflow/docsにプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 docs-ja@tensorflow.org メーリングリストにご連絡ください。
このチュートリアルでは、'tf.data'を使って画像データセットをロードする簡単な例を示します。
このチュートリアルで使用するデータセットは、クラスごとに別々のディレクトリに別れた形で配布されています。
設定
End of explanation
import pathlib
data_root = tf.keras.utils.get_file('flower_photos','https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz', untar=True)
data_root = pathlib.Path(data_root)
print(data_root)
Explanation: データセットのダウンロードと検査
画像の取得
訓練を始める前に、ネットワークに認識すべき新しいクラスを教えるために画像のセットが必要です。最初に使うためのクリエイティブ・コモンズでライセンスされた花の画像のアーカイブを作成してあります。
End of explanation
for item in data_root.iterdir():
    print(item)
import random
all_image_paths = list(data_root.glob('*/*'))
all_image_paths = [str(path) for path in all_image_paths]
random.shuffle(all_image_paths)
image_count = len(all_image_paths)
image_count
all_image_paths
Explanation: 218MBをダウンロードすると、花の画像のコピーが使えるようになっているはずです。
End of explanation
import os
attributions = (data_root/"LICENSE.txt").open(encoding='utf-8').readlines()[4:]
attributions = [line.split(' CC-BY') for line in attributions]
attributions = dict(attributions)
import IPython.display as display
def caption_image(image_path):
    image_rel = pathlib.Path(image_path).relative_to(data_root)
    return "Image (CC BY 2.0) " + ' - '.join(attributions[str(image_rel)].split(' - ')[:-1])
    
for n in range(3):
    image_path = random.choice(all_image_paths)
    display.display(display.Image(image_path))
    print(caption_image(image_path))
    print()
Explanation: 画像の検査
扱っている画像について知るために、画像のいくつかを見てみましょう。
End of explanation
label_names = sorted(item.name for item in data_root.glob('*/') if item.is_dir())
label_names
Explanation: 各画像のラベルの決定
ラベルを一覧してみます。
End of explanation
label_to_index = dict((name, index) for index,name in enumerate(label_names))
label_to_index
Explanation: ラベルにインデックスを割り当てます。
End of explanation
all_image_labels = [label_to_index[pathlib.Path(path).parent.name]
                    for path in all_image_paths]
print("First 10 labels indices: ", all_image_labels[:10])
Explanation: ファイルとラベルのインデックスの一覧を作成します。
End of explanation
img_path = all_image_paths[0]
img_path
Explanation: 画像の読み込みと整形
TensorFlowには画像を読み込んで処理するために必要なツールが備わっています。
End of explanation
img_raw = tf.read_file(img_path)
print(repr(img_raw)[:100]+"...")
Explanation: 以下は生のデータです。
End of explanation
img_tensor = tf.image.decode_image(img_raw)
print(img_tensor.shape)
print(img_tensor.dtype)
Explanation: 画像のテンソルにデコードします。
End of explanation
img_final = tf.image.resize_images(img_tensor, [192, 192])
img_final = img_final/255.0
print(img_final.shape)
print(img_final.numpy().min())
print(img_final.numpy().max())
Explanation: モデルに合わせてリサイズします。
End of explanation
def preprocess_image(image):
    image = tf.image.decode_jpeg(image, channels=3)
    image = tf.image.resize_images(image, [192, 192])
    image /= 255.0  # normalize to [0,1] range
    return image
def load_and_preprocess_image(path):
    image = tf.read_file(path)
    return preprocess_image(image)
import matplotlib.pyplot as plt
image_path = all_image_paths[0]
label = all_image_labels[0]
plt.imshow(load_and_preprocess_image(img_path))
plt.grid(False)
plt.xlabel(caption_image(img_path))
plt.title(label_names[label].title())
print()
Explanation: このあと使用するために、簡単な関数にまとめます。
End of explanation
path_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)
Explanation: tf.data.Datasetの構築
画像のデータセット
tf.data.Datasetを構築する最も簡単な方法は、from_tensor_slicesメソッドを使うことです。
文字列の配列をスライスすると、文字列のデータセットが出来上がります。
End of explanation
print('shape: ', repr(path_ds.output_shapes))
print('type: ', path_ds.output_types)
print()
print(path_ds)
Explanation: output_shapesとoutput_typesという2つのフィールドが、データセット中の要素の中身を示しています。この場合には、バイナリ文字列というスカラーのセットです。
End of explanation
image_ds = path_ds.map(load_and_preprocess_image, num_parallel_calls=AUTOTUNE)
import matplotlib.pyplot as plt
plt.figure(figsize=(8,8))
for n,image in enumerate(image_ds.take(4)):
    plt.subplot(2,2,n+1)
    plt.imshow(image)
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])
    plt.xlabel(caption_image(all_image_paths[n]))
Explanation: preprocess_imageをファイルパスのデータセットにマップすることで、画像を実行時にロードし整形する新しいデータセットを作成します。
End of explanation
label_ds = tf.data.Dataset.from_tensor_slices(tf.cast(all_image_labels, tf.int64))
for label in label_ds.take(10):
    print(label_names[label.numpy()])
Explanation: (image, label)のペアのデータセット
同じfrom_tensor_slicesメソッドを使ってラベルのデータセットを作ることができます。
End of explanation
image_label_ds = tf.data.Dataset.zip((image_ds, label_ds))
Explanation: これらのデータセットは同じ順番なので、zipすることで(image, label)というペアのデータセットができます。
End of explanation
print('image shape: ', image_label_ds.output_shapes[0])
print('label shape: ', image_label_ds.output_shapes[1])
print('types: ', image_label_ds.output_types)
print()
print(image_label_ds)
Explanation: 新しいデータセットのshapesとtypesは、それぞれのフィールドを示すシェイプと型のタプルです。
End of explanation
ds = tf.data.Dataset.from_tensor_slices((all_image_paths, all_image_labels))
# The tuples are unpacked into the positional arguments of the mapped function
# タプルは展開され、マップ関数の位置引数に割り当てられます
def load_and_preprocess_from_path_label(path, label):
    return load_and_preprocess_image(path), label
image_label_ds = ds.map(load_and_preprocess_from_path_label)
image_label_ds
Explanation: 注：all_image_labelsやall_image_pathsのような配列がある場合、tf.data.dataset.Dataset.zipメソッドの代わりとなるのは、配列のペアをスライスすることです。
End of explanation
BATCH_SIZE = 32
# シャッフルバッファのサイズをデータセットと同じに設定することで、データが完全にシャッフルされる
# ようにできます。
ds = image_label_ds.shuffle(buffer_size=image_count)
ds = ds.repeat()
ds = ds.batch(BATCH_SIZE)
# `prefetch`を使うことで、モデルの訓練中にバックグラウンドでデータセットがバッチを取得できます。
ds = ds.prefetch(buffer_size=AUTOTUNE)
ds
Explanation: 基本的な訓練手法
このデータセットを使ってモデルの訓練を行うには、データが
よくシャッフルされ
バッチ化され
限りなく繰り返され
バッチが出来るだけ早く利用できる
ことが必要です。
これらの特性はtf.dataAPIを使えば簡単に付け加えることができます。
End of explanation
ds = image_label_ds.apply(
    tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds = ds.batch(BATCH_SIZE)
ds = ds.prefetch(buffer_size=AUTOTUNE)
ds
Explanation: 注意すべきことがいくつかあります。
順番が重要です。
.repeatの前に.shuffleすると、エポックの境界を越えて要素がシャッフルされます。（他の要素がすべて出現する前に2回出現する要素があるかもしれません）
.batchの後に.shuffleすると、バッチの順番がシャッフルされますが、要素がバッチを越えてシャッフルされることはありません。
完全なシャッフルのため、buffer_sizeをデータセットと同じサイズに設定しています。データセットのサイズ未満の場合、値が大きいほど良くランダム化されますが、より多くのメモリーを使用します。
シャッフルバッファがいっぱいになってから要素が取り出されます。そのため、大きなbuffer_sizeがDatasetを使い始める際の遅延の原因になります。
シャッフルされたデータセットは、シャッフルバッファが完全に空になるまでデータセットが終わりであることを伝えません。.repeatによってDatasetが再起動されると、シャッフルバッファが一杯になるまでもう一つの待ち時間が発生します。
最後の問題は、tf.data.Dataset.applyメソッドを、融合されたtf.data.experimental.shuffle_and_repeat関数と組み合わせることで対処できます。
End of explanation
mobile_net = tf.keras.applications.MobileNetV2(input_shape=(192, 192, 3), include_top=False)
mobile_net.trainable=False
Explanation: データセットをモデルにつなぐ
tf.keras.applicationsからMobileNet v2のコピーを取得します。
これを簡単な転移学習のサンプルに使用します。
MobileNetの重みを訓練不可に設定します。
End of explanation
def change_range(image,label):
    return 2*image-1, label
keras_ds = ds.map(change_range)
Explanation: このモデルは、入力が[-1,1]の範囲に正規化されていることを想定しています。
help(keras_applications.mobilenet_v2.preprocess_input)
<pre>
...
This function applies the "Inception" preprocessing which converts
the RGB values from [0, 255] to [-1, 1] 
...
</pre>
このため、データをMobileNetモデルに渡す前に、入力を[0,1]の範囲から[-1,1]の範囲に変換する必要があります。
End of explanation
# シャッフルバッファがいっぱいになるまで、データセットは何秒かかかります。
image_batch, label_batch = next(iter(keras_ds))
feature_map_batch = mobile_net(image_batch)
print(feature_map_batch.shape)
Explanation: MobileNetは画像ごとに6x6の特徴量の空間を返します。
バッチを１つ渡してみましょう。
End of explanation
model = tf.keras.Sequential([
    mobile_net,
    tf.keras.layers.GlobalAveragePooling2D(),
    tf.keras.layers.Dense(len(label_names))])
Explanation: MobileNetをラップしたモデルを作り、出力層であるtf.keras.layers.Denseの前に、tf.keras.layers.GlobalAveragePooling2Dで空間の軸に沿って平均値を求めます。
End of explanation
logit_batch = model(image_batch).numpy()
print("min logit:", logit_batch.min())
print("max logit:", logit_batch.max())
print()
print("Shape:", logit_batch.shape)
Explanation: 期待したとおりの形状の出力が得られます。
End of explanation
model.compile(optimizer=tf.train.AdamOptimizer(), 
              loss=tf.keras.losses.sparse_categorical_crossentropy,
              metrics=["accuracy"])
Explanation: 訓練手法を記述するためにモデルをコンパイルします。
End of explanation
len(model.trainable_variables) 
model.summary()
Explanation: 訓練可能な変数は2つ、全結合層のweightsとbiasです。
End of explanation
steps_per_epoch=tf.ceil(len(all_image_paths)/BATCH_SIZE).numpy()
steps_per_epoch
model.fit(ds, epochs=1, steps_per_epoch=3)
Explanation: モデルを訓練します。
普通は、エポックごとの本当のステップ数を指定しますが、ここではデモの目的なので3ステップだけとします。
End of explanation
import time
def timeit(ds, batches=2*steps_per_epoch+1):
    overall_start = time.time()
    # タイマーをスタートする前に、パイプラインの初期化の（シャッフルバッファを埋める）ため、
    # バッチを１つ取得します
    it = iter(ds.take(batches+1))
    next(it)
    start = time.time()
    for i,(images,labels) in enumerate(it):
        if i%10 == 0:
            print('.',end='')
    print()
    end = time.time()
    duration = end-start
    print("{} batches: {} s".format(batches, duration))
    print("{:0.5f} Images/s".format(BATCH_SIZE*batches/duration))
    print("Total time: {}s".format(end-overall_start))
Explanation: 性能
注：このセクションでは性能の向上に役立ちそうな簡単なトリックをいくつか紹介します。詳しくは、Input Pipeline Performanceを参照してください。
上記の単純なパイプラインは、エポックごとにそれぞれのファイルを一つずつ読み込みます。これは、CPUを使ったローカルでの訓練では問題になりませんが、GPUを使った訓練では十分ではなく、いかなる分散訓練でも使うべきではありません。
調査のため、まず、データセットの性能をチェックする簡単な関数を定義します。
End of explanation
ds = image_label_ds.apply(
    tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds = ds.batch(BATCH_SIZE).prefetch(buffer_size=AUTOTUNE)
ds
timeit(ds)
Explanation: 現在のデータセットの性能は次のとおりです。
End of explanation
ds = image_label_ds.cache()
ds = ds.apply(
    tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds = ds.batch(BATCH_SIZE).prefetch(buffer_size=AUTOTUNE)
ds
timeit(ds)
Explanation: キャッシュ
tf.data.Dataset.cacheを使うと、エポックを越えて計算結果を簡単にキャッシュできます。特に、データがメモリに収まるときには効果的です。
ここでは、画像が前処理（デコードとリサイズ）された後でキャッシュされます。
End of explanation
timeit(ds)
Explanation: メモリキャッシュを使う際の欠点のひとつは、実行の都度キャッシュを再構築しなければならないことです。このため、データセットがスタートするたびに同じだけ起動のための遅延が発生します。
End of explanation
ds = image_label_ds.cache(filename='./cache.tf-data')
ds = ds.apply(
    tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds = ds.batch(BATCH_SIZE).prefetch(1)
ds
timeit(ds)
Explanation: データがメモリに収まらない場合には、キャッシュファイルを使用します。
End of explanation
timeit(ds)
Explanation: キャッシュファイルには、キャッシュを再構築することなくデータセットを再起動できるという利点もあります。2回めがどれほど早いか見てみましょう。
End of explanation
image_ds = tf.data.Dataset.from_tensor_slices(all_image_paths).map(tf.read_file)
tfrec = tf.data.experimental.TFRecordWriter('images.tfrec')
tfrec.write(image_ds)
Explanation: TFRecord ファイル
生の画像データ
TFRecordファイルは、バイナリの大きなオブジェクトのシーケンスを保存するための単純なフォーマットです。複数のサンプルを同じファイルに詰め込むことで、TensorFlowは複数のサンプルを一度に読み込むことができます。これは、特にGCSのようなリモートストレージサービスを使用する際の性能にとって重要です。
最初に、生の画像データからTFRecordファイルを構築します。
End of explanation
image_ds = tf.data.TFRecordDataset('images.tfrec').map(preprocess_image)
Explanation: 次に、TFRecordファイルを読み込み、以前定義したpreprocess_image関数を使って画像のデコード/リフォーマットを行うデータセットを構築します。
End of explanation
ds = tf.data.Dataset.zip((image_ds, label_ds))
ds = ds.apply(
    tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds=ds.batch(BATCH_SIZE).prefetch(AUTOTUNE)
ds
timeit(ds)
Explanation: これを、前に定義済みのラベルデータセットとzipし、期待通りの(image,label)のペアを得ます。
End of explanation
paths_ds = tf.data.Dataset.from_tensor_slices(all_image_paths)
image_ds = paths_ds.map(load_and_preprocess_image)
image_ds
Explanation: これは、cacheバージョンよりも低速です。前処理をキャッシュしていないからです。
シリアライズしたテンソル
前処理をTFRecordファイルに保存するには、前やったように前処理した画像のデータセットを作ります。
End of explanation
ds = image_ds.map(tf.serialize_tensor)
ds
tfrec = tf.data.experimental.TFRecordWriter('images.tfrec')
tfrec.write(ds)
Explanation: .jpeg文字列のデータセットではなく、これはテンソルのデータセットです。
これをTFRecordファイルにシリアライズするには、まず、テンソルのデータセットを文字列のデータセットに変換します。
End of explanation
RESTORE_TYPE = image_ds.output_types
RESTORE_SHAPE = image_ds.output_shapes
ds = tf.data.TFRecordDataset('images.tfrec')
def parse(x):
    result = tf.parse_tensor(x, out_type=RESTORE_TYPE)
    result = tf.reshape(result, RESTORE_SHAPE)
    return result
ds = ds.map(parse, num_parallel_calls=AUTOTUNE)
ds
Explanation: 前処理をキャッシュしたことにより、データはTFRecordファイルから非常に効率的にロードできます。テンソルを使用する前にデシリアライズすることを忘れないでください。
End of explanation
ds = tf.data.Dataset.zip((ds, label_ds))
ds = ds.apply(
  tf.data.experimental.shuffle_and_repeat(buffer_size=image_count))
ds=ds.batch(BATCH_SIZE).prefetch(AUTOTUNE)
ds
timeit(ds)
Explanation: 次にラベルを追加し、以前と同じような標準的な処理を適用します。
End of explanation
<END_TASK>