ترجمت واجهة Cloud Translation API‏ هذه الصفحة.
Switch to English

tf.data: إنشاء خطوط أنابيب إدخال TensorFlow

عرض على TensorFlow.org تشغيل في Google Colab عرض المصدر على جيثب تنزيل دفتر الملاحظات

تمكّنك واجهة برمجة تطبيقات tf.data من إنشاء خطوط أنابيب إدخال معقدة من قطع بسيطة قابلة لإعادة الاستخدام. على سبيل المثال ، قد يقوم خط الأنابيب الخاص بنموذج الصورة بتجميع البيانات من الملفات في نظام الملفات الموزعة ، وتطبيق الاضطرابات العشوائية على كل صورة ، ودمج الصور المحددة عشوائيًا في مجموعة للتدريب. قد يتضمن خط الأنابيب لنموذج نصي استخراج الرموز من بيانات النص الخام ، وتحويلها إلى تضمين معرفات مع جدول بحث ، وتجميع تسلسلات ذات أطوال مختلفة معًا. tf.data واجهة برمجة تطبيقات tf.data معالجة كميات كبيرة من البيانات ، والقراءة من تنسيقات البيانات المختلفة ، وإجراء تحويلات معقدة.

يقدم tf.data API تجريد tf.data.Dataset يمثل سلسلة من العناصر ، حيث يتكون كل عنصر من مكون واحد أو أكثر. على سبيل المثال ، في خط أنابيب الصورة ، قد يكون العنصر مثالاً تدريبياً فرديًا ، مع زوج من مكونات الموتر التي تمثل الصورة وملصقها.

هناك طريقتان مميزتان لإنشاء مجموعة بيانات:

  • ينشئ مصدر البيانات Dataset بيانات من البيانات المخزنة في الذاكرة أو في ملف واحد أو أكثر.

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

الميكانيكا الأساسية

لإنشاء خط إدخال ، يجب أن تبدأ بمصدر بيانات. على سبيل المثال ، لإنشاء Dataset بيانات من البيانات الموجودة في الذاكرة ، يمكنك استخدام tf.data.Dataset.from_tensors() أو tf.data.Dataset.from_tensor_slices() . بدلاً من ذلك ، إذا تم تخزين بيانات الإدخال الخاصة بك في ملف بتنسيق TFRecord الموصى به ، يمكنك استخدام tf.data.TFRecordDataset() .

بمجرد أن يكون لديك كائن Dataset ، يمكنك تحويله إلى مجموعة Dataset جديدة من خلال tf.data.Dataset استدعاءات الطريقة على كائن tf.data.Dataset . على سبيل المثال ، يمكنك تطبيق تحويلات لكل عنصر مثل Dataset.map() ، Dataset.map() متعددة العناصر مثل Dataset.batch() . راجع وثائق tf.data.Dataset للحصول على قائمة كاملة بالتحويلات.

كائن Dataset هو Python قابل للتكرار. هذا يجعل من الممكن استهلاك عناصرها باستخدام حلقة 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

أو من خلال إنشاء مكرر Python بشكل صريح باستخدام iter واستهلاك عناصره باستخدام next :

 it = iter(dataset)

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

بدلاً من ذلك ، يمكن استهلاك عناصر مجموعة البيانات باستخدام reduce التحويل ، مما يقلل من جميع العناصر للحصول على نتيجة واحدة. يوضح المثال التالي كيفية استخدام reduce تحول لحساب مجموع من مجموعة بيانات من الأعداد الصحيحة.

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

هيكل مجموعة البيانات

تحتوي مجموعة البيانات على عناصر لكل منها نفس البنية (المتداخلة) ويمكن أن تكون المكونات الفردية للهيكل من أي نوع يمكن تمثيله بواسطة tf.TypeSpec ، بما في ذلك tf.Tensor ، tf.sparse.SparseTensor ، tf.RaggedTensor ، tf.TensorArray ، أو tf.data.Dataset .

تتيح لك خاصية Dataset.element_spec فحص نوع كل مكون عنصر. تقوم الخاصية بإرجاع بنية متداخلة لكائنات tf.TypeSpec ، مطابقة بنية العنصر ، والتي قد تكون مكونًا واحدًا ، أو مجموعة من المكونات ، أو مجموعة متداخلة من المكونات. فمثلا:

 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

تدعم تحويلات Dataset البيانات مجموعات البيانات لأي هيكل. عند استخدام Dataset.map() و Dataset.filter() ، التي تطبق دالة على كل عنصر ، تحدد بنية العنصر وسيطات الدالة:

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

قراءة بيانات الإدخال

استهلاك صفيفات NumPy

راجع تحميل صفائف NumPy لمزيد من الأمثلة.

إذا كانت جميع بيانات الإدخال الخاصة بك تناسب الذاكرة ، فإن أبسط طريقة لإنشاء مجموعة Dataset منها هي تحويلها إلى tf.Tensor الكائنات واستخدام 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)>

تستهلك مولدات بايثون

مصدر بيانات شائع آخر يمكن ابتلاعه بسهولة ك tf.data.Dataset مجموعة tf.data.Dataset هي منشئ الثعبان.

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

يحول مُنشئ Dataset.from_generator منشئ الثعبان إلى tf.data.Dataset يعمل بكامل tf.data.Dataset .

يأخذ المُنشئ قابلاً للاستدعاء كمدخل وليس كمكرر. هذا يسمح لها بإعادة تشغيل المولد عندما يصل إلى النهاية. يأخذ وسيطة args اختيارية ، والتي يتم تمريرها كوسيطات للاستدعاء.

الوسيطة output_types مطلوبة لأن tf.data ينشئ tf.Graph داخليًا وتتطلب حواف الرسم البياني 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]

الوسيطة output_shapes غير مطلوبة ولكنها موصى بها بشدة نظرًا لأن العديد من عمليات tensorflow لا تدعم أجهزة tensors ذات الترتيب غير المعروف. إذا كان طول محور معين غير معروف أو متغير ، output_shapes None في output_shapes .

من المهم أيضًا ملاحظة أن output_shapes output_types تتبع نفس قواعد التعشيش مثل طرق مجموعات البيانات الأخرى.

هنا مولد مثال يوضح كلا الجانبين ، فإنه يعيد صفائف المصفوفات ، حيث يكون الصفيف الثاني متجهًا بطول غير معروف.

 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]

إخراج الأول هو int32 والثاني هو float32 .

العنصر الأول عبارة عن عددي ، وشكل () ، والثاني هو ناقل بطول غير معروف ، وشكل (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)>

الآن يمكن استخدامه مثل tf.data.Dataset عادي. لاحظ أنه عند تجميع مجموعة بيانات ذات شكل متغير ، تحتاج إلى استخدام 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.    ]]

للحصول على مثال أكثر واقعية ، حاول التفاف preprocessing.image.ImageDataGenerator كمجموعة بيانات tf.data.Dataset .

قم أولاً بتنزيل البيانات:

 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

قم 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)>

استهلاك بيانات TFRecord

راجع تحميل سجلات TF للحصول على مثال من طرف إلى طرف.

يدعم tf.data API مجموعة متنوعة من تنسيقات الملفات بحيث يمكنك معالجة مجموعات البيانات الكبيرة التي لا تتناسب مع الذاكرة. على سبيل المثال ، تنسيق ملف TFRecord هو تنسيق ثنائي بسيط موجه نحو التسجيل يستخدمه العديد من تطبيقات TensorFlow لبيانات التدريب. تمكنك فئة tf.data.TFRecordDataset من التدفق على محتويات ملف واحد أو أكثر من ملفات TFRecord كجزء من خط أنابيب الإدخال.

فيما يلي مثال على استخدام ملف الاختبار من لافتات اسم الشارع الفرنسية (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

يمكن أن تكون وسيطة filenames إلى مُهيئ TFRecordDataset سلسلة أو قائمة سلاسل أو tf.Tensor . لذلك إذا كان لديك مجموعتان من الملفات لأغراض التدريب والتحقق من الصحة ، يمكنك إنشاء طريقة مصنع تنتج مجموعة البيانات ، مع أخذ أسماء الملفات كوسيطة إدخال:

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

تستخدم العديد من مشاريع TensorFlow المتسلسلة tf.train.Example السجلات في ملفات TFRecord الخاصة بها. يجب فك تشفيرها قبل أن يتم فحصها:

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

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

استهلاك البيانات النصية

راجع تحميل النص للحصول على مثال نهاية إلى نهاية.

يتم توزيع العديد من مجموعات البيانات كملف نصي واحد أو أكثر. يوفر tf.data.TextLineDataset طريقة سهلة لاستخراج الأسطر من ملف نصي واحد أو أكثر. بالنظر إلى اسم ملف أو أكثر ، TextLineDataset عنصرًا بقيمة سلسلة واحدة لكل سطر من هذه الملفات.

 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)
 

فيما يلي الأسطر القليلة الأولى من الملف الأول:

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

Dataset.interleave الخطوط بين الملفات ، استخدم Dataset.interleave . هذا يجعل من السهل خلط الملفات معًا. في ما يلي الأسطر الأولى والثانية والثالثة من كل ترجمة:

 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'

بشكل افتراضي ، ينتج TextLineDataset كل سطر من كل ملف ، وهو ما قد لا يكون مرغوبًا ، على سبيل المثال ، إذا بدأ الملف بخط رأس ، أو يحتوي على تعليقات. يمكن إزالة هذه الخطوط باستخدام Dataset.skip() أو Dataset.filter() . هنا ، يمكنك تخطي السطر الأول ، ثم التصفية للعثور على الناجين فقط.

 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'

استهلاك بيانات CSV

انظر تحميل ملفات CSV ، وتحميل Pandas DataFrames لمزيد من الأمثلة.

تنسيق ملف CSV هو تنسيق شائع لتخزين البيانات المجدولة في نص عادي.

فمثلا:

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

إذا كانت بياناتك مناسبة للذاكرة ، فإن نفس طريقة Dataset.from_tensor_slices تعمل على القواميس ، مما يسمح باستيراد هذه البيانات بسهولة:

 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'

طريقة أكثر قابلية للتحجيم هي التحميل من القرص حسب الضرورة.

توفر الوحدة النمطية tf.data طرقًا لاستخراج السجلات من ملف CSV أو أكثر يتوافق مع RFC 4180 .

إن دالة experimental.make_csv_dataset هي الواجهة عالية المستوى لقراءة مجموعات ملفات csv. وهو يدعم الاستدلال على نوع العمود والعديد من الميزات الأخرى ، مثل الخلط والتبديل ، لجعل الاستخدام بسيطًا.

 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']

يمكنك استخدام وسيطة select_columns إذا كنت بحاجة فقط إلى مجموعة فرعية من الأعمدة.

 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']

هناك أيضًا فئة experimental.CsvDataset ذات مستوى أدنى. فئة بيانات مجموعة البيانات التي توفر تحكمًا أكثر دقة. لا يدعم الاستدلال نوع العمود. بدلاً من ذلك ، يجب تحديد نوع كل عمود.

 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']

إذا كانت بعض الأعمدة فارغة ، تتيح لك هذه الواجهة ذات المستوى المنخفض توفير القيم الافتراضية بدلاً من أنواع الأعمدة.

 %%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]

بشكل افتراضي ، ينتج عن CsvDataset كل عمود من كل سطر من الملف ، والذي قد لا يكون مرغوبًا فيه ، على سبيل المثال إذا بدأ الملف بخط رأس يجب تجاهله ، أو إذا كانت بعض الأعمدة غير مطلوبة في الإدخال. يمكن إزالة هذه الخطوط والحقول باستخدام وسيطات header و select_cols على التوالي.

 # 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]

تستهلك مجموعات من الملفات

هناك العديد من مجموعات البيانات الموزعة كمجموعة من الملفات ، حيث يكون كل ملف مثالاً.

 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)

 

يحتوي الدليل الجذر على دليل لكل فئة:

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

تعتبر الملفات الموجودة في كل دليل فئة أمثلة:

 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'

قراءة البيانات باستخدام وظيفة tf.io.read_file واستخراج الملصق من المسار ، وإرجاع أزواج (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'

عناصر مجموعة البيانات المجمعة

دفعات بسيطة

أبسط شكل من مجموعات التجميع n عناصر متتالية من مجموعة البيانات في عنصر واحد. يقوم Dataset.batch() بذلك بالضبط ، مع نفس القيود التي tf.stack() عامل tf.stack() ، المطبق على كل مكون من العناصر: أي لكل مكون i ، يجب أن يكون لكل العناصر موتر من نفس الشكل بالضبط.

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

بينما تحاول tf.data نشر معلومات الشكل ، تؤدي الإعدادات الافتراضية لـ Dataset.batch إلى حجم مجموعة غير معروف لأن الدفعة الأخيرة قد لا تكون ممتلئة. لاحظ None في الشكل:

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

استخدم الوسيطة drop_remainder لتجاهل الدفعة الأخيرة والحصول على انتشار كامل الشكل:

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

يندمج مع الحشو

تعمل الوصفة المذكورة أعلاه مع أجهزة التنوتر ذات الحجم نفسه. ومع ذلك ، تعمل العديد من النماذج (مثل نماذج التسلسل) مع بيانات الإدخال التي يمكن أن يكون لها حجم متفاوت (مثل تسلسلات أطوال مختلفة). للتعامل مع هذه الحالة ، Dataset.padded_batch تحويل Dataset.padded_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,))

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 بتعيين حشو مختلف لكل بُعد من كل مكون ، وقد يكون متغير الطول (محدد بواسطة None في المثال أعلاه) أو بطول ثابت. من الممكن أيضًا تجاوز قيمة الحشو ، والتي تكون القيمة الافتراضية هي 0.

سير عمل التدريب

معالجة فترات متعددة

تقدم واجهة برمجة تطبيقات tf.data طريقتين رئيسيتين لمعالجة فترات متعددة من نفس البيانات.

إن أبسط طريقة للتكرار عبر مجموعة بيانات في فترات متعددة هي استخدام تحويل Dataset.repeat() . أولاً ، أنشئ مجموعة بيانات من البيانات العملاقة:

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

Dataset.repeat() تطبيق تحويل Dataset.repeat() بدون وسائط إلى تكرار الإدخال إلى أجل غير مسمى.

تسلسل التحول Dataset.repeat حججه دون الإشارة إلى نهاية حقبة وبداية الحقبة التالية. وبسبب هذا ، فإن مجموعة Dataset.batch المطبقة بعد Dataset.repeat ستنتج دفعات تتداخل مع حدود عصر:

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

بي إن جي

إذا كنت بحاجة إلى فصل واضح Dataset.batch ، ضع Dataset.batch قبل التكرار:

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

plot_batch_sizes(titanic_batches)
 

بي إن جي

إذا كنت ترغب في إجراء حساب مخصص (على سبيل المثال ، جمع الإحصائيات) في نهاية كل حقبة ، فمن الأسهل إعادة تشغيل تكرار مجموعة البيانات في كل عصر:

 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

خلط بيانات الإدخال عشوائيًا

Dataset.shuffle() التحويل Dataset.shuffle() على مخزن مؤقت ذي حجم ثابت ويختار العنصر التالي بشكل عشوائي بشكل عشوائي من ذلك المخزن المؤقت.

أضف فهرسًا إلى مجموعة البيانات حتى تتمكن من رؤية التأثير:

 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 هو 100 ، وحجم الدفعة 20 ، فإن الدفعة الأولى لا تحتوي على عناصر بمؤشر يزيد عن 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]

كما هو الحال مع Dataset.batch فإن الترتيب Dataset.repeat بـ Dataset.repeat مهم.

Dataset.shuffle لا يشير إلى نهاية حقبة حتى يصبح المخزن المؤقت Dataset.shuffle فارغًا. لذا ، فإن التبديل العشوائي قبل التكرار سيظهر كل عنصر في عصر واحد قبل الانتقال إلى التالي:

 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>

بي إن جي

لكن التكرار قبل خلط ورق اللعب يخلط حدود العصر معًا:

 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>

بي إن جي

بيانات المعالجة المسبقة

ينتج عن تحويل Dataset.map(f) مجموعة بيانات جديدة عن طريق تطبيق دالة معينة f على كل عنصر من عناصر مجموعة بيانات الإدخال. يعتمد على وظيفة map() التي يتم تطبيقها بشكل عام على القوائم (والهياكل الأخرى) بلغات البرمجة الوظيفية. تأخذ الدالة f كائنات tf.Tensor التي تمثل عنصرًا واحدًا في الإدخال ، وتعيد كائنات tf.Tensor التي ستمثل عنصرًا واحدًا في مجموعة البيانات الجديدة. يستخدم تنفيذه عمليات TensorFlow القياسية لتحويل عنصر إلى آخر.

يغطي هذا القسم أمثلة شائعة حول كيفية استخدام Dataset.map() .

فك تشفير بيانات الصورة وتغيير حجمها

عند تدريب شبكة عصبية على بيانات الصور الواقعية ، غالبًا ما يكون من الضروري تحويل الصور ذات الأحجام المختلفة إلى حجم مشترك ، بحيث يمكن تجميعها في حجم ثابت.

إعادة بناء مجموعة بيانات أسماء الزهور:

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

اكتب دالة تعالج عناصر مجموعة البيانات.

 # 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
 

اختبر أنه يعمل.

 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)
 

بي إن جي

قم بتعيينه فوق مجموعة البيانات.

 images_ds = list_ds.map(parse_image)

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

بي إن جي

بي إن جي

تطبيق منطق بايثون التعسفي

لأسباب تتعلق بالأداء ، استخدم عمليات TensorFlow لمعالجة بياناتك مسبقًا كلما أمكن ذلك. ومع ذلك ، من المفيد في بعض الأحيان استدعاء مكتبات Python الخارجية عند تحليل بيانات الإدخال الخاصة بك. يمكنك استخدام عملية tf.py_function() في تحويل Dataset.map() .

على سبيل المثال، إذا كنت تريد تطبيق دوران عشوائي، و tf.image حدة ليس لديها سوى tf.image.rot90 ، وهي ليست مفيدة جدا لتكبير الصورة.

لتوضيح tf.py_function ، حاول استخدام الوظيفة 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).

بي إن جي

لاستخدام هذه الوظيفة مع Dataset.map يتم تطبيق نفس المحاذير كما هو الحال مع Dataset.from_generator ، تحتاج إلى وصف أشكال وأنواع الإرجاع عند تطبيق الوظيفة:

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

بي إن جي

بي إن جي

تحليل tf.Example رسائل المخزن المؤقت للبروتوكول

استخراج العديد من خطوط أنابيب الإدخال tf.train.Example رسائل المخزن المؤقت بروتوكول من تنسيق TFRecord. يحتوي كل سجل tf.train.Example على واحد أو أكثر من "الميزات" ، ويحول خط أنابيب الإدخال عادةً هذه الميزات إلى موتر.

 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>

يمكنك العمل مع tf.train.Example protos خارج tf.data.Dataset لفهم البيانات:

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

بي إن جي

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

نوافذ السلاسل الزمنية

للحصول على مثال لسلسلة زمنية من نهاية إلى نهاية ، راجع: التنبؤ بالسلسلة الزمنية .

غالبًا ما يتم تنظيم بيانات السلاسل الزمنية مع الحفاظ على المحور الزمني.

استخدم Dataset.range بسيط لتوضيح:

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

عادةً ما تريد النماذج التي تستند إلى هذا النوع من البيانات شريحة زمنية متجاورة.

سيكون أبسط نهج هو تجميع البيانات:

باستخدام 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]

أو لإجراء تنبؤات كثيفة خطوة واحدة في المستقبل ، يمكنك تغيير الميزات والتسميات بخطوة واحدة بالنسبة لبعضها البعض:

 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]

للتنبؤ بنافذة كاملة بدلاً من الإزاحة الثابتة ، يمكنك تقسيم الدفعات إلى قسمين:

 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]

للسماح ببعض التداخل بين ميزات دفعة واحدة وتسميات أخرى ، استخدم 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]

باستخدام window

أثناء استخدام أعمال Dataset.batch ، هناك حالات قد تحتاج فيها إلى تحكم أفضل. Dataset.window طريقة Dataset.window كاملاً ، ولكنها تتطلب بعض العناية: فهي تُرجع مجموعة Dataset من Datasets . انظر هيكل مجموعة البيانات للحصول على التفاصيل.

 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>

يمكن أن تأخذ طريقة Dataset.flat_map مجموعة بيانات من مجموعات البيانات Dataset.flat_map في مجموعة بيانات واحدة:

  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 

في جميع الحالات تقريبًا ، ستحتاج إلى .batch مجموعة البيانات أولاً:

 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]

الآن ، يمكنك أن ترى أن وسيطة shift تتحكم في مدى تحرك كل نافذة.

عند وضع هذا معًا ، يمكنك كتابة هذه الوظيفة:

 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]

ثم من السهل استخراج الملصقات ، كما كان من قبل:

 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]

جارى الاختزال

عند العمل مع مجموعة بيانات غير متوازنة بشكل كبير في الفصل ، قد ترغب في إعادة تشكيل مجموعة البيانات. يوفر tf.data طريقتين للقيام بذلك. تعد مجموعة بيانات الاحتيال الخاصة ببطاقة الائتمان مثالاً جيدًا على هذا النوع من المشاكل.

 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()])
 

الآن ، تحقق من توزيع الطبقات ، فهو منحرف للغاية:

 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]

من الطرق الشائعة للتدريب باستخدام مجموعة بيانات غير متوازنة موازنة ذلك. تتضمن tf.data بعض الطرق التي تمكن سير العمل هذا:

أخذ عينات مجموعات البيانات

تتمثل إحدى طرق إعادة تشكيل مجموعة البيانات في استخدام sample_from_datasets . هذا هو أكثر قابلية للتطبيق عندما يكون لديك منفصلة data.Dataset لكل فئة.

هنا ، ما عليك سوى استخدام الفلتر لتوليدها من بيانات الاحتيال الخاصة ببطاقة الائتمان:

 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]

لاستخدام tf.data.experimental.sample_from_datasets بتمرير مجموعات البيانات والوزن لكل منها:

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

تنتج مجموعة البيانات الآن أمثلة لكل فئة باحتمال 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]

إعادة الرفض

تتمثل مشكلة واحدة في طريقة experimental.sample_from_datasets المذكورة أعلاه من مجموعات البيانات في أنها تحتاج إلى tf.data.Dataset منفصلة لكل فصل. يعمل استخدام Dataset.filter ، ولكن ينتج عنه تحميل جميع البيانات مرتين.

يمكن تطبيق وظيفة data.experimental.rejection_resample على مجموعة بيانات لإعادة التوازن إليها ، مع تحميلها مرة واحدة فقط. سيتم إسقاط العناصر من مجموعة البيانات لتحقيق التوازن.

data.experimental.rejection_resample تأخذ وسيطة class_func . يتم تطبيق class_func هذا على كل عنصر مجموعة بيانات ، ويتم استخدامه لتحديد الفئة التي ينتمي إليها المثال لأغراض الموازنة.

عناصر creditcard_ds هي بالفعل أزواج (features, label) . لذا يحتاج class_func فقط إلى إرجاع هذه التصنيفات:

 def class_func(features, label):
  return label
 

يحتاج جهاز إعادة التشكيل أيضًا إلى توزيع مستهدف ، وتقديرًا أوليًا للتوزيع:

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

يتعامل unbatch إعادة unbatch مع أمثلة فردية ، لذلك يجب عليك unbatch مجموعة البيانات قبل تطبيق أداة إعادة unbatch :

 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:


تقوم عملية إعادة class_func بإعادة class_func (class, example) من أزواج class_func . في هذه الحالة ، كان example بالفعل زوجًا (feature, label) ، لذا استخدم map لإسقاط النسخة الإضافية من التسميات:

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

تنتج مجموعة البيانات الآن أمثلة لكل فئة باحتمال 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]

فحص نقاط التكرار

يدعم Tensorflow أخذ نقاط التفتيش بحيث أنه عند إعادة تشغيل عملية التدريب الخاصة بك ، يمكنه استعادة أحدث نقطة تفتيش لاستعادة معظم تقدمه. بالإضافة إلى فحص متغيرات النموذج ، يمكنك أيضًا التحقق من تقدم مكرر مجموعة البيانات. قد يكون هذا مفيدًا إذا كان لديك مجموعة بيانات كبيرة ولا تريد بدء مجموعة البيانات من البداية في كل إعادة تشغيل. لاحظ مع ذلك أن نقاط فحص المكرر قد تكون كبيرة ، لأن التحولات مثل shuffle prefetch تتطلب عناصر التخزين المؤقت داخل المكرر.

لتضمين المكرر الخاص بك في نقطة تفتيش ، قم بتمرير tf.train.Checkpoint إلى 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]

استخدام واجهات برمجة التطبيقات عالية المستوى

tf.keras

tf.keras API العديد من جوانب إنشاء نماذج التعلم الآلي وتنفيذها. في .fit() و .evaluate() و .predict() واجهات برمجة التطبيقات دعم مجموعات البيانات كمدخلات. في ما يلي مجموعة بيانات سريعة وإعداد النموذج:

 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'])
 

تمرير مجموعة بيانات من أزواج (feature, label) هو كل ما تحتاجه لـ Model.fit و Model.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>

إذا قمت بتمرير مجموعة بيانات لا حصر لها ، على سبيل المثال عن طريق استدعاء Dataset.repeat() ، فأنت بحاجة فقط لتمرير وسيطة 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>

للتقييم يمكنك اجتياز عدد خطوات التقييم:

 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

لمجموعات البيانات الطويلة ، عيّن عدد الخطوات للتقييم:

 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

التسميات غير مطلوبة عند استدعاء 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)

ولكن يتم تجاهل التسميات إذا قمت بتمرير مجموعة بيانات تحتوي عليها:

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

tf.estimator

لاستخدام Dataset في input_fn من tf.estimator.Estimator ، ما tf.estimator.Estimator سوى إرجاع Dataset من input_fn إطار العمل استهلاك عناصرها نيابة عنك. فمثلا:

 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']