Trang này được dịch bởi Cloud Translation API.
Switch to English

tf.data: Xây dựng đường ống đầu vào TensorFlow

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải vở

API tf.data cho phép bạn xây dựng các đường ống đầu vào phức tạp từ các phần đơn giản, có thể tái sử dụng. Ví dụ: đường ống cho mô hình hình ảnh có thể tổng hợp dữ liệu từ các tệp trong hệ thống tệp phân tán, áp dụng nhiễu loạn ngẫu nhiên cho mỗi hình ảnh và hợp nhất các hình ảnh được chọn ngẫu nhiên thành một lô để đào tạo. Đường ống cho một mô hình văn bản có thể bao gồm trích xuất các ký hiệu từ dữ liệu văn bản thô, chuyển đổi chúng thành nhúng định danh với bảng tra cứu và gộp các chuỗi với độ dài khác nhau. API tf.data cho phép xử lý một lượng lớn dữ liệu, đọc từ các định dạng dữ liệu khác nhau và thực hiện các phép biến đổi phức tạp.

API tf.data giới thiệu một bản tóm tắt tf.data.Dataset đại diện cho một chuỗi các phần tử, trong đó mỗi phần tử bao gồm một hoặc nhiều thành phần. Ví dụ, trong một đường ống hình ảnh, một phần tử có thể là một ví dụ đào tạo duy nhất, với một cặp thành phần tenor đại diện cho hình ảnh và nhãn của nó.

Có hai cách riêng biệt để tạo bộ dữ liệu:

  • Nguồn dữ liệu xây dựng một Dataset từ dữ liệu được lưu trữ trong bộ nhớ hoặc trong một hoặc nhiều tệp.

  • Chuyển đổi dữ liệu xây dựng bộ dữ liệu từ một hoặc nhiều đối tượng tf.data.Dataset .

 import tensorflow as tf
 
 import pathlib
import os
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

np.set_printoptions(precision=4)
 

Cơ học cơ bản

Để tạo một đường ống đầu vào, bạn phải bắt đầu với một nguồn dữ liệu. Ví dụ: để xây dựng một Dataset từ dữ liệu trong bộ nhớ, bạn có thể sử dụng tf.data.Dataset.from_tensors() hoặc tf.data.Dataset.from_tensor_slices() . Ngoài ra, nếu dữ liệu đầu vào của bạn được lưu trữ trong một tệp ở định dạng TFRecord được đề xuất, bạn có thể sử dụng tf.data.TFRecordDataset() .

Khi bạn có một đối tượng Dataset , bạn có thể chuyển đổi nó thành một Dataset mới bằng cách gọi các phương thức chuỗi trên đối tượng tf.data.Dataset . Ví dụ: bạn có thể áp dụng các phép biến đổi theo từng phần tử, chẳng hạn như Dataset.map() và các phép biến đổi đa phần tử như Dataset.batch() . Xem tài liệu cho tf.data.Dataset để biết danh sách đầy đủ các biến đổi.

Đối tượng Dataset là một Python lặp. Điều này cho phép tiêu thụ các phần tử của nó bằng vòng lặp for:

 dataset = tf.data.Dataset.from_tensor_slices([8, 3, 0, 8, 2, 1])
dataset
 
<TensorSliceDataset shapes: (), types: tf.int32>
 for elem in dataset:
  print(elem.numpy())
 
8
3
0
8
2
1

Hoặc bằng cách tạo rõ ràng một trình lặp Python bằng iter và sử dụng các phần tử của nó bằng cách sử dụng next :

 it = iter(dataset)

print(next(it).numpy())
 
8

Ngoài ra, các phần tử dữ liệu có thể được sử dụng bằng cách sử dụng phép biến đổi reduce , làm giảm tất cả các phần tử để tạo ra một kết quả duy nhất. Ví dụ sau minh họa cách sử dụng reduce chuyển đổi để tính tổng của một bộ dữ liệu của các số nguyên.

 print(dataset.reduce(0, lambda state, value: state + value).numpy())
 
22

Cấu trúc dữ liệu

Một tập dữ liệu chứa các thành phần mà mỗi phần tử có cùng cấu trúc (lồng nhau) và các thành phần riêng lẻ của cấu trúc có thể thuộc bất kỳ loại nào được đại diện bởi tf.TypeSpec , bao gồm tf.Tensor , tf.sparse.SparseTensor , tf.RaggedTensor , tf.TensorArray , hoặc tf.data.Dataset .

Dataset.element_spec tính Dataset.element_spec cho phép bạn kiểm tra loại của từng thành phần. Thuộc tính trả về cấu trúc lồng nhau của các đối tượng tf.TypeSpec , khớp với cấu trúc của phần tử, có thể là một thành phần đơn lẻ, bộ dữ liệu thành phần hoặc bộ dữ liệu được lồng vào nhau. Ví dụ:

 dataset1 = tf.data.Dataset.from_tensor_slices(tf.random.uniform([4, 10]))

dataset1.element_spec
 
TensorSpec(shape=(10,), dtype=tf.float32, name=None)
 dataset2 = tf.data.Dataset.from_tensor_slices(
   (tf.random.uniform([4]),
    tf.random.uniform([4, 100], maxval=100, dtype=tf.int32)))

dataset2.element_spec
 
(TensorSpec(shape=(), dtype=tf.float32, name=None),
 TensorSpec(shape=(100,), dtype=tf.int32, name=None))
 dataset3 = tf.data.Dataset.zip((dataset1, dataset2))

dataset3.element_spec
 
(TensorSpec(shape=(10,), dtype=tf.float32, name=None),
 (TensorSpec(shape=(), dtype=tf.float32, name=None),
  TensorSpec(shape=(100,), dtype=tf.int32, name=None)))
 # Dataset containing a sparse tensor.
dataset4 = tf.data.Dataset.from_tensors(tf.SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]))

dataset4.element_spec
 
SparseTensorSpec(TensorShape([3, 4]), tf.int32)
 # Use value_type to see the type of value represented by the element spec
dataset4.element_spec.value_type
 
tensorflow.python.framework.sparse_tensor.SparseTensor

Các phép biến đổi Dataset hỗ trợ các bộ dữ liệu của bất kỳ cấu trúc nào. Khi sử dụng các phép biến đổi Dataset.map()Dataset.filter() , áp dụng một hàm cho mỗi phần tử, cấu trúc phần tử xác định các đối số của hàm:

 dataset1 = tf.data.Dataset.from_tensor_slices(
    tf.random.uniform([4, 10], minval=1, maxval=10, dtype=tf.int32))

dataset1
 
<TensorSliceDataset shapes: (10,), types: tf.int32>
 for z in dataset1:
  print(z.numpy())
 
[8 1 2 6 1 7 2 6 1 3]
[6 5 6 5 3 5 2 5 3 6]
[5 8 4 8 3 1 4 6 4 8]
[2 4 5 8 3 5 7 9 4 2]

 dataset2 = tf.data.Dataset.from_tensor_slices(
   (tf.random.uniform([4]),
    tf.random.uniform([4, 100], maxval=100, dtype=tf.int32)))

dataset2
 
<TensorSliceDataset shapes: ((), (100,)), types: (tf.float32, tf.int32)>
 dataset3 = tf.data.Dataset.zip((dataset1, dataset2))

dataset3
 
<ZipDataset shapes: ((10,), ((), (100,))), types: (tf.int32, (tf.float32, tf.int32))>
 for a, (b,c) in dataset3:
  print('shapes: {a.shape}, {b.shape}, {c.shape}'.format(a=a, b=b, c=c))
 
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)
shapes: (10,), (), (100,)

Đọc dữ liệu đầu vào

Sử dụng mảng NumPy

Xem Tải mảng NumPy để biết thêm ví dụ.

Nếu tất cả dữ liệu đầu vào của bạn vừa với bộ nhớ, cách đơn giản nhất để tạo Dataset từ chúng là chuyển đổi chúng thành các đối tượng tf.Tensor và sử dụng Dataset.from_tensor_slices() .

 train, test = tf.keras.datasets.fashion_mnist.load_data()
 
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step

 images, labels = train
images = images/255

dataset = tf.data.Dataset.from_tensor_slices((images, labels))
dataset
 
<TensorSliceDataset shapes: ((28, 28), ()), types: (tf.float64, tf.uint8)>

Tiêu thụ máy phát điện Python

Một nguồn dữ liệu phổ biến khác có thể dễ dàng được nhập vào dưới dạng tf.data.Dataset là trình tạo python.

 def count(stop):
  i = 0
  while i<stop:
    yield i
    i += 1
 
 for n in count(5):
  print(n)
 
0
1
2
3
4

Hàm tạo Dataset.from_generator chuyển đổi trình tạo python thành tf.data.Dataset đầy đủ chức năng.

Hàm tạo lấy một cuộc gọi là đầu vào, không phải là một trình vòng lặp. Điều này cho phép nó khởi động lại máy phát điện khi đến cuối. Phải mất một tùy chọn args tranh cãi, được thông qua như là đối số của callable.

Đối số output_types là bắt buộc vì tf.data xây dựng tf.Graph bên trong và các cạnh đồ thị yêu cầu tf.dtype .

 ds_counter = tf.data.Dataset.from_generator(count, args=[25], output_types=tf.int32, output_shapes = (), )
 
 for count_batch in ds_counter.repeat().batch(10).take(10):
  print(count_batch.numpy())
 
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24  0  1  2  3  4]
[ 5  6  7  8  9 10 11 12 13 14]
[15 16 17 18 19 20 21 22 23 24]
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24  0  1  2  3  4]
[ 5  6  7  8  9 10 11 12 13 14]
[15 16 17 18 19 20 21 22 23 24]

Đối số output_shapes không bắt buộc nhưng được đánh giá cao vì nhiều thao tác kéo căng không hỗ trợ các tenxơ có thứ hạng không xác định. Nếu độ dài của một trục cụ thể là không xác định hoặc biến, hãy đặt nó là None trong output_shapes .

Cũng cần lưu ý rằng output_shapesoutput_types tuân theo các quy tắc lồng nhau giống như các phương thức dữ liệu khác.

Dưới đây là một trình tạo ví dụ minh họa cả hai khía cạnh, nó trả về các bộ dữ liệu, trong đó mảng thứ hai là một vectơ có độ dài không xác định.

 def gen_series():
  i = 0
  while True:
    size = np.random.randint(0, 10)
    yield i, np.random.normal(size=(size,))
    i += 1
 
 for i, series in gen_series():
  print(i, ":", str(series))
  if i > 5:
    break
 
0 : [-1.978  -1.0531  0.1959 -2.1618]
1 : [ 1.9185 -0.1874  0.5084]
2 : [0.1441 0.3987 0.7737 0.9266 1.5057 0.9151]
3 : [ 0.681  -0.6155 -0.1231 -0.2429  0.6892  1.2571 -1.7588 -1.6575 -0.5375]
4 : [-0.5567  1.5298  0.7242  0.2213]
5 : [ 1.5572 -0.6856]
6 : [-1.0965 -0.336   1.2405  0.6006]

Đầu ra đầu tiên là một int32 thứ hai là một float32 .

Mục đầu tiên là một vô hướng, hình dạng () và thứ hai là một vectơ có độ dài, hình dạng không xác định (None,)

 ds_series = tf.data.Dataset.from_generator(
    gen_series, 
    output_types=(tf.int32, tf.float32), 
    output_shapes=((), (None,)))

ds_series
 
<FlatMapDataset shapes: ((), (None,)), types: (tf.int32, tf.float32)>

Bây giờ nó có thể được sử dụng như một tf.data.Dataset thông thường. Lưu ý rằng khi bó một tập dữ liệu có hình dạng thay đổi, bạn cần sử dụng Dataset.padded_batch .

 ds_series_batch = ds_series.shuffle(20).padded_batch(10)

ids, sequence_batch = next(iter(ds_series_batch))
print(ids.numpy())
print()
print(sequence_batch.numpy())
 
[ 2 10 18  3  6 15 25 23  0  4]

[[ 1.2665 -0.6274  0.4076  1.0146  0.      0.      0.      0.    ]
 [ 0.8091 -0.0683 -0.1464  0.2734  0.7461 -0.1009  0.      0.    ]
 [-0.9381  1.5075  0.      0.      0.      0.      0.      0.    ]
 [ 1.5705  0.4438  0.      0.      0.      0.      0.      0.    ]
 [-0.4692 -1.8328 -2.2838  0.7418  0.0172 -0.3547 -1.4502 -1.2786]
 [-1.574   0.      0.      0.      0.      0.      0.      0.    ]
 [-0.9274  1.4758  0.      0.      0.      0.      0.      0.    ]
 [-0.5043  0.7066  0.9599 -1.2986  0.      0.      0.      0.    ]
 [ 0.      0.      0.      0.      0.      0.      0.      0.    ]
 [-0.4893 -0.6937  0.      0.      0.      0.      0.      0.    ]]

Để có một ví dụ thực tế hơn, hãy thử gói preprocessing.image.ImageDataGenerator tf.data.Dataset .

Đầu tiên tải xuống dữ liệu:

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

Tạo hình image.ImageDataGenerator

 img_gen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255, rotation_range=20)
 
 images, labels = next(img_gen.flow_from_directory(flowers))
 
Found 3670 images belonging to 5 classes.

 print(images.dtype, images.shape)
print(labels.dtype, labels.shape)
 
float32 (32, 256, 256, 3)
float32 (32, 5)

 ds = tf.data.Dataset.from_generator(
    img_gen.flow_from_directory, args=[flowers], 
    output_types=(tf.float32, tf.float32), 
    output_shapes=([32,256,256,3], [32,5])
)

ds
 
<FlatMapDataset shapes: ((32, 256, 256, 3), (32, 5)), types: (tf.float32, tf.float32)>

Sử dụng dữ liệu TFRecord

Xem Tải TFRecords để biết ví dụ từ đầu đến cuối.

API tf.data hỗ trợ nhiều định dạng tệp để bạn có thể xử lý các bộ dữ liệu lớn không phù hợp với bộ nhớ. Ví dụ, định dạng tệp TFRecord là định dạng nhị phân hướng bản ghi đơn giản mà nhiều ứng dụng TensorFlow sử dụng để đào tạo dữ liệu. Lớp tf.data.TFRecordDataset cho phép bạn truyền phát nội dung của một hoặc nhiều tệp TFRecord như một phần của đường ống đầu vào.

Dưới đây là một ví dụ sử dụng tệp thử nghiệm từ Dấu hiệu tên đường phố Pháp (FSNS).

 # Creates a dataset that reads all of the examples from two files.
fsns_test_file = tf.keras.utils.get_file("fsns.tfrec", "https://storage.googleapis.com/download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001")
 
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001
7905280/7904079 [==============================] - 0s 0us/step

Đối số filenames cho trình khởi tạo TFRecordDataset có thể là một chuỗi, một danh sách các chuỗi hoặc một tf.Tensor của các chuỗi. Do đó, nếu bạn có hai bộ tệp cho mục đích đào tạo và xác thực, bạn có thể tạo phương thức xuất xưởng tạo bộ dữ liệu, lấy tên tệp làm đối số đầu vào:

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

Nhiều dự án TensorFlow sử dụng các bản ghi tf.train.Example được tuần tự hóa trong các tệp TFRecord của chúng. Chúng cần được giải mã trước khi có thể được kiểm tra:

 raw_example = next(iter(dataset))
parsed = tf.train.Example.FromString(raw_example.numpy())

parsed.features.feature['image/text']
 
bytes_list {
  value: "Rue Perreyon"
}

Tiêu thụ dữ liệu văn bản

Xem Tải văn bản cho một ví dụ từ đầu đến cuối.

Nhiều bộ dữ liệu được phân phối dưới dạng một hoặc nhiều tệp văn bản. tf.data.TextLineDataset cung cấp một cách dễ dàng để trích xuất các dòng từ một hoặc nhiều tệp văn bản. Cho một hoặc nhiều tên tệp, TextLineDataset sẽ tạo ra một phần tử có giá trị chuỗi trên mỗi dòng của các tệp đó.

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

file_paths = [
    tf.keras.utils.get_file(file_name, directory_url + file_name)
    for file_name in file_names
]
 
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

 dataset = tf.data.TextLineDataset(file_paths)
 

Dưới đây là một vài dòng đầu tiên của tệp đầu tiên:

 for line in dataset.take(5):
  print(line.numpy())
 
b"\xef\xbb\xbfAchilles sing, O Goddess! Peleus' son;"
b'His wrath pernicious, who ten thousand woes'
b"Caused to Achaia's host, sent many a soul"
b'Illustrious into Ades premature,'
b'And Heroes gave (so stood the will of Jove)'

Để thay thế các dòng giữa các tệp, hãy sử dụng Dataset.interleave . Điều này làm cho việc xáo trộn các tệp với nhau dễ dàng hơn. Dưới đây là dòng đầu tiên, thứ hai và thứ ba từ mỗi bản dịch:

 files_ds = tf.data.Dataset.from_tensor_slices(file_paths)
lines_ds = files_ds.interleave(tf.data.TextLineDataset, cycle_length=3)

for i, line in enumerate(lines_ds.take(9)):
  if i % 3 == 0:
    print()
  print(line.numpy())
 

b"\xef\xbb\xbfAchilles sing, O Goddess! Peleus' son;"
b"\xef\xbb\xbfOf Peleus' son, Achilles, sing, O Muse,"
b'\xef\xbb\xbfSing, O goddess, the anger of Achilles son of Peleus, that brought'

b'His wrath pernicious, who ten thousand woes'
b'The vengeance, deep and deadly; whence to Greece'
b'countless ills upon the Achaeans. Many a brave soul did it send'

b"Caused to Achaia's host, sent many a soul"
b'Unnumbered ills arose; which many a soul'
b'hurrying down to Hades, and many a hero did it yield a prey to dogs and'

Theo mặc định, TextLineDataset mang lại mọi dòng của mỗi tệp, có thể không mong muốn, ví dụ, nếu tệp bắt đầu bằng một dòng tiêu đề hoặc chứa các bình luận. Những dòng này có thể được loại bỏ bằng cách sử dụng các phép biến đổi Dataset.skip() hoặc Dataset.filter() . Tại đây, bạn bỏ qua dòng đầu tiên, sau đó lọc để chỉ tìm những người sống sót.

 titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")
titanic_lines = tf.data.TextLineDataset(titanic_file)
 
Downloading data from https://storage.googleapis.com/tf-datasets/titanic/train.csv
32768/30874 [===============================] - 0s 0us/step

 for line in titanic_lines.take(10):
  print(line.numpy())
 
b'survived,sex,age,n_siblings_spouses,parch,fare,class,deck,embark_town,alone'
b'0,male,22.0,1,0,7.25,Third,unknown,Southampton,n'
b'1,female,38.0,1,0,71.2833,First,C,Cherbourg,n'
b'1,female,26.0,0,0,7.925,Third,unknown,Southampton,y'
b'1,female,35.0,1,0,53.1,First,C,Southampton,n'
b'0,male,28.0,0,0,8.4583,Third,unknown,Queenstown,y'
b'0,male,2.0,3,1,21.075,Third,unknown,Southampton,n'
b'1,female,27.0,0,2,11.1333,Third,unknown,Southampton,n'
b'1,female,14.0,1,0,30.0708,Second,unknown,Cherbourg,n'
b'1,female,4.0,1,1,16.7,Third,G,Southampton,n'

 def survived(line):
  return tf.not_equal(tf.strings.substr(line, 0, 1), "0")

survivors = titanic_lines.skip(1).filter(survived)
 
 for line in survivors.take(10):
  print(line.numpy())
 
b'1,female,38.0,1,0,71.2833,First,C,Cherbourg,n'
b'1,female,26.0,0,0,7.925,Third,unknown,Southampton,y'
b'1,female,35.0,1,0,53.1,First,C,Southampton,n'
b'1,female,27.0,0,2,11.1333,Third,unknown,Southampton,n'
b'1,female,14.0,1,0,30.0708,Second,unknown,Cherbourg,n'
b'1,female,4.0,1,1,16.7,Third,G,Southampton,n'
b'1,male,28.0,0,0,13.0,Second,unknown,Southampton,y'
b'1,female,28.0,0,0,7.225,Third,unknown,Cherbourg,y'
b'1,male,28.0,0,0,35.5,First,A,Southampton,y'
b'1,female,38.0,1,5,31.3875,Third,unknown,Southampton,n'

Sử dụng dữ liệu CSV

Xem Tải tệp CSVTải dữ liệu Pandas để biết thêm ví dụ.

Định dạng tệp CSV là định dạng phổ biến để lưu trữ dữ liệu dạng bảng trong văn bản thuần túy.

Ví dụ:

 titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")
 
 df = pd.read_csv(titanic_file, index_col=None)
df.head()
 

Nếu dữ liệu của bạn vừa với bộ nhớ, cùng một phương thức Dataset.from_tensor_slices hoạt động trên từ điển, cho phép dễ dàng nhập dữ liệu này:

 titanic_slices = tf.data.Dataset.from_tensor_slices(dict(df))

for feature_batch in titanic_slices.take(1):
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
 
  'survived'          : 0
  'sex'               : b'male'
  'age'               : 22.0
  'n_siblings_spouses': 1
  'parch'             : 0
  'fare'              : 7.25
  'class'             : b'Third'
  'deck'              : b'unknown'
  'embark_town'       : b'Southampton'
  'alone'             : b'n'

Một cách tiếp cận có thể mở rộng hơn là tải từ đĩa khi cần thiết.

Mô-đun tf.data cung cấp các phương thức để trích xuất các bản ghi từ một hoặc nhiều tệp CSV tuân thủ RFC 4180 .

Hàm experimental.make_csv_dataset là giao diện cấp cao để đọc các tập tin csv. Nó hỗ trợ suy luận kiểu cột và nhiều tính năng khác, như trộn và xáo trộn, để làm cho việc sử dụng đơn giản.

 titanic_batches = tf.data.experimental.make_csv_dataset(
    titanic_file, batch_size=4,
    label_name="survived")
 
 for feature_batch, label_batch in titanic_batches.take(1):
  print("'survived': {}".format(label_batch))
  print("features:")
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
 
'survived': [0 1 0 0]
features:
  'sex'               : [b'male' b'female' b'male' b'male']
  'age'               : [28. 42. 43. 21.]
  'n_siblings_spouses': [0 0 0 0]
  'parch'             : [0 0 0 0]
  'fare'              : [47.1    13.      8.05    8.6625]
  'class'             : [b'First' b'Second' b'Third' b'Third']
  'deck'              : [b'unknown' b'unknown' b'unknown' b'unknown']
  'embark_town'       : [b'Southampton' b'Southampton' b'Southampton' b'Southampton']
  'alone'             : [b'y' b'y' b'y' b'y']

Bạn có thể sử dụng đối số select_columns nếu bạn chỉ cần một tập hợp con của các cột.

 titanic_batches = tf.data.experimental.make_csv_dataset(
    titanic_file, batch_size=4,
    label_name="survived", select_columns=['class', 'fare', 'survived'])
 
 for feature_batch, label_batch in titanic_batches.take(1):
  print("'survived': {}".format(label_batch))
  for key, value in feature_batch.items():
    print("  {!r:20s}: {}".format(key, value))
 
'survived': [1 0 1 1]
  'fare'              : [24.15    0.     13.8583 53.1   ]
  'class'             : [b'Third' b'Second' b'Second' b'First']

Ngoài ra còn có một cấp dưới experimental.CsvDataset lớp mà cung cấp điều khiển hạt mịn. Nó không hỗ trợ suy luận kiểu cột. Thay vào đó, bạn phải chỉ định loại của mỗi cột.

 titanic_types  = [tf.int32, tf.string, tf.float32, tf.int32, tf.int32, tf.float32, tf.string, tf.string, tf.string, tf.string] 
dataset = tf.data.experimental.CsvDataset(titanic_file, titanic_types , header=True)

for line in dataset.take(10):
  print([item.numpy() for item in line])
 
[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n']
[1, b'female', 38.0, 1, 0, 71.2833, b'First', b'C', b'Cherbourg', b'n']
[1, b'female', 26.0, 0, 0, 7.925, b'Third', b'unknown', b'Southampton', b'y']
[1, b'female', 35.0, 1, 0, 53.1, b'First', b'C', b'Southampton', b'n']
[0, b'male', 28.0, 0, 0, 8.4583, b'Third', b'unknown', b'Queenstown', b'y']
[0, b'male', 2.0, 3, 1, 21.075, b'Third', b'unknown', b'Southampton', b'n']
[1, b'female', 27.0, 0, 2, 11.1333, b'Third', b'unknown', b'Southampton', b'n']
[1, b'female', 14.0, 1, 0, 30.0708, b'Second', b'unknown', b'Cherbourg', b'n']
[1, b'female', 4.0, 1, 1, 16.7, b'Third', b'G', b'Southampton', b'n']
[0, b'male', 20.0, 0, 0, 8.05, b'Third', b'unknown', b'Southampton', b'y']

Nếu một số cột trống, giao diện cấp thấp này cho phép bạn cung cấp các giá trị mặc định thay vì các loại cột.

 %%writefile missing.csv
1,2,3,4
,2,3,4
1,,3,4
1,2,,4
1,2,3,
,,,
 
Writing missing.csv

 # 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 = [999,999,999,999]
dataset = tf.data.experimental.CsvDataset("missing.csv", record_defaults)
dataset = dataset.map(lambda *items: tf.stack(items))
dataset
 
<MapDataset shapes: (4,), types: tf.int32>
 for line in dataset:
  print(line.numpy())
 
[1 2 3 4]
[999   2   3   4]
[  1 999   3   4]
[  1   2 999   4]
[  1   2   3 999]
[999 999 999 999]

Theo mặc định, CsvDataset mang lại mọi cột của mỗi dòng của tệp, điều này có thể không mong muốn, ví dụ nếu tệp bắt đầu bằng một dòng tiêu đề nên được bỏ qua hoặc nếu một số cột không được yêu cầu trong đầu vào. Các dòng và trường này có thể được loại bỏ với các đối số headerselect_cols tương ứng.

 # Creates a dataset that reads all of the records from two CSV files with
# headers, extracting float data from columns 2 and 4.
record_defaults = [999, 999] # Only provide defaults for the selected columns
dataset = tf.data.experimental.CsvDataset("missing.csv", record_defaults, select_cols=[1, 3])
dataset = dataset.map(lambda *items: tf.stack(items))
dataset
 
<MapDataset shapes: (2,), types: tf.int32>
 for line in dataset:
  print(line.numpy())
 
[2 4]
[2 4]
[999   4]
[2 4]
[  2 999]
[999 999]

Tập hợp các tập tin

Có nhiều bộ dữ liệu được phân phối dưới dạng một tập hợp các tệp, trong đó mỗi tệp là một ví dụ.

 flowers_root = tf.keras.utils.get_file(
    'flower_photos',
    'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz',
    untar=True)
flowers_root = pathlib.Path(flowers_root)

 

Thư mục gốc chứa một thư mục cho mỗi lớp:

 for item in flowers_root.glob("*"):
  print(item.name)
 
sunflowers
daisy
LICENSE.txt
roses
tulips
dandelion

Các tệp trong mỗi thư mục lớp là ví dụ:

 list_ds = tf.data.Dataset.list_files(str(flowers_root/'*/*'))

for f in list_ds.take(5):
  print(f.numpy())
 
b'/home/kbuilder/.keras/datasets/flower_photos/dandelion/7243478942_30bf542a2d_m.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/4525067924_177ea3bfb4.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/tulips/7002703410_3e97b29da5_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/daisy/6299910262_336309ffa5_n.jpg'
b'/home/kbuilder/.keras/datasets/flower_photos/sunflowers/6140661443_bb48344226.jpg'

Đọc dữ liệu bằng hàm tf.io.read_file và trích xuất nhãn từ đường dẫn, trả về các cặp (image, label) :

 def process_path(file_path):
  label = tf.strings.split(file_path, os.sep)[-2]
  return tf.io.read_file(file_path), label

labeled_ds = list_ds.map(process_path)
 
 for image_raw, label_text in labeled_ds.take(1):
  print(repr(image_raw.numpy()[:100]))
  print()
  print(label_text.numpy())
 
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00H\x00H\x00\x00\xff\xe2\x0cXICC_PROFILE\x00\x01\x01\x00\x00\x0cHLino\x02\x10\x00\x00mntrRGB XYZ \x07\xce\x00\x02\x00\t\x00\x06\x001\x00\x00acspMSFT\x00\x00\x00\x00IEC sRGB\x00\x00\x00\x00\x00\x00'

b'tulips'

Các phần tử dữ liệu hàng loạt

Pha trộn đơn giản

Hình thức đơn giản nhất của ngăn xếp ngăn xếp n phần tử liên tiếp của tập dữ liệu thành một phần tử. Dataset.batch() biến đổi Dataset.batch() thực hiện chính xác điều này, với cùng các ràng buộc như toán tử tf.stack() , áp dụng cho từng thành phần của các phần tử: tức là đối với mỗi thành phần i , tất cả các phần tử phải có một tenxơ có cùng hình dạng chính xác.

 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)

for batch in batched_dataset.take(4):
  print([arr.numpy() for arr in batch])
 
[array([0, 1, 2, 3]), array([ 0, -1, -2, -3])]
[array([4, 5, 6, 7]), array([-4, -5, -6, -7])]
[array([ 8,  9, 10, 11]), array([ -8,  -9, -10, -11])]
[array([12, 13, 14, 15]), array([-12, -13, -14, -15])]

Trong khi tf.data cố gắng truyền bá thông tin hình dạng, các cài đặt mặc định của Dataset.batch dẫn đến kích thước lô không xác định vì lô cuối cùng có thể không đầy đủ. Lưu ý None trong hình:

 batched_dataset
 
<BatchDataset shapes: ((None,), (None,)), types: (tf.int64, tf.int64)>

Sử dụng đối số drop_remainder để bỏ qua lô cuối cùng đó và nhận lan truyền hình dạng đầy đủ:

 batched_dataset = dataset.batch(7, drop_remainder=True)
batched_dataset
 
<BatchDataset shapes: ((7,), (7,)), types: (tf.int64, tf.int64)>

Batching tenors với đệm

Các công thức trên làm việc cho tenor mà tất cả có cùng kích thước. Tuy nhiên, nhiều mô hình (ví dụ mô hình chuỗi) hoạt động với dữ liệu đầu vào có thể có kích thước khác nhau (ví dụ: chuỗi có độ dài khác nhau). Để xử lý trường hợp này, phép biến đổi Dataset.padded_batch cho phép bạn ghép các thang đo có hình dạng khác nhau bằng cách chỉ định một hoặc nhiều kích thước trong đó chúng có thể được đệm.

 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,))

for batch in dataset.take(2):
  print(batch.numpy())
  print()

 
[[0 0 0]
 [1 0 0]
 [2 2 0]
 [3 3 3]]

[[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 biến đổi Dataset.padded_batch cho phép bạn đặt các phần đệm khác nhau cho từng kích thước của từng thành phần và nó có thể có độ dài thay đổi (được biểu thị bằng None trong ví dụ trên) hoặc độ dài không đổi. Cũng có thể ghi đè giá trị đệm, mặc định là 0.

Quy trình đào tạo

Xử lý nhiều kỷ nguyên

API tf.data cung cấp hai cách chính để xử lý nhiều epoch của cùng một dữ liệu.

Cách đơn giản nhất để lặp lại tập dữ liệu trong nhiều Dataset.repeat() là sử dụng phép biến đổi Dataset.repeat() . Đầu tiên, tạo một bộ dữ liệu về dữ liệu titanic:

 titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv")
titanic_lines = tf.data.TextLineDataset(titanic_file)
 
 def plot_batch_sizes(ds):
  batch_sizes = [batch.shape[0] for batch in ds]
  plt.bar(range(len(batch_sizes)), batch_sizes)
  plt.xlabel('Batch number')
  plt.ylabel('Batch size')
 

Áp dụng phép biến đổi Dataset.repeat() không có đối số sẽ lặp lại đầu vào vô thời hạn.

Dataset.repeat biến đổi Dataset.repeat kết hợp các đối số của nó mà không báo hiệu sự kết thúc của một kỷ nguyên và sự khởi đầu của kỷ nguyên tiếp theo. Do đó, một Dataset.batch được áp dụng sau Dataset.repeat sẽ mang lại các lô nối các ranh giới kỷ nguyên:

 titanic_batches = titanic_lines.repeat(3).batch(128)
plot_batch_sizes(titanic_batches)
 

png

Nếu bạn cần tách epoch rõ ràng, hãy đặt Dataset.batch trước khi lặp lại:

 titanic_batches = titanic_lines.batch(128).repeat(3)

plot_batch_sizes(titanic_batches)
 

png

Nếu bạn muốn thực hiện tính toán tùy chỉnh (ví dụ: để thu thập số liệu thống kê) ở cuối mỗi epoch thì đơn giản nhất là khởi động lại tập dữ liệu lặp trên mỗi epoch:

 epochs = 3
dataset = titanic_lines.batch(128)

for epoch in range(epochs):
  for batch in dataset:
    print(batch.shape)
  print("End of epoch: ", epoch)
 
(128,)
(128,)
(128,)
(128,)
(116,)
End of epoch:  0
(128,)
(128,)
(128,)
(128,)
(116,)
End of epoch:  1
(128,)
(128,)
(128,)
(128,)
(116,)
End of epoch:  2

Xáo trộn ngẫu nhiên dữ liệu đầu vào

Dataset.shuffle() biến đổi Dataset.shuffle() duy trì bộ đệm có kích thước cố định và chọn phần tử tiếp theo một cách ngẫu nhiên từ bộ đệm đó.

Thêm một chỉ mục vào tập dữ liệu để bạn có thể thấy hiệu ứng:

 lines = tf.data.TextLineDataset(titanic_file)
counter = tf.data.experimental.Counter()

dataset = tf.data.Dataset.zip((counter, lines))
dataset = dataset.shuffle(buffer_size=100)
dataset = dataset.batch(20)
dataset
 
<BatchDataset shapes: ((None,), (None,)), types: (tf.int64, tf.string)>

buffer_size là 100 và kích thước lô là 20, nên lô đầu tiên không chứa phần tử nào có chỉ số trên 120.

 n,line_batch = next(iter(dataset))
print(n.numpy())
 
[ 63  48 101  12 103  52   6  39   4   9  93  91   5  86  79  64  95  33
 102  50]

Như với Dataset.batch thứ tự liên quan đến các vấn đề Dataset.repeat .

Dataset.shuffle không báo hiệu sự kết thúc của một kỷ nguyên cho đến khi bộ đệm xáo trộn trống. Vì vậy, một shuffle được đặt trước một lặp lại sẽ hiển thị mọi yếu tố của một kỷ nguyên trước khi chuyển sang tiếp theo:

 dataset = tf.data.Dataset.zip((counter, lines))
shuffled = dataset.shuffle(buffer_size=100).batch(10).repeat(2)

print("Here are the item ID's near the epoch boundary:\n")
for n, line_batch in shuffled.skip(60).take(5):
  print(n.numpy())
 
Here are the item ID's near the epoch boundary:

[613 609 624 553 608 583 493 617 611 610]
[217 508 579 601 319 616 606 549 618 623]
[416 567 404 622 283 458 503 602]
[ 87  68  56  16   6  62   1  89  58 106]
[98 80 43 10 67 44 19 34 13 57]

 shuffle_repeat = [n.numpy().mean() for n, line_batch in shuffled]
plt.plot(shuffle_repeat, label="shuffle().repeat()")
plt.ylabel("Mean item ID")
plt.legend()
 
<matplotlib.legend.Legend at 0x7fe0a00a1d68>

png

Nhưng lặp lại trước khi xáo trộn trộn các ranh giới kỷ nguyên lại với nhau:

 dataset = tf.data.Dataset.zip((counter, lines))
shuffled = dataset.repeat(2).shuffle(buffer_size=100).batch(10)

print("Here are the item ID's near the epoch boundary:\n")
for n, line_batch in shuffled.skip(55).take(15):
  print(n.numpy())
 
Here are the item ID's near the epoch boundary:

[440  15   8 599 567  18 550   5  19  17]
[ 12 501 571 473 466  21 531 596 580 555]
[  3 573  38 563  25 416 595  29  46 602]
[485 566 561  16 331 615 386  28 609  41]
[611 622 575  10 589  61 598 527  52  35]
[ 55 597  42  23  13  47  11 505  68 582]
[612 613  75  43   7 392  74 452  82 509]
[  9  44  62 491  71 343  51 590  60  98]
[  6  95 619  86 625 537 617  85 465   0]
[ 88  27  92 101 109 111 104  24  36 113]
[103 118  79  53  70  40 121 100  65  33]
[562 588 124 125  64  84  83  67 610 130]
[  4 142 131  90 518 129 143 112   2 551]
[377  91 140  76  50  48 526 553 156 591]
[105 128  69 114  93 520 154  56 145 115]

 repeat_shuffle = [n.numpy().mean() for n, line_batch in shuffled]

plt.plot(shuffle_repeat, label="shuffle().repeat()")
plt.plot(repeat_shuffle, label="repeat().shuffle()")
plt.ylabel("Mean item ID")
plt.legend()
 
<matplotlib.legend.Legend at 0x7fe0582fbb70>

png

Dữ liệu tiền xử lý

Dataset.map(f) biến đổi Dataset.map(f) tạo ra một tập dữ liệu mới bằng cách áp dụng hàm f cho cho từng phần tử của tập dữ liệu đầu vào. Nó dựa trên hàm map() thường được áp dụng cho các danh sách (và các cấu trúc khác) trong các ngôn ngữ lập trình hàm. Hàm f lấy các đối tượng tf.Tensor đại diện cho một phần tử trong đầu vào và trả về các đối tượng tf.Tensor sẽ đại diện cho một phần tử trong tập dữ liệu mới. Việc triển khai của nó sử dụng các hoạt động TensorFlow tiêu chuẩn để chuyển đổi một yếu tố này sang yếu tố khác.

Phần này bao gồm các ví dụ phổ biến về cách sử dụng Dataset.map() .

Giải mã dữ liệu hình ảnh và thay đổi kích thước nó

Khi đào tạo một mạng lưới thần kinh về dữ liệu hình ảnh trong thế giới thực, thường cần phải chuyển đổi các hình ảnh có kích thước khác nhau thành một kích thước chung, để chúng có thể được chia thành một kích thước cố định.

Xây dựng lại tập dữ liệu tên tệp hoa:

 list_ds = tf.data.Dataset.list_files(str(flowers_root/'*/*'))
 

Viết hàm thao tác các phần tử dữ liệu.

 # Reads an image from a file, decodes it into a dense tensor, and resizes it
# to a fixed shape.
def parse_image(filename):
  parts = tf.strings.split(filename, os.sep)
  label = parts[-2]

  image = tf.io.read_file(filename)
  image = tf.image.decode_jpeg(image)
  image = tf.image.convert_image_dtype(image, tf.float32)
  image = tf.image.resize(image, [128, 128])
  return image, label
 

Kiểm tra rằng nó hoạt động.

 file_path = next(iter(list_ds))
image, label = parse_image(file_path)

def show(image, label):
  plt.figure()
  plt.imshow(image)
  plt.title(label.numpy().decode('utf-8'))
  plt.axis('off')

show(image, label)
 

png

Ánh xạ nó qua tập dữ liệu.

 images_ds = list_ds.map(parse_image)

for image, label in images_ds.take(2):
  show(image, label)
 

png

png

Áp dụng logic Python tùy ý

Vì lý do hiệu suất, hãy sử dụng các hoạt động của TensorFlow để xử lý trước dữ liệu của bạn bất cứ khi nào có thể. Tuy nhiên, đôi khi rất hữu ích khi gọi các thư viện Python bên ngoài khi phân tích dữ liệu đầu vào của bạn. Bạn có thể sử dụng tf.py_function() hoạt động trong một Dataset.map() chuyển đổi.

Ví dụ: nếu bạn muốn áp dụng xoay vòng ngẫu nhiên, mô-đun tf.image chỉ có tf.image.rot90 , không hữu ích cho việc tăng cường hình ảnh.

Để thể hiện tf.py_function , hãy thử sử dụng hàm scipy.ndimage.rotate :

 import scipy.ndimage as ndimage

def random_rotate_image(image):
  image = ndimage.rotate(image, np.random.uniform(-30, 30), reshape=False)
  return image
 
 image, label = next(iter(images_ds))
image = random_rotate_image(image)
show(image, label)
 
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

png

Để sử dụng chức năng này với Dataset.map , hãy cẩn thận như với Dataset.from_generator , bạn cần mô tả các hình dạng và kiểu trả về khi bạn áp dụng hàm:

 def tf_random_rotate_image(image, label):
  im_shape = image.shape
  [image,] = tf.py_function(random_rotate_image, [image], [tf.float32])
  image.set_shape(im_shape)
  return image, label
 
 rot_ds = images_ds.map(tf_random_rotate_image)

for image, label in rot_ds.take(2):
  show(image, label)
 
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

png

png

Phân tích cú pháp tin nhắn bộ đệm giao thức tf.Example

Nhiều đường ống đầu vào trích xuất các thông điệp bộ đệm giao thức tf.train.Example từ định dạng TFRecord. Mỗi bản ghi tf.train.Example chứa một hoặc nhiều "tính năng" và đường ống đầu vào thường chuyển đổi các tính năng này thành các thang đo.

 fsns_test_file = tf.keras.utils.get_file("fsns.tfrec", "https://storage.googleapis.com/download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001")
dataset = tf.data.TFRecordDataset(filenames = [fsns_test_file])
dataset
 
<TFRecordDatasetV2 shapes: (), types: tf.string>

Bạn có thể làm việc với tf.train.Example bên ngoài tf.data.Dataset để hiểu dữ liệu:

 raw_example = next(iter(dataset))
parsed = tf.train.Example.FromString(raw_example.numpy())

feature = parsed.features.feature
raw_img = feature['image/encoded'].bytes_list.value[0]
img = tf.image.decode_png(raw_img)
plt.imshow(img)
plt.axis('off')
_ = plt.title(feature["image/text"].bytes_list.value[0])
 

png

 raw_example = next(iter(dataset))
 
 def tf_parse(eg):
  example = tf.io.parse_example(
      eg[tf.newaxis], {
          'image/encoded': tf.io.FixedLenFeature(shape=(), dtype=tf.string),
          'image/text': tf.io.FixedLenFeature(shape=(), dtype=tf.string)
      })
  return example['image/encoded'][0], example['image/text'][0]
 
 img, txt = tf_parse(raw_example)
print(txt.numpy())
print(repr(img.numpy()[:20]), "...")
 
b'Rue Perreyon'
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02X' ...

 decoded = dataset.map(tf_parse)
decoded
 
<MapDataset shapes: ((), ()), types: (tf.string, tf.string)>
 image_batch, text_batch = next(iter(decoded.batch(10)))
image_batch.shape
 
TensorShape([10])

Cửa sổ chuỗi thời gian

Để biết ví dụ về chuỗi thời gian từ đầu đến cuối, hãy xem: Dự báo chuỗi thời gian .

Dữ liệu chuỗi thời gian thường được tổ chức với trục thời gian nguyên vẹn.

Sử dụng một Dataset.range đơn giản để chứng minh:

 range_ds = tf.data.Dataset.range(100000)
 

Thông thường, các mô hình dựa trên loại dữ liệu này sẽ muốn một lát thời gian liền kề.

Cách tiếp cận đơn giản nhất sẽ là bó dữ liệu:

Sử dụng batch

 batches = range_ds.batch(10, drop_remainder=True)

for batch in batches.take(5):
  print(batch.numpy())
 
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]

Hoặc để đưa ra dự đoán dày đặc một bước trong tương lai, bạn có thể thay đổi các tính năng và nhãn theo một bước so với nhau:

 def dense_1_step(batch):
  # Shift features and labels one step relative to each other.
  return batch[:-1], batch[1:]

predict_dense_1_step = batches.map(dense_1_step)

for features, label in predict_dense_1_step.take(3):
  print(features.numpy(), " => ", label.numpy())
 
[0 1 2 3 4 5 6 7 8]  =>  [1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18]  =>  [11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28]  =>  [21 22 23 24 25 26 27 28 29]

Để dự đoán toàn bộ cửa sổ thay vì bù cố định, bạn có thể chia các lô thành hai phần:

 batches = range_ds.batch(15, drop_remainder=True)

def label_next_5_steps(batch):
  return (batch[:-5],   # Take the first 5 steps
          batch[-5:])   # take the remainder

predict_5_steps = batches.map(label_next_5_steps)

for features, label in predict_5_steps.take(3):
  print(features.numpy(), " => ", label.numpy())
 
[0 1 2 3 4 5 6 7 8 9]  =>  [10 11 12 13 14]
[15 16 17 18 19 20 21 22 23 24]  =>  [25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]  =>  [40 41 42 43 44]

Để cho phép một số trùng lặp giữa các tính năng của một lô và nhãn của một lô khác, hãy sử dụng Dataset.zip :

 feature_length = 10
label_length = 5

features = range_ds.batch(feature_length, drop_remainder=True)
labels = range_ds.batch(feature_length).skip(1).map(lambda labels: labels[:-5])

predict_5_steps = tf.data.Dataset.zip((features, labels))

for features, label in predict_5_steps.take(3):
  print(features.numpy(), " => ", label.numpy())
 
[0 1 2 3 4 5 6 7 8 9]  =>  [10 11 12 13 14]
[10 11 12 13 14 15 16 17 18 19]  =>  [20 21 22 23 24]
[20 21 22 23 24 25 26 27 28 29]  =>  [30 31 32 33 34]

Sử dụng window

Trong khi sử dụng Dataset.batch hoạt động, có những tình huống bạn có thể cần kiểm soát tốt hơn. Phương thức Dataset.window cung cấp cho bạn toàn quyền kiểm soát, nhưng yêu cầu một số lưu ý: nó trả về một Dataset của Datasets . Xem cấu trúc bộ dữ liệu để biết chi tiết.

 window_size = 5

windows = range_ds.window(window_size, shift=1)
for sub_ds in windows.take(5):
  print(sub_ds)
 
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>
<_VariantDataset shapes: (), types: tf.int64>

Phương thức Dataset.flat_map có thể lấy một tập dữ liệu của bộ dữ liệu và làm phẳng nó thành một tập dữ liệu duy nhất:

  for x in windows.flat_map(lambda x: x).take(30):
   print(x.numpy(), end=' ')
 
WARNING:tensorflow:AutoGraph could not transform <function <lambda> at 0x7fe0582dbbf8> and will run it as-is.
Cause: could not parse the source code:

for x in windows.flat_map(lambda x: x).take(30):

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function <lambda> at 0x7fe0582dbbf8> and will run it as-is.
Cause: could not parse the source code:

for x in windows.flat_map(lambda x: x).take(30):

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 

Trong gần như tất cả các trường hợp, bạn sẽ muốn .batch bộ dữ liệu trước:

 def sub_to_batch(sub):
  return sub.batch(window_size, drop_remainder=True)

for example in windows.flat_map(sub_to_batch).take(5):
  print(example.numpy())
 
[0 1 2 3 4]
[1 2 3 4 5]
[2 3 4 5 6]
[3 4 5 6 7]
[4 5 6 7 8]

Bây giờ, bạn có thể thấy rằng đối số shift kiểm soát mỗi cửa sổ di chuyển qua bao nhiêu.

Đặt cái này lại với nhau bạn có thể viết hàm này:

 def make_window_dataset(ds, window_size=5, shift=1, stride=1):
  windows = ds.window(window_size, shift=shift, stride=stride)

  def sub_to_batch(sub):
    return sub.batch(window_size, drop_remainder=True)

  windows = windows.flat_map(sub_to_batch)
  return windows

 
 ds = make_window_dataset(range_ds, window_size=10, shift = 5, stride=3)

for example in ds.take(10):
  print(example.numpy())
 
[ 0  3  6  9 12 15 18 21 24 27]
[ 5  8 11 14 17 20 23 26 29 32]
[10 13 16 19 22 25 28 31 34 37]
[15 18 21 24 27 30 33 36 39 42]
[20 23 26 29 32 35 38 41 44 47]
[25 28 31 34 37 40 43 46 49 52]
[30 33 36 39 42 45 48 51 54 57]
[35 38 41 44 47 50 53 56 59 62]
[40 43 46 49 52 55 58 61 64 67]
[45 48 51 54 57 60 63 66 69 72]

Sau đó, thật dễ dàng để trích xuất nhãn, như trước đây:

 dense_labels_ds = ds.map(dense_1_step)

for inputs,labels in dense_labels_ds.take(3):
  print(inputs.numpy(), "=>", labels.numpy())
 
[ 0  3  6  9 12 15 18 21 24] => [ 3  6  9 12 15 18 21 24 27]
[ 5  8 11 14 17 20 23 26 29] => [ 8 11 14 17 20 23 26 29 32]
[10 13 16 19 22 25 28 31 34] => [13 16 19 22 25 28 31 34 37]

Lấy mẫu lại

Khi làm việc với một tập dữ liệu rất mất cân bằng, bạn có thể muốn lấy mẫu lại tập dữ liệu. tf.data cung cấp hai phương thức để làm điều này. Bộ dữ liệu gian lận thẻ tín dụng là một ví dụ điển hình cho loại vấn đề này.

 zip_path = tf.keras.utils.get_file(
    origin='https://storage.googleapis.com/download.tensorflow.org/data/creditcard.zip',
    fname='creditcard.zip',
    extract=True)

csv_path = zip_path.replace('.zip', '.csv')
 
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/creditcard.zip
69156864/69155632 [==============================] - 10s 0us/step

 creditcard_ds = tf.data.experimental.make_csv_dataset(
    csv_path, batch_size=1024, label_name="Class",
    # Set the column types: 30 floats and an int.
    column_defaults=[float()]*30+[int()])
 

Bây giờ, hãy kiểm tra phân phối của các lớp, nó rất sai lệch:

 def count(counts, batch):
  features, labels = batch
  class_1 = labels == 1
  class_1 = tf.cast(class_1, tf.int32)

  class_0 = labels == 0
  class_0 = tf.cast(class_0, tf.int32)

  counts['class_0'] += tf.reduce_sum(class_0)
  counts['class_1'] += tf.reduce_sum(class_1)

  return counts
 
 counts = creditcard_ds.take(10).reduce(
    initial_state={'class_0': 0, 'class_1': 0},
    reduce_func = count)

counts = np.array([counts['class_0'].numpy(),
                   counts['class_1'].numpy()]).astype(np.float32)

fractions = counts/counts.sum()
print(fractions)
 
[0.996 0.004]

Một cách tiếp cận phổ biến để đào tạo với một bộ dữ liệu mất cân bằng là cân bằng nó. tf.data bao gồm một vài phương thức cho phép luồng công việc này:

Lấy mẫu dữ liệu

Một cách tiếp cận để lấy mẫu lại một tập dữ liệu là sử dụng sample_from_datasets . Điều này được áp dụng nhiều hơn khi bạn có một data.Dataset riêng biệt. Bộ data.Dataset cho mỗi lớp.

Tại đây, chỉ cần sử dụng bộ lọc để tạo chúng từ dữ liệu gian lận thẻ tín dụng:

 negative_ds = (
  creditcard_ds
    .unbatch()
    .filter(lambda features, label: label==0)
    .repeat())
positive_ds = (
  creditcard_ds
    .unbatch()
    .filter(lambda features, label: label==1)
    .repeat())
 
WARNING:tensorflow:AutoGraph could not transform <function <lambda> at 0x7fe0a01fd1e0> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==0)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function <lambda> at 0x7fe0a01fd1e0> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==0)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING:tensorflow:AutoGraph could not transform <function <lambda> at 0x7fe058159620> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==1)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert
WARNING: AutoGraph could not transform <function <lambda> at 0x7fe058159620> and will run it as-is.
Cause: could not parse the source code:

    .filter(lambda features, label: label==1)

This error may be avoided by creating the lambda in a standalone statement.

To silence this warning, decorate the function with @tf.autograph.experimental.do_not_convert

 for features, label in positive_ds.batch(10).take(1):
  print(label.numpy())
 
[1 1 1 1 1 1 1 1 1 1]

Để sử dụng tf.data.experimental.sample_from_datasets vượt qua các bộ dữ liệu và trọng số cho mỗi bộ:

 balanced_ds = tf.data.experimental.sample_from_datasets(
    [negative_ds, positive_ds], [0.5, 0.5]).batch(10)
 

Bây giờ bộ dữ liệu tạo ra các ví dụ của mỗi lớp với xác suất 50/50:

 for features, labels in balanced_ds.take(10):
  print(labels.numpy())
 
[0 0 0 1 0 0 1 1 0 0]
[1 1 0 0 1 1 0 0 0 1]
[1 1 0 0 0 0 0 0 1 1]
[1 0 0 1 1 0 0 0 1 0]
[1 1 0 0 0 1 1 0 0 1]
[0 0 1 1 1 0 0 1 1 0]
[0 0 0 1 0 0 0 1 1 1]
[1 1 0 1 0 0 1 0 1 1]
[0 1 0 0 1 1 0 0 0 1]
[0 1 0 0 1 0 0 1 1 0]

Từ chối thay đổi

Một vấn đề với cách tiếp cận experimental.sample_from_datasets tf.data.Dataset ở trên là nó cần một tf.data.Dataset riêng cho mỗi lớp. Sử dụng Dataset.filter hoạt động, nhưng kết quả là tất cả dữ liệu được tải hai lần.

Hàm data.experimental.rejection_resample có thể được áp dụng cho bộ dữ liệu để cân bằng lại nó, trong khi chỉ tải nó một lần. Các yếu tố sẽ được loại bỏ khỏi bộ dữ liệu để đạt được sự cân bằng.

data.experimental.rejection_resample nhận một đối số class_func . class_func này được áp dụng cho từng thành phần của tập dữ liệu và được sử dụng để xác định một ví dụ thuộc về lớp nào cho mục đích cân bằng.

Các yếu tố của creditcard_ds đã là cặp (features, label) . Vì vậy, class_func chỉ cần trả về các nhãn đó:

 def class_func(features, label):
  return label
 

Bộ ghép lại cũng cần một phân phối mục tiêu và tùy chọn ước tính phân phối ban đầu:

 resampler = tf.data.experimental.rejection_resample(
    class_func, target_dist=[0.5, 0.5], initial_dist=fractions)
 

Bộ cộng lại xử lý các ví dụ riêng lẻ, do đó bạn phải unbatch kết nối bộ dữ liệu trước khi áp dụng bộ lấy mẫu:

 resample_ds = creditcard_ds.unbatch().apply(resampler).batch(10)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/data/experimental/ops/resampling.py:156: Print (from tensorflow.python.ops.logging_ops) is deprecated and will be removed after 2018-08-20.
Instructions for updating:
Use tf.print instead of tf.Print. Note that tf.print returns a no-output operator that directly prints the output. Outside of defuns or eager mode, this operator will not be executed unless it is directly specified in session.run or used as a control dependency for other operators. This is only a concern in graph mode. Below is an example of how to ensure tf.print executes in graph mode:


Trả về bộ ghép lại tạo các cặp (class, example) từ đầu ra của class_func . Trong trường hợp này, example đã là một cặp (feature, label) , vì vậy hãy sử dụng map để thả bản sao thêm của nhãn:

 balanced_ds = resample_ds.map(lambda extra_label, features_and_label: features_and_label)
 

Bây giờ bộ dữ liệu tạo ra các ví dụ của mỗi lớp với xác suất 50/50:

 for features, labels in balanced_ds.take(10):
  print(labels.numpy())
 
[1 0 1 1 1 1 0 1 1 1]
[0 0 1 1 1 0 1 0 1 1]
[1 0 0 1 0 0 0 0 0 1]
[1 1 1 1 1 1 0 1 1 1]
[1 1 0 1 0 0 0 0 1 0]
[1 0 0 0 1 0 1 0 1 0]
[0 0 0 0 0 0 1 0 0 0]
[0 0 0 1 1 0 0 1 0 1]
[0 0 1 1 1 1 0 0 1 1]
[0 0 1 1 0 1 0 1 1 0]

Điểm kiểm tra lặp

Tensorflow hỗ trợ lấy điểm kiểm tra để khi quá trình đào tạo của bạn khởi động lại, nó có thể khôi phục điểm kiểm tra mới nhất để phục hồi hầu hết tiến trình của nó. Ngoài việc kiểm tra các biến mô hình, bạn cũng có thể kiểm tra tiến trình của bộ lặp dữ liệu. Điều này có thể hữu ích nếu bạn có một tập dữ liệu lớn và không muốn bắt đầu tập dữ liệu từ đầu mỗi lần khởi động lại. Tuy nhiên, lưu ý rằng các điểm kiểm tra của trình lặp có thể lớn, vì các phép biến đổi như shuffleprefetch yêu cầu các phần tử đệm trong trình vòng lặp.

Để đưa iterator của bạn vào một điểm kiểm tra, hãy chuyển iterator đến tf.train.Checkpoint tạo tf.train.Checkpoint .

 range_ds = tf.data.Dataset.range(20)

iterator = iter(range_ds)
ckpt = tf.train.Checkpoint(step=tf.Variable(0), iterator=iterator)
manager = tf.train.CheckpointManager(ckpt, '/tmp/my_ckpt', max_to_keep=3)

print([next(iterator).numpy() for _ in range(5)])

save_path = manager.save()

print([next(iterator).numpy() for _ in range(5)])

ckpt.restore(manager.latest_checkpoint)

print([next(iterator).numpy() for _ in range(5)])
 
[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[5, 6, 7, 8, 9]

Sử dụng API cấp cao

tf.keras

API tf.keras đơn giản hóa nhiều khía cạnh trong việc tạo và thực hiện các mô hình học máy. Các .fit().evaluate().predict() hỗ trợ các bộ dữ liệu làm đầu vào. Dưới đây là một bộ dữ liệu nhanh và thiết lập mô hình:

 train, test = tf.keras.datasets.fashion_mnist.load_data()

images, labels = train
images = images/255.0
labels = labels.astype(np.int32)
 
 fmnist_train_ds = tf.data.Dataset.from_tensor_slices((images, labels))
fmnist_train_ds = fmnist_train_ds.shuffle(5000).batch(32)

model = tf.keras.Sequential([
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(10)
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), 
              metrics=['accuracy'])
 

Truyền một tập dữ liệu của các cặp (feature, label) là tất cả những gì cần thiết cho Model.fitModel.evaluate :

 model.fit(fmnist_train_ds, epochs=2)
 
Epoch 1/2
WARNING:tensorflow:Layer flatten 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.

1875/1875 [==============================] - 4s 2ms/step - loss: 0.6031 - accuracy: 0.7937
Epoch 2/2
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4620 - accuracy: 0.8416

<tensorflow.python.keras.callbacks.History at 0x7fe13f9ed3c8>

Nếu bạn vượt qua một tập dữ liệu vô hạn, ví dụ bằng cách gọi Dataset.repeat() , bạn chỉ cần chuyển đối số steps_per_epoch :

 model.fit(fmnist_train_ds.repeat(), epochs=2, steps_per_epoch=20)
 
Epoch 1/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4050 - accuracy: 0.8672
Epoch 2/2
20/20 [==============================] - 0s 2ms/step - loss: 0.4077 - accuracy: 0.8703

<tensorflow.python.keras.callbacks.History at 0x7fe0ca13edd8>

Để đánh giá bạn có thể vượt qua số bước đánh giá:

 loss, accuracy = model.evaluate(fmnist_train_ds)
print("Loss :", loss)
print("Accuracy :", accuracy)
 
1875/1875 [==============================] - 3s 2ms/step - loss: 0.4474 - accuracy: 0.8439
Loss : 0.4474281072616577
Accuracy : 0.843916654586792

Đối với bộ dữ liệu dài, đặt số bước để đánh giá:

 loss, accuracy = model.evaluate(fmnist_train_ds.repeat(), steps=10)
print("Loss :", loss)
print("Accuracy :", accuracy)
 
10/10 [==============================] - 0s 2ms/step - loss: 0.5262 - accuracy: 0.8156
Loss : 0.5262183547019958
Accuracy : 0.815625011920929

Các nhãn không bắt buộc khi gọi Model.predict .

 predict_ds = tf.data.Dataset.from_tensor_slices(images).batch(32)
result = model.predict(predict_ds, steps = 10)
print(result.shape)
 
(320, 10)

Nhưng các nhãn bị bỏ qua nếu bạn vượt qua một tập dữ liệu có chứa chúng:

 result = model.predict(fmnist_train_ds, steps = 10)
print(result.shape)
 
(320, 10)

tf.estimator

Để sử dụng Dataset trong input_fn của tf.estimator.Estimator , chỉ cần trả lại Dataset từ input_fn và khung sẽ đảm nhiệm việc tiêu thụ các phần tử của nó cho bạn. Ví dụ:

 import tensorflow_datasets as tfds

def train_input_fn():
  titanic = tf.data.experimental.make_csv_dataset(
      titanic_file, batch_size=32,
      label_name="survived")
  titanic_batches = (
      titanic.cache().repeat().shuffle(500)
      .prefetch(tf.data.experimental.AUTOTUNE))
  return titanic_batches
 
 embark = tf.feature_column.categorical_column_with_hash_bucket('embark_town', 32)
cls = tf.feature_column.categorical_column_with_vocabulary_list('class', ['First', 'Second', 'Third']) 
age = tf.feature_column.numeric_column('age')
 
 import tempfile
model_dir = tempfile.mkdtemp()
model = tf.estimator.LinearClassifier(
    model_dir=model_dir,
    feature_columns=[embark, cls, age],
    n_classes=2
)
 
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpefmfuc4o', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

 model = model.train(input_fn=train_input_fn, steps=100)
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1666: 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.6/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/feature_column/feature_column_v2.py:540: Layer.add_variable (from tensorflow.python.keras.engine.base_layer_v1) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.add_weight` method instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/optimizer_v2/ftrl.py:144: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.
Instructions for updating:
Call initializer instance with the dtype argument instead of passing it to the constructor
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...
INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpefmfuc4o/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...
INFO:tensorflow:loss = 0.6931472, step = 0
INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 100...
INFO:tensorflow:Saving checkpoints for 100 into /tmp/tmpefmfuc4o/model.ckpt.
INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 100...
INFO:tensorflow:Loss for final step: 0.58668363.

 result = model.evaluate(train_input_fn, steps=10)

for key, value in result.items():
  print(key, ":", value)
 
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2020-07-23T01:23:29Z
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpefmfuc4o/model.ckpt-100
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [1/10]
INFO:tensorflow:Evaluation [2/10]
INFO:tensorflow:Evaluation [3/10]
INFO:tensorflow:Evaluation [4/10]
INFO:tensorflow:Evaluation [5/10]
INFO:tensorflow:Evaluation [6/10]
INFO:tensorflow:Evaluation [7/10]
INFO:tensorflow:Evaluation [8/10]
INFO:tensorflow:Evaluation [9/10]
INFO:tensorflow:Evaluation [10/10]
INFO:tensorflow:Inference Time : 0.83507s
INFO:tensorflow:Finished evaluation at 2020-07-23-01:23:30
INFO:tensorflow:Saving dict for global step 100: accuracy = 0.675, accuracy_baseline = 0.58125, auc = 0.71750116, auc_precision_recall = 0.6480325, average_loss = 0.64111984, global_step = 100, label/mean = 0.41875, loss = 0.64111984, precision = 0.85714287, prediction/mean = 0.30204886, recall = 0.26865673
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 100: /tmp/tmpefmfuc4o/model.ckpt-100
accuracy : 0.675
accuracy_baseline : 0.58125
auc : 0.71750116
auc_precision_recall : 0.6480325
average_loss : 0.64111984
label/mean : 0.41875
loss : 0.64111984
precision : 0.85714287
prediction/mean : 0.30204886
recall : 0.26865673
global_step : 100

 for pred in model.predict(train_input_fn):
  for key, value in pred.items():
    print(key, ":", value)
  break
 
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from /tmp/tmpefmfuc4o/model.ckpt-100
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
logits : [-0.5965]
logistic : [0.3551]
probabilities : [0.6449 0.3551]
class_ids : [0]
classes : [b'0']
all_class_ids : [0 1]
all_classes : [b'0' b'1']