日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TensorFlow tf.data 导入数据(tf.data官方教程) * * * * *

發布時間:2025/3/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TensorFlow tf.data 导入数据(tf.data官方教程) * * * * * 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文鏈接:https://blog.csdn.net/u014061630/article/details/80728694
TensorFlow版本:1.10.0 > Guide > Importing Data

導入數據(Reading data)

上一篇介紹了TensorFlow讀取數據的四種方法:tf.data、Feeding、QueueRunner、Preloaded data。

推薦:如何構建高性能的輸入 pipeline

本篇的內容主要介紹 tf.data API的使用

文章目錄

導入數據
??1. Dataset的基本機制
????1.1 了解 Dataset 的結構并嘗試創建 Dataset
????1.2 了解迭代器的作用,并創建 Iterator ?
????1.3 從迭代器中讀取數據 ?
????1.4 保存迭代器的狀態 ?
??2. 構建 Dataset ?
????2.1 基于 NumPy 數組構建Dataset ?
????2.2 基于 tf.data.TFRecordDataset 構建 Dataset ?
????2.3 基于 tf.data.FixedLengthRecordDataset 構建 Dataset ?
????2.4 基于 tf.data.TextLineDataset 構建 Dataset ?
????2.5 基于 tf.contrib.data.CsvDataset 構建 Dataset ?
????2.5 直接從文件讀取,解析數據 ?
??3. 用 Dataset.map() 進行數據預處理 ?
????3.1 從 tf.Example 中解析出數據 ?
????3.2 解碼圖片數據并調整其大小 / 直接從文件讀取文件 ?
????3.3 基于 tf.py_func 使用 Python 函數進行預處理 ?
??4. 數據集進行 batch ?
????4.1 最簡單的 batch(直接 stack) ?
????4.2 將 Tensor 填充成統一大小,然后 batch ?
??5. 訓練時數據集的配置 ?
????5.1 迭代多個 epoch ?
????5.2 隨機 shuffle 數據集 ?
????5.3 tf.data 和使用高階 API 的混合使用 ?
??????5.3.1 在 tf.train.MonitoredTrainingSession 中使用 tf.data ?
??????5.3.2 在 tf.estimator.Estimator 中使用 tf.data ?

基于 tf.data API,我們可以使用簡單的代碼來構建復雜的輸入 pipeline。 (例1,從分布式文件系統中讀取數據、進行預處理、合成為 batch、訓練中使用數據集;例2,文本模型的輸入 pipeline 需要從原始文本數據中提取符號、根據對照表將其轉換為嵌入標識符,以及將不同長度的序列組合成batch數據等。) 使用 tf.data API 可以輕松處理大量數據、不同的數據格式以及復雜的轉換。

tf.data API 在 TensorFlow 中引入了兩個新概念

  • tf.data.Dataset:表示一系列元素,其中每個元素包含一個或多個 Tensor 對象。例如,在圖片管道中,一個元素可能是單個訓練樣本,具有一對表示圖片數據和標簽的張量??梢酝ㄟ^兩種不同的方式來創建數據集。

    • 直接從 Tensor 創建 Dataset(例如 Dataset.from_tensor_slices());當然 Numpy 也是可以的,TensorFlow 會自動將其轉換為 Tensor。

    • 通過對一個或多個 tf.data.Dataset 對象來使用變換(例如 Dataset.batch())來創建 Dataset

  • tf.data.Iterator:這是從數據集中提取元素的主要方法。Iterator.get_next() 指令會在執行時生成 Dataset 的下一個元素,并且此指令通常充當輸入管道和模型之間的接口。最簡單的迭代器是“單次迭代器”,它會對處理好的 Dataset 進行單次迭代。要實現更復雜的用途,您可以通過 Iterator.initializer 指令使用不同的數據集重新初始化和參數化迭代器,這樣一來,您就可以在同一個程序中對訓練和驗證數據進行多次迭代(舉例而言)。

1. Dataset 的基本機制 ?

本部分將介紹:

  • Dataset 的基礎知識,并嘗試創建 Dataset
  • Iterator 的基礎知識,并嘗試創建 Iterator
  • 通過 Iterator 來提取 Dataset 中的數據
  • 要構建輸入 pipeline,你必須首先根據數據集的存儲方式選擇相應的方法創建 Dataset 對象來讀取數據。(如果你的數據在內存中,請使用tf.data.Dataset.from_tensors() 或 tf.data.Dataset.from_tensor_slices() 來創建 Dataset;如果你的數據是 tfrecord 格式的,那么請使用 tf.data.TFRecordDataset 來創建 Dataset)

    有了 Dataset 對象以后,您就可以通過使用 tf.data.Dataset 對象的各種方法對其進行處理。例如,您可以對Dataset的每一個元素使用某種變換,例 Dataset.map()(為每個元素使用一個函數),也可以對多個元素使用某種變換(例如 Dataset.batch())。 要了解所有可用的變換,請參閱 tf.data.Dataset 的文檔。

    消耗 Dataset 中值的最常見方法是構建迭代器對象。通過迭代器對象,每次可以訪問數據集中的一個元素 (例如,通過調用 Dataset.make_one_shot_iterator())。 tf.data.Iterator 提供了兩個指令:Iterator.initializer,您可以通過此指令(重新)初始化迭代器的狀態;以及 Iterator.get_next(),此指令返回迭代器中的下一個元素的 tf.Tensor 對象。根據您的需求,您可以選擇不同類型的迭代器,下文將對此進行詳細介紹。

    1.1 了解 Dataset 的結構并嘗試創建 Dataset ?

    一個 Dataset 對象包含多個元素,每個元素的結構都相同。每個元素包含一個或多個 tf.Tensor 對象,這些對象被稱為組件。每個組件都有 tf.DType 屬性,表示 Tensor 中元素的類型;以及 tf.TensorShape 屬性,表示每個元素(可能部分指定)的靜態形狀。您可以通過 Dataset.output_types 和 Dataset.output_shapes 屬性檢查數據集元素各個組件的類型和形狀。Dataset 的屬性由構成該 Dataset 的元素的屬性映射得到,元素可以是單個張量、張量元組,也可以是張量的嵌套元組。例如:

    dataset1 = tf.data.Dataset.from_tensor_slices(tf.random_uniform([4, 10])) print(dataset1.output_types) # ==> "tf.float32" print(dataset1.output_shapes) # ==> "(10,)"dataset2 = tf.data.Dataset.from_tensor_slices((tf.random_uniform([4]),tf.random_uniform([4, 100], maxval=100, dtype=tf.int32))) print(dataset2.output_types) # ==> "(tf.float32, tf.int32)" print(dataset2.output_shapes) # ==> "((), (100,))"dataset3 = tf.data.Dataset.zip((dataset1, dataset2)) print(dataset3.output_types) # ==> (tf.float32, (tf.float32, tf.int32)) print(dataset3.output_shapes) # ==> "(10, ((), (100,)))"

    為 Dataset 中的元素的各個組件命名通常會帶來便利性(例如,元素的各個組件表示不同特征時)。除了元組之外,還可以使用 命名元組(collections.namedtuple) 或 字典 來表示 Dataset 的單個元素。

    dataset = tf.data.Dataset.from_tensor_slices({"a": tf.random_uniform([4]),"b": tf.random_uniform([4, 100], maxval=100, dtype=tf.int32)}) print(dataset.output_types) # ==> "{'a': tf.float32, 'b': tf.int32}" print(dataset.output_shapes) # ==> "{'a': (), 'b': (100,)}"

    Dataset 的變換支持任何結構的數據集。在使用 Dataset.map()、Dataset.flat_map() 和 Dataset.filter() 函數時(這些轉換會對每個元素應用一個函數),元素結構決定了函數的參數:

    dataset1 = dataset1.map(lambda x: ...)dataset2 = dataset2.flat_map(lambda x, y: ...)# Note: Argument destructuring is not available in Python 3. dataset3 = dataset3.filter(lambda x, (y, z): ...)

    1.2 了解迭代器的作用,并創建 Iterator ?

    構建了表示輸入數據的 Dataset 后,下一步就是創建 Iterator 來訪問該數據集中的元素。tf.data API 目前支持下列迭代器,其復雜程度逐漸上升:

  • 單次迭代器
  • 可初始化迭代器
  • 可重新初始化迭代器
  • 可 feeding 迭代器
  • 單次迭代器是最簡單的迭代器形式,僅支持對數據集進行一次迭代,不需要顯式初始化。單次迭代器可以處理現有的基于隊列的輸入管道支持的幾乎所有情況,但不支持參數化。以 Dataset.range() 為例:

    dataset = tf.data.Dataset.range(100) iterator = dataset.make_one_shot_iterator() next_element = iterator.get_next()for i in range(100):value = sess.run(next_element)assert i == value

    注意:目前,單次迭代器是唯一可輕松與 Estimator 配合使用的類型。

    您需要先運行顯式 iterator.initializer 指令,才能使用可初始化迭代器。雖然有些不便,但它允許您使用一個或多個 tf.placeholder() 張量(可在初始化迭代器時饋送)參數化數據集的定義。繼續以 Dataset.range() 為例:

    max_value = tf.placeholder(tf.int64, shape=[]) dataset = tf.data.Dataset.range(max_value) iterator = dataset.make_initializable_iterator() next_element = iterator.get_next()# Initialize an iterator over a dataset with 10 elements. sess.run(iterator.initializer, feed_dict={max_value: 10}) for i in range(10):value = sess.run(next_element)assert i == value# Initialize the same iterator over a dataset with 100 elements. sess.run(iterator.initializer, feed_dict={max_value: 100}) for i in range(100):value = sess.run(next_element)assert i == value

    可重新初始化迭代器 可以通過多個不同的 Dataset 對象進行初始化。例如,您可能有一個訓練輸入管道,它會對輸入圖片進行隨機擾動來改善泛化;還有一個驗證輸入管道,它會評估對未修改數據的預測。這些管道通常會使用不同的 Dataset 對象,這些對象具有相同的結構(即每個組件具有相同類型和兼容形狀)。

    # Define training and validation datasets with the same structure. training_dataset = tf.data.Dataset.range(100).map(lambda x: x + tf.random_uniform([], -10, 10, tf.int64)) validation_dataset = tf.data.Dataset.range(50)# A reinitializable iterator is defined by its structure. We could use the # `output_types` and `output_shapes` properties of either `training_dataset` # or `validation_dataset` here, because they are compatible. iterator = tf.data.Iterator.from_structure(training_dataset.output_types,training_dataset.output_shapes) next_element = iterator.get_next()training_init_op = iterator.make_initializer(training_dataset) validation_init_op = iterator.make_initializer(validation_dataset)# Run 20 epochs in which the training dataset is traversed, followed by the # validation dataset. for _ in range(20):# Initialize an iterator over the training dataset.sess.run(training_init_op)for _ in range(100):sess.run(next_element)# Initialize an iterator over the validation dataset.sess.run(validation_init_op)for _ in range(50):sess.run(next_element)

    可 feeding 迭代器 可以與 tf.placeholder 一起使用,通過熟悉的 feed_dict 機制來選擇每次調用 tf.Session.run 時所使用的 Iterator。它提供的功能與可重新初始化迭代器的相同,但在迭代器之間切換時不需要從數據集的開頭初始化迭代器。例如,以上面的同一訓練和驗證數據集為例,您可以使用 tf.data.Iterator.from_string_handle 定義一個可讓您在兩個數據集之間切換的可 feeding 迭代器:

    # Define training and validation datasets with the same structure. training_dataset = tf.data.Dataset.range(100).map(lambda x: x + tf.random_uniform([], -10, 10, tf.int64)).repeat() validation_dataset = tf.data.Dataset.range(50)# A feedable iterator is defined by a handle placeholder and its structure. We # could use the `output_types` and `output_shapes` properties of either # `training_dataset` or `validation_dataset` here, because they have # identical structure. handle = tf.placeholder(tf.string, shape=[]) iterator = tf.data.Iterator.from_string_handle(handle, training_dataset.output_types, training_dataset.output_shapes) next_element = iterator.get_next()# You can use feedable iterators with a variety of different kinds of iterator # (such as one-shot and initializable iterators). training_iterator = training_dataset.make_one_shot_iterator() validation_iterator = validation_dataset.make_initializable_iterator()# The `Iterator.string_handle()` method returns a tensor that can be evaluated # and used to feed the `handle` placeholder. training_handle = sess.run(training_iterator.string_handle()) validation_handle = sess.run(validation_iterator.string_handle())# Loop forever, alternating between training and validation. while True:# Run 200 steps using the training dataset. Note that the training dataset is# infinite, and we resume from where we left off in the previous `while` loop# iteration.for _ in range(200):sess.run(next_element, feed_dict={handle: training_handle})# Run one pass over the validation dataset.sess.run(validation_iterator.initializer)for _ in range(50):sess.run(next_element, feed_dict={handle: validation_handle})

    1.3 從迭代器中讀取數據 ?

    Iterator.get_next() 方法返回一個或多個 tf.Tensor 對象,這些對象對應于迭代器的下一個元素。每次 eval 這些張量時,它們都會獲取底層數據集中下一個元素的值。(請注意,與 TensorFlow 中的其他有狀態對象一樣,調用 Iterator.get_next() 并不會立即使迭代器進入下個狀態。相反,您必須使用 TensorFlow 表達式中返回的 tf.Tensor 對象,并將該表達式的結果傳遞到tf.Session.run(),以獲取下一個元素并使迭代器進入下個狀態。)

    如果迭代器到達數據集的末尾,則執行 Iterator.get_next() 指令會產生 tf.errors.OutOfRangeError。在此之后,迭代器將處于不可用狀態;如果需要繼續使用,則必須對其重新初始化。

    dataset = tf.data.Dataset.range(5) iterator = dataset.make_initializable_iterator() next_element = iterator.get_next()# Typically `result` will be the output of a model, or an optimizer's # training operation. result = tf.add(next_element, next_element)sess.run(iterator.initializer) print(sess.run(result)) # ==> "0" print(sess.run(result)) # ==> "2" print(sess.run(result)) # ==> "4" print(sess.run(result)) # ==> "6" print(sess.run(result)) # ==> "8" try:sess.run(result) except tf.errors.OutOfRangeError:print("End of dataset") # ==> "End of dataset"

    一種常用的方法是將“訓練循環”封裝在 try-except 塊中:

    sess.run(iterator.initializer) while True:try:sess.run(result)except tf.errors.OutOfRangeError:break

    如果數據集的每個元素都具有嵌套結構,則 Iterator.get_next() 的返回值將是一個或多個 tf.Tensor 對象,這些對象具有相同的嵌套結構:

    dataset1 = tf.data.Dataset.from_tensor_slices(tf.random_uniform([4, 10])) dataset2 = tf.data.Dataset.from_tensor_slices((tf.random_uniform([4]), tf.random_uniform([4, 100]))) dataset3 = tf.data.Dataset.zip((dataset1, dataset2))iterator = dataset3.make_initializable_iterator()sess.run(iterator.initializer) next1, (next2, next3) = iterator.get_next()

    注意:next1、next2、next3 由相同的 op / node 產生,因此eval next1、next2 或 next3 中的任何一個都會使所有組件的迭代器進入下個狀態。

    1.4 保存迭代器的狀態 ?

    tf.contrib.data.make_saveable_from_iterator 函數會從迭代器創建一個 SaveableObject,這個對象可以用來保存、恢復迭代器的當前狀態(甚至是整個輸入 pipeline)。

    # Create saveable object from iterator. saveable = tf.contrib.data.make_saveable_from_iterator(iterator)# Save the iterator state by adding it to the saveable objects collection. tf.add_to_collection(tf.GraphKeys.SAVEABLE_OBJECTS, saveable) saver = tf.train.Saver()with tf.Session() as sess:if should_checkpoint:saver.save(path_to_checkpoint)# Restore the iterator state. with tf.Session() as sess:saver.restore(sess, path_to_checkpoint)

    2. 構建 Dataset ?

    2.1 基于 NumPy 數組構建Dataset ?

    如果您的所有輸入數據都適合存儲在內存中,則根據輸入數據創建 Dataset 的最簡單方法是將它們轉換為 tf.Tensor 對象,并使用 Dataset.from_tensor_slices()。

    # Load the training data into two NumPy arrays, for example using `np.load()`. with np.load("/var/data/training_data.npy") as data:features = data["features"]labels = data["labels"]# Assume that each row of `features` corresponds to the same row as `labels`. assert features.shape[0] == labels.shape[0]dataset = tf.data.Dataset.from_tensor_slices((features, labels))

    注意:上面的代碼段會將 features 和 labels 數組作為 tf.constant() 指令嵌入在 TensorFlow 圖中。這非常適合小型數據集,但會浪費內存,因為這會多次復制數組的內容,并可能會達到 tf.GraphDef 協議緩沖區的 2GB 上限。

    作為替代方案,您可以基于 tf.placeholder() 張量定義 Dataset,并使用可初始化 Iterator,然后在初始化 dataset 的 Iterator 時將 NumPy 數組供給程序。

    # Load the training data into two NumPy arrays, for example using `np.load()`. with np.load("/var/data/training_data.npy") as data:features = data["features"]labels = data["labels"]# Assume that each row of `features` corresponds to the same row as `labels`. assert features.shape[0] == labels.shape[0]features_placeholder = tf.placeholder(features.dtype, features.shape) labels_placeholder = tf.placeholder(labels.dtype, labels.shape)dataset = tf.data.Dataset.from_tensor_slices((features_placeholder, labels_placeholder)) # [Other transformations on `dataset`...] dataset = ... iterator = dataset.make_initializable_iterator()sess.run(iterator.initializer, feed_dict={features_placeholder: features,labels_placeholder: labels})

    2.2 基于 tf.data.TFRecordDataset 構建 Dataset ?

    tf.data API 支持多種文件格式,因此您可以處理那些不適合存儲在內存中的大型數據集。例如,TFRecord 文件格式是一種面向記錄的簡單二進制格式,很多 TensorFlow 應用采用此格式來訓練數據。通過 tf.data.TFRecordDataset 類,您可以將一個或多個 TFRecord 文件的內容作為輸入管道的一部分進行流式傳輸。

    # Creates a dataset that reads all of the examples from two files. filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] dataset = tf.data.TFRecordDataset(filenames)

    TFRecordDataset 初始化程序的 filenames 參數可以是字符串、字符串列表,也可以是字符串 tf.Tensor。因此,如果您有兩組分別用于訓練和驗證的文件,則可以使用 tf.placeholder(tf.string) 來表示文件名,并使用適當的文件名初始化迭代器:

    filenames = tf.placeholder(tf.string, shape=[None]) dataset = tf.data.TFRecordDataset(filenames) #如何將數據解析(parse)為Tensor見 3.1 節 dataset = dataset.map(...) # Parse the record into tensors. dataset = dataset.repeat() # Repeat the input indefinitely. dataset = dataset.batch(32) iterator = dataset.make_initializable_iterator()# You can feed the initializer with the appropriate filenames for the current # phase of execution, e.g. training vs. validation.# Initialize `iterator` with training data. training_filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] sess.run(iterator.initializer, feed_dict={filenames: training_filenames})# Initialize `iterator` with validation data. validation_filenames = ["/var/data/validation1.tfrecord", ...] sess.run(iterator.initializer, feed_dict={filenames: validation_filenames})

    2.3 基于 tf.data.FixedLengthRecordDataset 構建 Dataset ?

    有很多數據集都是二進制文件。tf.data.FixedLengthRecordDataset 提供了一種從一個或多個二進制文件中讀取數據的簡單方法。給定一個或多個文件名,FixedLengthRecordDataset

    filenames = ["/var/data/file1.bin", "/var/data/file2.bin"] dataset = tf.data.FixedLengthRecordDataset(filenames, record_bytes, header_bytes, footer_bytes, buffer_size)
    • filenames : tf.string,包含一個或多個文件名;
    • record_bytes :tf.int64,一個 record 占的 bytes;
    • header_bytes :(可選)tf.int64,每個文件開頭需要跳過多少 bytes;
    • footer_bytes :(可選)tf.int64,每個文件結尾需要忽略多少 bytes;
    • buffer_size :(可選)tf.int64,讀取時,緩沖多少bytes;

    2.4 基于 tf.data.TextLineDataset 構建 Dataset ?

    很多數據集都是作為一個或多個文本文件分布的。tf.data.TextLineDataset 提供了一種從一個或多個文本文件中提取行的簡單方法。給定一個或多個文件名,TextLineDataset 會為這些文件的每行生成一個字符串值元素。像 TFRecordDataset 一樣,TextLineDataset 將 filenames 視為 tf.Tensor,因此您可以通過傳遞 tf.placeholder(tf.string) 來進行參數化。

    filenames = ["/var/data/file1.txt", "/var/data/file2.txt"] dataset = tf.data.TextLineDataset(filenames)

    默認情況下,TextLineDataset 每次讀取每個文件的一行,這可能是不是我們想要的,例如,如果文件以標題行開頭或包含評論??梢允褂?Dataset.skip() 和 Dataset.filter() 轉換來移除這些行。為了將這些轉換分別應用于每個文件,我們使用 Dataset.flat_map() 為每個文件創建一個嵌套的 Dataset。

    filenames = ["/var/data/file1.txt", "/var/data/file2.txt"]dataset = tf.data.Dataset.from_tensor_slices(filenames)# Use `Dataset.flat_map()` to transform each file as a separate nested dataset, # and then concatenate their contents sequentially into a single "flat" dataset. # * Skip the first line (header row). # * Filter out lines beginning with "#" (comments). dataset = dataset.flat_map(lambda filename: (tf.data.TextLineDataset(filename).skip(1).filter(lambda line: tf.not_equal(tf.substr(line, 0, 1), "#"))))

    2.5 基于 tf.contrib.data.CsvDataset 構建 Dataset ?

    csv 是一種以純文本方式儲存表格數據的文件格式。tf.contrib.data.CsvDataset 類提供了一種方式去從一個或多個符合 RFC 4180 規范的 CSV 文件中提取 records。

    # Creates a dataset that reads all of the records from two CSV files, each with # eight float columns filenames = ["/var/data/file1.csv", "/var/data/file2.csv"] record_defaults = [tf.float32] * 8 # Eight required float columns dataset = tf.contrib.data.CsvDataset(filenames, record_defaults)

    如果一些列是空的,你可以設置默認值:

    # Creates a dataset that reads all of the records from two CSV files, each with # four float columns which may have missing values record_defaults = [[0.0]] * 8 dataset = tf.contrib.data.CsvDataset(filenames, record_defaults)

    默認情況下,一個 CsvDataset 每次從文件中讀取一行,這可能不是想要的(例如:如果文件的 header line 應該被忽略;或者輸入中的一些列是不需要的)。可以使用 header 及 select_cols 參數完成這些想法:

    # Creates a dataset that reads all of the records from two CSV files, each with # four float columns which may have missing values record_defaults = [[0.0]] * 8 dataset = tf.contrib.data.CsvDataset(filenames, record_defaults)

    2.6 直接從文件讀取,解析數據 ?

    這一部分其實就是3.2節代碼所示

    3. 用 Dataset.map() 進行數據預處理 ?

    Dataset.map(f) 轉換通過將指定函數 f 應用于輸入數據集的每個元素來生成新數據集。此轉換基于 map() 函數(通常應用于函數式編程語言中的列表(和其他結構))。函數 f 會接受表示輸入中單個元素的 tf.Tensor 對象,并返回表示新數據集中單個元素的 tf.Tensor 對象。此函數的實現使用標準的 TensorFlow 指令將一個元素轉換為另一個元素。

    本部分介紹了如何使用 Dataset.map() 的常見示例。

    3.1 從 tf.Example 中解析出數據 ?

    很多輸入管道都從 TFRecord 格式的文件(例如使用 tf.python_io.TFRecordWriter 編寫)中提取 tf.train.Example 協議緩沖區消息。每個 tf.train.Example 記錄都包含一個或多個“特征”,輸入管道通常會將這些特征轉換為張量。

    # Transforms a scalar string `example_proto` into a pair of a scalar string and # a scalar integer, representing an image and its label, respectively. def _parse_function(example_proto):features = {"image": tf.FixedLenFeature((), tf.string, default_value=""),"label": tf.FixedLenFeature((), tf.int32, default_value=0)}parsed_features = tf.parse_single_example(example_proto, features)return parsed_features["image"], parsed_features["label"]# Creates a dataset that reads all of the examples from two files, and extracts # the image and label features. filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] dataset = tf.data.TFRecordDataset(filenames) dataset = dataset.map(_parse_function)

    3.2 解碼圖片數據并調整其大小 / 直接從文件讀取文件 ?

    在用真實的圖片數據訓練神經網絡時,通常需要將不同大小的圖片轉換為通用大小,這樣就可以將它們批處理為具有固定大小的數據。

    # Reads an image from a file, decodes it into a dense tensor, and resizes it # to a fixed shape. def _parse_function(filename, label):image_string = tf.read_file(filename)image_decoded = tf.image.decode_image(image_string)image_resized = tf.image.resize_images(image_decoded, [28, 28])return image_resized, label# A vector of filenames. filenames = tf.constant(["/var/data/image1.jpg", "/var/data/image2.jpg", ...])# `labels[i]` is the label for the image in `filenames[i]. labels = tf.constant([0, 37, ...])dataset = tf.data.Dataset.from_tensor_slices((filenames, labels)) dataset = dataset.map(_parse_function)

    3.3 基于 tf.py_func 使用 Python 函數進行預處理 ?

    為了確保性能,我們建議您盡可能使用 TensorFlow 指令預處理數據。不過,在解析輸入數據時,調用外部 Python 庫有時很有用。為此,請在 Dataset.map() 轉換中調用 tf.py_func() 指令。

    # tf.py_func tf.py_func(func, # 一個Python函數inp, # 一個Tensor列表Tout, # 輸出的Tensor的dtype或Tensors的dtype列表stateful=True, # 布爾值,輸入值相同,輸出值就相同,那么就將stateful設置為Falsename=None)

    下面是一個借助opencv進行圖像預處理的例子:

    import cv2# Use a custom OpenCV function to read the image, instead of the standard # TensorFlow `tf.read_file()` operation. def _read_py_function(filename, label):image_decoded = cv2.imread(filename.decode(), cv2.IMREAD_GRAYSCALE)return image_decoded, label# Use standard TensorFlow operations to resize the image to a fixed shape. def _resize_function(image_decoded, label):image_decoded.set_shape([None, None, None])image_resized = tf.image.resize_images(image_decoded, [28, 28])return image_resized, labelfilenames = ["/var/data/image1.jpg", "/var/data/image2.jpg", ...] labels = [0, 37, 29, 1, ...]dataset = tf.data.Dataset.from_tensor_slices((filenames, labels)) dataset = dataset.map(lambda filename, label: tuple(tf.py_func(_read_py_function, [filename, label], [tf.uint8, label.dtype]))) dataset = dataset.map(_resize_function)

    4. 數據集進行 batch ?

    4.1 最簡單的 batch(直接 stack) ?

    最簡單的 batch 處理方法是將數據集中的 nnn 個連續元素堆疊為一個元素。Dataset.batch() 轉換正是這么做的,它與 tf.stack() 運算符具有相同的限制(被應用于元素的每個組件):即對于每個組件 iii,所有元素的張量形狀必須完全相同。

    inc_dataset = tf.data.Dataset.range(100) dec_dataset = tf.data.Dataset.range(0, -100, -1) dataset = tf.data.Dataset.zip((inc_dataset, dec_dataset)) batched_dataset = dataset.batch(4)iterator = batched_dataset.make_one_shot_iterator() next_element = iterator.get_next()print(sess.run(next_element)) # ==> ([0, 1, 2, 3], [ 0, -1, -2, -3]) print(sess.run(next_element)) # ==> ([4, 5, 6, 7], [-4, -5, -6, -7]) print(sess.run(next_element)) # ==> ([8, 9, 10, 11], [-8, -9, -10, -11])

    4.2 將 Tensor 填充成統一大小,然后 batch ?

    使用填充批處理張量
    上述方法適用于具有相同大小的張量。不過,很多模型(例如序列模型)處理的輸入數據可能具有不同的大小(例如序列的長度不同)。為了解決這種情況,可以通過 Dataset.padded_batch() 轉換來指定一個或多個會被填充的維度,從而批處理不同形狀的張量。

    dataset = tf.data.Dataset.range(100) dataset = dataset.map(lambda x: tf.fill([tf.cast(x, tf.int32)], x)) dataset = dataset.padded_batch(4, padded_shapes=[None])iterator = dataset.make_one_shot_iterator() next_element = iterator.get_next()print(sess.run(next_element)) # ==> [[0, 0, 0], # [1, 0, 0], # [2, 2, 0], # [3, 3, 3]]print(sess.run(next_element)) # ==> [[4, 4, 4, 4, 0, 0, 0],# [5, 5, 5, 5, 5, 0, 0],# [6, 6, 6, 6, 6, 6, 0],# [7, 7, 7, 7, 7, 7, 7]]

    您可以通過 Dataset.padded_batch() 轉換為每個組件的每個維度設置不同的填充,并且可以采用可變長度(在上面的示例中用 None 表示)或恒定長度。也可以替換填充值,默認設置為 0。

    5. 訓練時數據集的配置 ?

    5.1 迭代多個 epoch ?

    tf.data API 提供了兩種主要方式來處理同一數據的多個周期。

    要迭代數據集多個周期,最簡單的方法是使用 Dataset.repeat()。例如,要創建一個將其輸入重復 10 個周期的數據集:

    filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] dataset = tf.data.TFRecordDataset(filenames) dataset = dataset.map(...) dataset = dataset.repeat(10) dataset = dataset.batch(32)

    應用不帶參數的 Dataset.repeat() 轉換將無限次地重復輸入。Dataset.repeat() 轉換將其參數連接起來,而不會在一個周期結束和下一個周期開始時發出信號。

    如果您想在每個周期結束時收到信號,則可以編寫在數據集結束時捕獲 tf.errors.OutOfRangeError的訓練循環。此時,您可以收集關于該周期的一些統計信息(例如驗證錯誤)。

    filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] dataset = tf.data.TFRecordDataset(filenames) dataset = dataset.map(...) dataset = dataset.batch(32) iterator = dataset.make_initializable_iterator() next_element = iterator.get_next()# Compute for 100 epochs. for _ in range(100):sess.run(iterator.initializer)while True:try:sess.run(next_element)except tf.errors.OutOfRangeError:break# [Perform end-of-epoch calculations here.]

    5.2 隨機 shuffle 數據集 ?

    Dataset.shuffle() 轉換使用一個類似于 tf.RandomShuffleQueue 的算法來隨機重排輸入數據集:它保留一個固定大小的緩沖區,并以相同方式從此緩沖區中隨機選擇下一個元素。

    filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] dataset = tf.data.TFRecordDataset(filenames) dataset = dataset.map(...) dataset = dataset.shuffle(buffer_size=10000) dataset = dataset.batch(32) dataset = dataset.repeat()

    5.3 tf.data 和使用高階 API 的混合使用 ?

    5.3.1 在 tf.train.MonitoredTrainingSession 中使用 tf.data ?

    tf.train.MonitoredTrainingSession API 簡化了在分布式設置下運行 TensorFlow 的很多方面。MonitoredTrainingSession 使用 tf.errors.OutOfRangeError 表示訓練已完成,因此要將其與 tf.data API 結合使用,我們建議使用 Dataset.make_one_shot_iterator()。例如:

    filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"] dataset = tf.data.TFRecordDataset(filenames) dataset = dataset.map(...) dataset = dataset.shuffle(buffer_size=10000) dataset = dataset.batch(32) dataset = dataset.repeat(num_epochs) iterator = dataset.make_one_shot_iterator()next_example, next_label = iterator.get_next() loss = model_function(next_example, next_label)training_op = tf.train.AdagradOptimizer(...).minimize(loss)with tf.train.MonitoredTrainingSession(...) as sess:while not sess.should_stop():sess.run(training_op)

    5.3.2 在 tf.estimator.Estimator 中使用 tf.data ?

    要在 tf.estimator.Estimator 的 input_fn 中使用 Dataset,我們建議使用 Dataset.make_one_shot_iterator()。例如:

    def dataset_input_fn():filenames = ["/var/data/file1.tfrecord", "/var/data/file2.tfrecord"]dataset = tf.data.TFRecordDataset(filenames)# Use `tf.parse_single_example()` to extract data from a `tf.Example`# protocol buffer, and perform any additional per-record preprocessing.def parser(record):keys_to_features = {"image_data": tf.FixedLenFeature((), tf.string, default_value=""),"date_time": tf.FixedLenFeature((), tf.int64, default_value=""),"label": tf.FixedLenFeature((), tf.int64,default_value=tf.zeros([], dtype=tf.int64)),}parsed = tf.parse_single_example(record, keys_to_features)# Perform additional preprocessing on the parsed data.image = tf.image.decode_jpeg(parsed["image_data"])image = tf.reshape(image, [299, 299, 1])label = tf.cast(parsed["label"], tf.int32)return {"image_data": image, "date_time": parsed["date_time"]}, label# Use `Dataset.map()` to build a pair of a feature dictionary and a label# tensor for each example.dataset = dataset.map(parser)dataset = dataset.shuffle(buffer_size=10000)dataset = dataset.batch(32)dataset = dataset.repeat(num_epochs)iterator = dataset.make_one_shot_iterator()# `features` is a dictionary in which each value is a batch of values for# that feature; `labels` is a batch of labels.features, labels = iterator.get_next()return features, labels

    注:本文來自于TenosrFlow官方使用tf.data導入數據的 Develop > GUIDE > Importing data

    總結

    以上是生活随笔為你收集整理的TensorFlow tf.data 导入数据(tf.data官方教程) * * * * *的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。