سخنرانی ها ، جلسات محصول ، کارگاه ها و موارد دیگر را از لیست پخش Google I / O مشاهده کنید

داده های CSV را بارگیری کنید

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHubدانلود دفترچه یادداشت

این آموزش نمونه هایی از نحوه استفاده از داده های CSV با TensorFlow را ارائه می دهد.

این دو قسمت اصلی دارد:

  1. بارگیری داده ها از روی دیسک
  2. پیش پردازش آن به فرم مناسب برای آموزش.

این آموزش بر روی بارگذاری متمرکز است و چند نمونه سریع از پیش پردازش را بیان می کند. برای یک آموزش است که تمرکز بر جنبه پیش پردازش را ببینید راهنمای لایه از پیش پردازش و آموزش .

برپایی

import pandas as pd
import numpy as np

# Make numpy values easier to read.
np.set_printoptions(precision=3, suppress=True)

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.layers.experimental import preprocessing

در داده های حافظه

برای هر مجموعه داده CSV کوچک ، ساده ترین راه برای آموزش یک مدل TensorFlow بر روی آن ، بارگیری آن در حافظه به عنوان یک pandas Dataframe یا یک آرایه NumPy است.

یک مثال نسبتاً ساده ، مجموعه داده های abalone است .

  • مجموعه داده کوچک است.
  • همه ویژگی های ورودی همه مقادیر نقطه شناور با برد محدود هستند.

در اینجا نحوه بارگیری داده ها در Pandas DataFrame :

abalone_train = pd.read_csv(
    "https://storage.googleapis.com/download.tensorflow.org/data/abalone_train.csv",
    names=["Length", "Diameter", "Height", "Whole weight", "Shucked weight",
           "Viscera weight", "Shell weight", "Age"])

abalone_train.head()

این مجموعه داده شامل مجموعه ای از اندازه گیری های آبالون ، نوعی حلزون دریایی است.

پوسته آبله

"پوسته آبلون" (توسط Nicki Dugan Pogue ، CC BY-SA 2.0)

وظیفه اسمی این مجموعه داده پیش بینی سن از اندازه گیری های دیگر است ، بنابراین ویژگی ها و برچسب ها را برای آموزش جدا کنید:

abalone_features = abalone_train.copy()
abalone_labels = abalone_features.pop('Age')

برای این مجموعه داده با همه ویژگی ها یکسان رفتار خواهید کرد. ویژگی ها را در یک آرایه NumPy قرار دهید:

abalone_features = np.array(abalone_features)
abalone_features
array([[0.435, 0.335, 0.11 , ..., 0.136, 0.077, 0.097],
       [0.585, 0.45 , 0.125, ..., 0.354, 0.207, 0.225],
       [0.655, 0.51 , 0.16 , ..., 0.396, 0.282, 0.37 ],
       ...,
       [0.53 , 0.42 , 0.13 , ..., 0.374, 0.167, 0.249],
       [0.395, 0.315, 0.105, ..., 0.118, 0.091, 0.119],
       [0.45 , 0.355, 0.12 , ..., 0.115, 0.067, 0.16 ]])

بعد یک مدل رگرسیون ایجاد کنید سن را پیش بینی کنید. از آنجا که تنها یک keras.Sequential ورودی واحد وجود دارد ، یک keras.Sequential وجود دارد. در اینجا مدل keras.Sequential کافی است.

abalone_model = tf.keras.Sequential([
  layers.Dense(64),
  layers.Dense(1)
])

abalone_model.compile(loss = tf.losses.MeanSquaredError(),
                      optimizer = tf.optimizers.Adam())

برای آموزش آن مدل ، ویژگی ها و برچسب ها را به Model.fit :

abalone_model.fit(abalone_features, abalone_labels, epochs=10)
Epoch 1/10
104/104 [==============================] - 1s 2ms/step - loss: 61.2118
Epoch 2/10
104/104 [==============================] - 0s 2ms/step - loss: 11.9831
Epoch 3/10
104/104 [==============================] - 0s 2ms/step - loss: 8.7308
Epoch 4/10
104/104 [==============================] - 0s 1ms/step - loss: 8.1889
Epoch 5/10
104/104 [==============================] - 0s 2ms/step - loss: 7.6973
Epoch 6/10
104/104 [==============================] - 0s 2ms/step - loss: 7.2868
Epoch 7/10
104/104 [==============================] - 0s 2ms/step - loss: 6.9842
Epoch 8/10
104/104 [==============================] - 0s 1ms/step - loss: 6.7556
Epoch 9/10
104/104 [==============================] - 0s 1ms/step - loss: 6.6239
Epoch 10/10
104/104 [==============================] - 0s 2ms/step - loss: 6.5126
<tensorflow.python.keras.callbacks.History at 0x7f4bf8402410>

شما فقط ابتدایی ترین روش آموزش مدل با استفاده از داده های CSV را مشاهده کرده اید. در مرحله بعدی ، شما خواهید آموخت که چگونه پیش پردازش را برای عادی سازی ستون های عددی اعمال کنید.

پیش پردازش اولیه

این روش خوبی است که ورودی های مدل خود را عادی کنید. لایه های experimental.preprocessing پردازش یک روش مناسب برای ساخت این نرمال در مدل شما است.

این لایه میانگین و واریانس هر ستون را از قبل محاسبه می کند و برای عادی سازی داده ها از این موارد استفاده می کند.

ابتدا لایه را ایجاد می کنید:

normalize = preprocessing.Normalization()

سپس از روش Normalization.adapt() برای تطبیق لایه نرمال سازی با داده های خود استفاده می کنید.

normalize.adapt(abalone_features)

سپس از لایه نرمال سازی در مدل خود استفاده کنید:

norm_abalone_model = tf.keras.Sequential([
  normalize,
  layers.Dense(64),
  layers.Dense(1)
])

norm_abalone_model.compile(loss = tf.losses.MeanSquaredError(),
                           optimizer = tf.optimizers.Adam())

norm_abalone_model.fit(abalone_features, abalone_labels, epochs=10)
Epoch 1/10
104/104 [==============================] - 0s 2ms/step - loss: 92.2295
Epoch 2/10
104/104 [==============================] - 0s 2ms/step - loss: 52.6606
Epoch 3/10
104/104 [==============================] - 0s 2ms/step - loss: 15.8834
Epoch 4/10
104/104 [==============================] - 0s 2ms/step - loss: 5.6510
Epoch 5/10
104/104 [==============================] - 0s 2ms/step - loss: 5.0132
Epoch 6/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9937
Epoch 7/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9871
Epoch 8/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9607
Epoch 9/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9417
Epoch 10/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9781
<tensorflow.python.keras.callbacks.History at 0x7f4bf8188490>

انواع داده های مخلوط

مجموعه داده "تایتانیک" حاوی اطلاعاتی در مورد مسافران تایتانیک است. وظیفه اسمی این مجموعه داده پیش بینی زنده ماندن است.

تایتانیک

تصویر از ویکی مدیا

داده های خام به راحتی می توانند به عنوان Pandas DataFrame ، اما بلافاصله به عنوان ورودی به مدل DataFrame قابل استفاده نیستند.

titanic = pd.read_csv("https://storage.googleapis.com/tf-datasets/titanic/train.csv")
titanic.head()
titanic_features = titanic.copy()
titanic_labels = titanic_features.pop('survived')

به دلیل انواع و دامنه های مختلف داده ، نمی توانید به سادگی ویژگی ها را در آرایه NumPy انباشته و به یک keras.Sequential . هر ستون باید به صورت جداگانه اداره شود.

به عنوان یک گزینه ، می توانید داده های خود را به صورت آفلاین پیش پردازش کنید (با استفاده از هر ابزاری که دوست دارید) برای تبدیل ستون های دسته بندی به ستون های عددی ، و سپس خروجی پردازش شده را به مدل TensorFlow خود منتقل کنید. عیب این روش این است که اگر مدل خود را پس انداز و صادر کنید ، پیش پردازش با آن ذخیره نمی شود. لایه های experimental.preprocessing پردازش از این مشکل اجتناب می کنند زیرا آنها بخشی از مدل هستند.

در این مثال ، شما مدلی ایجاد خواهید کرد که منطق پیش پردازش را با استفاده از API کاربردی Keras پیاده سازی می کند . همچنین می توانید این کار را با طبقه بندی فرعی انجام دهید .

API عملکردی با سنسورهای "نمادین" کار می کند. تانسورهای عادی "مشتاق" دارای یک ارزش هستند. در مقابل ، این سنسورهای "نمادین" چنین نمی کنند. در عوض آنها پیگیری می کنند که کدام عملیات بر روی آنها اجرا می شود و نمایشی از محاسبه را ایجاد می کنند که بعداً می توانید اجرا کنید. در اینجا یک مثال سریع آورده شده است:

# Create a symbolic input
input = tf.keras.Input(shape=(), dtype=tf.float32)

# Do a calculation using is
result = 2*input + 1

# the result doesn't have a value
result
<KerasTensor: shape=(None,) dtype=float32 (created by layer 'tf.__operators__.add')>
calc = tf.keras.Model(inputs=input, outputs=result)
print(calc(1).numpy())
print(calc(2).numpy())
3.0
5.0

برای ساختن مدل پیش پردازش ، با ساختن مجموعه ای از keras.Input نمادین keras.Input اشیا keras.Input ، مطابق با نام ها و انواع داده های ستون های CSV است.

inputs = {}

for name, column in titanic_features.items():
  dtype = column.dtype
  if dtype == object:
    dtype = tf.string
  else:
    dtype = tf.float32

  inputs[name] = tf.keras.Input(shape=(1,), name=name, dtype=dtype)

inputs
{'sex': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'sex')>,
 'age': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'age')>,
 'n_siblings_spouses': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'n_siblings_spouses')>,
 'parch': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'parch')>,
 'fare': <KerasTensor: shape=(None, 1) dtype=float32 (created by layer 'fare')>,
 'class': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'class')>,
 'deck': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'deck')>,
 'embark_town': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'embark_town')>,
 'alone': <KerasTensor: shape=(None, 1) dtype=string (created by layer 'alone')>}

اولین قدم در منطق پیش پردازش شما این است که ورودی های عددی را با هم پیوند دهید و آنها را از طریق یک لایه عادی اجرا کنید:

numeric_inputs = {name:input for name,input in inputs.items()
                  if input.dtype==tf.float32}

x = layers.Concatenate()(list(numeric_inputs.values()))
norm = preprocessing.Normalization()
norm.adapt(np.array(titanic[numeric_inputs.keys()]))
all_numeric_inputs = norm(x)

all_numeric_inputs
<KerasTensor: shape=(None, 4) dtype=float32 (created by layer 'normalization_1')>

تمام نتایج نمادین پیش پردازش را جمع آوری کنید تا بعداً آنها را به هم پیوند دهید.

preprocessed_inputs = [all_numeric_inputs]

برای ورودی های رشته از تابع preprocessing.StringLookup برای نقشه برداری از رشته ها به شاخص های عدد صحیح در واژگان استفاده کنید. در مرحله بعد ، از preprocessing.CategoryEncoding float32 برای تبدیل شاخص ها به داده های float32 مناسب برای مدل استفاده کنید.

تنظیمات پیش فرض برای preprocessing.CategoryEncoding طبقه بندی preprocessing.CategoryEncoding برای هر ورودی یک بردار داغ ایجاد می کند. یک layers.Embedding . layers.Embedding نیز کار می کند. برای کسب اطلاعات بیشتر در مورد این موضوع ، به راهنمای لایه های پیش پردازش و آموزش مراجعه کنید.

for name, input in inputs.items():
  if input.dtype == tf.float32:
    continue

  lookup = preprocessing.StringLookup(vocabulary=np.unique(titanic_features[name]))
  one_hot = preprocessing.CategoryEncoding(max_tokens=lookup.vocab_size())

  x = lookup(input)
  x = one_hot(x)
  preprocessed_inputs.append(x)
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.
WARNING:tensorflow:vocab_size is deprecated, please use vocabulary_size.
WARNING:tensorflow:max_tokens is deprecated, please use num_tokens instead.

با مجموعه ای از inputs و inputs processed_inputs ، می توانید تمام ورودی های پیش پردازش شده را با هم پیوند دهید و مدلی را بسازید که پیش پردازش را مدیریت کند:

preprocessed_inputs_cat = layers.Concatenate()(preprocessed_inputs)

titanic_preprocessing = tf.keras.Model(inputs, preprocessed_inputs_cat)

tf.keras.utils.plot_model(model = titanic_preprocessing , rankdir="LR", dpi=72, show_shapes=True)

png

این model فقط شامل پیش پردازش ورودی است. می توانید آن را اجرا کنید تا ببینید چه تاثیری بر داده های شما دارد. مدل های Keras Pandas DataFrames به طور خودکار تبدیل DataFrames زیرا مشخص نیست که باید به یک تنسور تبدیل شود یا به یک فرهنگ لغت از سنسورها. بنابراین آن را به دیکشنری تنور تبدیل کنید:

titanic_features_dict = {name: np.array(value) 
                         for name, value in titanic_features.items()}

اولین نمونه آموزش را برش دهید و آن را به این مدل پیش پردازش منتقل کنید ، ویژگی های عددی و رشته های یک رشته ای را می بینید که همه با هم ترکیب شده اند:

features_dict = {name:values[:1] for name, values in titanic_features_dict.items()}
titanic_preprocessing(features_dict)
<tf.Tensor: shape=(1, 33), dtype=float32, numpy=
array([[-0.61 ,  0.395, -0.479, -0.497,  0.   ,  0.   ,  0.   ,  1.   ,

         0.   ,  0.   ,  0.   ,  0.   ,  1.   ,  0.   ,  0.   ,  0.   ,
         0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  1.   ,  0.   ,
         0.   ,  0.   ,  0.   ,  1.   ,  0.   ,  0.   ,  0.   ,  1.   ,
         0.   ]], dtype=float32)>

اکنون مدل را در بالای این مورد بسازید:

def titanic_model(preprocessing_head, inputs):
  body = tf.keras.Sequential([
    layers.Dense(64),
    layers.Dense(1)
  ])

  preprocessed_inputs = preprocessing_head(inputs)
  result = body(preprocessed_inputs)
  model = tf.keras.Model(inputs, result)

  model.compile(loss=tf.losses.BinaryCrossentropy(from_logits=True),
                optimizer=tf.optimizers.Adam())
  return model

titanic_model = titanic_model(titanic_preprocessing, inputs)

وقتی مدل را آموزش می دهید ، فرهنگ لغت ویژگی ها را به عنوان x و برچسب را به عنوان y .

titanic_model.fit(x=titanic_features_dict, y=titanic_labels, epochs=10)
Epoch 1/10
20/20 [==============================] - 1s 4ms/step - loss: 0.6321
Epoch 2/10
20/20 [==============================] - 0s 4ms/step - loss: 0.5221
Epoch 3/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4835
Epoch 4/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4595
Epoch 5/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4463
Epoch 6/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4381
Epoch 7/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4299
Epoch 8/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4272
Epoch 9/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4238
Epoch 10/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4236
<tensorflow.python.keras.callbacks.History at 0x7f4c97f3a0d0>

از آنجا که پیش پردازش بخشی از مدل است ، می توانید مدل را ذخیره کرده و در جای دیگری بارگیری کنید و نتایج یکسانی بدست آورید:

titanic_model.save('test')
reloaded = tf.keras.models.load_model('test')
INFO:tensorflow:Assets written to: test/assets
features_dict = {name:values[:1] for name, values in titanic_features_dict.items()}

before = titanic_model(features_dict)
after = reloaded(features_dict)
assert (before-after)<1e-3
print(before)
print(after)
tf.Tensor([[-1.878]], shape=(1, 1), dtype=float32)
tf.Tensor([[-1.878]], shape=(1, 1), dtype=float32)

با استفاده از tf.data

در بخش قبلی هنگام آموزش مدل ، به تغییر داده ها و دسته بندی داده های داخلی مدل اعتماد کرده اید.

اگر به کنترل بیشتری بر روی خط لوله داده ورودی نیاز دارید یا نیاز به استفاده از داده هایی دارید که به راحتی در حافظه جای نمی گیرند: از tf.data استفاده کنید.

برای مثالهای بیشتر به راهنمای tf.data مراجعه کنید .

روشن در داده های حافظه

به عنوان اولین نمونه استفاده از tf.data برای داده های CSV ، کد زیر را در نظر بگیرید تا به صورت دستی فرهنگ لغت ویژگی های بخش قبل را برش دهید. برای هر شاخص ، این شاخص را برای هر ویژگی می گیرد:

import itertools

def slices(features):
  for i in itertools.count():
    # For each feature take index `i`
    example = {name:values[i] for name, values in features.items()}
    yield example

این را اجرا کنید و اولین مثال را چاپ کنید:

for example in slices(titanic_features_dict):
  for name, value in example.items():
    print(f"{name:19s}: {value}")
  break
sex                : male
age                : 22.0
n_siblings_spouses : 1
parch              : 0
fare               : 7.25
class              : Third
deck               : unknown
embark_town        : Southampton
alone              : n

ابتدایی ترینtf.data.Dataset در لودر اطلاعات حافظه سازنده Dataset.from_tensor_slices . این یکtf.data.Dataset برمی گرداند که نسخه کلی عملکرد slices فوق را درtf.data.Dataset پیاده سازی می کند.

features_ds = tf.data.Dataset.from_tensor_slices(titanic_features_dict)

می توانید مانند هر پایتون قابل تکرار دیگر از طریقtf.data.Dataset تکرار کنید:

for example in features_ds:
  for name, value in example.items():
    print(f"{name:19s}: {value}")
  break
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'

تابع from_tensor_slices می تواند از پس ساختارهای مختلف فرهنگ لغت یا tuples برآید. کد زیر مجموعه ای از جفتهای (features_dict, labels) می کند:

titanic_ds = tf.data.Dataset.from_tensor_slices((titanic_features_dict, titanic_labels))

برای آموزش یک مدل با استفاده از این Dataset ، باید حداقل داده ها را shuffle و batch کنید.

titanic_batches = titanic_ds.shuffle(len(titanic_labels)).batch(32)

به جای انتقال features و labels به Model.fit ، شما مجموعه داده را می گیرید:

titanic_model.fit(titanic_batches, epochs=5)
Epoch 1/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4225
Epoch 2/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4214
Epoch 3/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4203
Epoch 4/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4203
Epoch 5/5
20/20 [==============================] - 0s 5ms/step - loss: 0.4199
<tensorflow.python.keras.callbacks.History at 0x7f4c968ccf90>

از یک پرونده واحد

تاکنون این آموزش با داده های درون حافظه کار کرده است. tf.data یک جعبه ابزار بسیار مقیاس پذیر برای ساخت خطوط لوله داده است و چند عملکرد برای بارگیری پرونده های CSV فراهم می کند.

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

اکنون داده های CSV را از پرونده بخوانید و یکtf.data.Dataset ایجاد کنید.

(برای مشاهده اسناد کامل ، به tf.data.experimental.make_csv_dataset مراجعه کنید)

titanic_csv_ds = tf.data.experimental.make_csv_dataset(
    titanic_file_path,
    batch_size=5, # Artificially small to make examples easier to show.
    label_name='survived',
    num_epochs=1,
    ignore_errors=True,)

این عملکرد شامل بسیاری از ویژگی های راحت است بنابراین کار با داده ها آسان است. این شامل:

  • استفاده از سرصفحه های ستون به عنوان کلید واژه نامه.
  • تعیین خودکار نوع هر ستون.
for batch, label in titanic_csv_ds.take(1):
  for key, value in batch.items():
    print(f"{key:20s}: {value}")
  print()
  print(f"{'label':20s}: {label}")
sex                 : [b'male' b'male' b'male' b'male' b'male']
age                 : [28. 44. 40. 16. 25.]
n_siblings_spouses  : [8 0 0 0 1]
parch               : [2 0 0 0 0]
fare                : [69.55   7.925  0.    10.5   91.079]
class               : [b'Third' b'Third' b'First' b'Second' b'First']
deck                : [b'unknown' b'unknown' b'B' b'unknown' b'B']
embark_town         : [b'Southampton' b'Southampton' b'Southampton' b'Southampton' b'Cherbourg']
alone               : [b'n' b'y' b'y' b'y' b'n']

label               : [0 1 0 0 1]

همچنین می تواند داده ها را از حالت فشرده خارج کند. در اینجا یک فایل CSV gzipped حاوی مجموعه داده ترافیک بین ایالتی مترو است

یک ترافیک.

تصویر از ویکی مدیا

traffic_volume_csv_gz = tf.keras.utils.get_file(
    'Metro_Interstate_Traffic_Volume.csv.gz', 
    "https://archive.ics.uci.edu/ml/machine-learning-databases/00492/Metro_Interstate_Traffic_Volume.csv.gz",
    cache_dir='.', cache_subdir='traffic')
Downloading data from https://archive.ics.uci.edu/ml/machine-learning-databases/00492/Metro_Interstate_Traffic_Volume.csv.gz
409600/405373 [==============================] - 1s 2us/step

آرگومان compression_type را تنظیم کنید تا مستقیماً از پرونده فشرده بخواند:

traffic_volume_csv_gz_ds = tf.data.experimental.make_csv_dataset(
    traffic_volume_csv_gz,
    batch_size=256,
    label_name='traffic_volume',
    num_epochs=1,
    compression_type="GZIP")

for batch, label in traffic_volume_csv_gz_ds.take(1):
  for key, value in batch.items():
    print(f"{key:20s}: {value[:5]}")
  print()
  print(f"{'label':20s}: {label[:5]}")
holiday             : [b'None' b'None' b'None' b'None' b'None']
temp                : [291.08 273.08 296.58 301.02 288.18]
rain_1h             : [0.   0.   0.25 0.   0.  ]
snow_1h             : [0. 0. 0. 0. 0.]
clouds_all          : [ 1 90  0  0  0]
weather_main        : [b'Clear' b'Clouds' b'Rain' b'Clear' b'Clear']
weather_description : [b'sky is clear' b'overcast clouds' b'light rain' b'Sky is Clear'
 b'Sky is Clear']
date_time           : [b'2013-05-17 01:00:00' b'2013-04-11 08:00:00' b'2013-06-12 19:00:00'
 b'2013-08-26 23:00:00' b'2013-07-25 05:00:00']

label               : [ 475 3069 3342 1133 2903]

ذخیره سازی

تجزیه و تحلیل داده های csv سربار است. برای مدل های کوچک ، این می تواند گلوگاه آموزش باشد.

بسته به مورد استفاده شما ممکن است یک ایده خوب برای استفاده Dataset.cache یا data.experimental.snapshot به طوری که داده های CSV است تنها در عصر اول تجزیه شده است.

تفاوت اصلی بین روش های cache و snapshot این است که فایلهای cache فقط توسط فرآیند TensorFlow که آنها را ایجاد کرده است قابل استفاده هستند ، اما پرونده های snapshot را می توان با فرایندهای دیگر خواند.

به عنوان مثال ، تکرار بیش از 20 بار در traffic_volume_csv_gz_ds ، بدون پنهان سازی 15 ثانیه طول می کشد ، یا با حافظه پنهان 2 ~ ثانیه طول می کشد.

%%time
for i, (batch, label) in enumerate(traffic_volume_csv_gz_ds.repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
...............................................................................................
CPU times: user 16.8 s, sys: 4.11 s, total: 20.9 s
Wall time: 12.9 s
%%time
caching = traffic_volume_csv_gz_ds.cache().shuffle(1000)

for i, (batch, label) in enumerate(caching.shuffle(1000).repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
...............................................................................................
CPU times: user 1.55 s, sys: 198 ms, total: 1.75 s
Wall time: 1.37 s
%%time
snapshot = tf.data.experimental.snapshot('titanic.tfsnap')
snapshotting = traffic_volume_csv_gz_ds.apply(snapshot).shuffle(1000)

for i, (batch, label) in enumerate(snapshotting.shuffle(1000).repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
...............................................................................................
CPU times: user 2.31 s, sys: 396 ms, total: 2.7 s
Wall time: 1.64 s

اگر بارگیری داده های شما با بارگیری پرونده های csv کند می شود و cache و snapshot برای موارد استفاده شما کافی نیستند ، رمزگذاری مجدد داده های خود را در قالب ساده تر در نظر بگیرید.

چندین پرونده

تمام مثالهای موجود در این بخش را می توان به راحتی و بدون tf.data انجام tf.data . مکانی که tf.data می تواند کارها را ساده کند ، کار با مجموعه پرونده ها است.

به عنوان مثال ، مجموعه داده های تصاویر فونت نویسه به عنوان مجموعه ای از پرونده های csv توزیع می شود ، یکی در هر فونت.

قلم ها

تصویر ویلی هایدلباخ از Pixabay

مجموعه داده را بارگیری کنید و به فایلهای داخل آن نگاهی بیندازید:

fonts_zip = tf.keras.utils.get_file(
    'fonts.zip',  "https://archive.ics.uci.edu/ml/machine-learning-databases/00417/fonts.zip",
    cache_dir='.', cache_subdir='fonts',
    extract=True)
Downloading data from https://archive.ics.uci.edu/ml/machine-learning-databases/00417/fonts.zip
160317440/160313983 [==============================] - 8s 0us/step
import pathlib
font_csvs =  sorted(str(p) for p in pathlib.Path('fonts').glob("*.csv"))

font_csvs[:10]
['fonts/AGENCY.csv',
 'fonts/ARIAL.csv',
 'fonts/BAITI.csv',
 'fonts/BANKGOTHIC.csv',
 'fonts/BASKERVILLE.csv',
 'fonts/BAUHAUS.csv',
 'fonts/BELL.csv',
 'fonts/BERLIN.csv',
 'fonts/BERNARD.csv',
 'fonts/BITSTREAMVERA.csv']
len(font_csvs)
153

هنگام برخورد با دسته ای از فایل ها می توانید یک file_pattern به سبک glob را به تابع experimental.make_csv_dataset کنید. ترتیب پرونده ها هر تکرار اشتباه گرفته می شود.

با استفاده از آرگومان num_parallel_reads تعداد پرونده هایی را که به طور موازی خوانده می شوند و بهم می پیوندند تنظیم کنید.

fonts_ds = tf.data.experimental.make_csv_dataset(
    file_pattern = "fonts/*.csv",
    batch_size=10, num_epochs=1,
    num_parallel_reads=20,
    shuffle_buffer_size=10000)

این پرونده های csv تصاویر را به صورت یک ردیف مسطح می کند. نام ستون ها با r{row}c{column} . این اولین دسته است:

for features in fonts_ds.take(1):
  for i, (name, value) in enumerate(features.items()):
    if i>15:
      break
    print(f"{name:20s}: {value}")
print('...')
print(f"[total: {len(features)} features]")
font                : [b'CANDARA' b'SWIS721' b'BROADWAY' b'MONOTYPE' b'VIVALDI' b'SWIS721'
 b'MINGLIU' b'SNAP' b'BROADWAY' b'OCRA']
fontVariant         : [b'CANDARA' b'SWIS721 LTEX BT' b'BROADWAY' b'MONOTYPE CORSIVA' b'VIVALDI'
 b'SWIS721 LTEX BT' b'MINGLIU_HKSCS-EXTB' b'SNAP ITC' b'BROADWAY'
 b'scanned']
m_label             : [7901  172  163 1056  214  229  215   48  123   50]
strength            : [0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4]
italic              : [0 1 1 0 1 1 1 0 1 0]
orientation         : [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
m_top               : [37 56 35 42 25 31 42 40 35  0]
m_left              : [23 36 22 25 26 27 22 22 34  0]
originalH           : [48 16 51 40 56 54 35 49 54 32]
originalW           : [39 41 49 40 57 40 40 53 36 22]
h                   : [20 20 20 20 20 20 20 20 20 20]
w                   : [20 20 20 20 20 20 20 20 20 20]
r0c0                : [  1 131   1   1   1   1   1   1   1  24]
r0c1                : [  1 255   1   1   1   1   1   1   1 227]
r0c2                : [  1 255   1   1   1   1   1   1   1  96]
r0c3                : [142 255   1   1   1   1   1   1   1 154]
...
[total: 412 features]

اختیاری: زمینه های بسته بندی

احتمالاً نمی خواهید با هر پیکسل در ستون های جداگانه مانند این کار کنید. قبل از استفاده از این مجموعه داده ، حتما پیکسل ها را در یک سنسور تصویر قرار دهید.

در اینجا کدی وجود دارد که نام ستون را تجزیه می کند تا تصاویر را برای هر مثال ایجاد کند:

import re

def make_images(features):
  image = [None]*400
  new_feats = {}

  for name, value in features.items():
    match = re.match('r(\d+)c(\d+)', name)
    if match:
      image[int(match.group(1))*20+int(match.group(2))] = value
    else:
      new_feats[name] = value

  image = tf.stack(image, axis=0)
  image = tf.reshape(image, [20, 20, -1])
  new_feats['image'] = image

  return new_feats

این عملکرد را به هر دسته از مجموعه داده اعمال کنید:

fonts_image_ds = fonts_ds.map(make_images)

for features in fonts_image_ds.take(1):
  break

تصاویر حاصل را رسم کنید:

from matplotlib import pyplot as plt

plt.figure(figsize=(6,6), dpi=120)

for n in range(9):
  plt.subplot(3,3,n+1)
  plt.imshow(features['image'][..., n])
  plt.title(chr(features['m_label'][n]))
  plt.axis('off')
/home/kbuilder/.local/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py:240: RuntimeWarning: Glyph 3926 missing from current font.
  font.set_text(s, 0.0, flags=flags)
/home/kbuilder/.local/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py:203: RuntimeWarning: Glyph 3926 missing from current font.
  font.set_text(s, 0, flags=flags)

png

توابع سطح پایین

تاکنون این آموزش بر روی ابزارهای سطح بالا برای خواندن داده های CSV متمرکز شده است. اگر مورد استفاده شما متناسب با الگوهای اساسی نباشد ، دو API دیگر نیز وجود دارد که می تواند برای کاربران پیشرفته مفید باشد.

این بخش برای ارائه نحوه استفاده از این قابلیت سطح پایین ، عملکردهای ارائه شده توسط make_csv_dataset دوباره ایجاد می کند.

tf.io.decode_csv

این تابع یک رشته یا لیستی از رشته ها را به لیستی از ستون ها رمزگشایی می کند.

برخلاف make_csv_dataset این تابع سعی نمی کند انواع داده های ستون را حدس بزند. شما با تهیه لیستی از record_defaults که حاوی مقداری از نوع صحیح برای هر ستون است ، انواع ستون را مشخص می کنید.

برای خواندن داده های تایتانیک به عنوان رشته ای با استفاده از decode_csv می توانید بگویید:

text = pathlib.Path(titanic_file_path).read_text()
lines = text.split('\n')[1:-1]

all_strings = [str()]*10
all_strings
['', '', '', '', '', '', '', '', '', '']
features = tf.io.decode_csv(lines, record_defaults=all_strings) 

for f in features:
  print(f"type: {f.dtype.name}, shape: {f.shape}")
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)

برای تجزیه آنها با انواع واقعی آنها ، لیستی از record_defaults از انواع متناظر ایجاد کنید:

print(lines[0])
0,male,22.0,1,0,7.25,Third,unknown,Southampton,n
titanic_types = [int(), str(), float(), int(), int(), float(), str(), str(), str(), str()]
titanic_types
[0, '', 0.0, 0, 0, 0.0, '', '', '', '']
features = tf.io.decode_csv(lines, record_defaults=titanic_types) 

for f in features:
  print(f"type: {f.dtype.name}, shape: {f.shape}")
type: int32, shape: (627,)
type: string, shape: (627,)
type: float32, shape: (627,)
type: int32, shape: (627,)
type: int32, shape: (627,)
type: float32, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)
type: string, shape: (627,)

tf.data.experimental.CsvDataset

tf.data.experimental.CsvDataset کلاس فراهم می کند یک فایل CSV حداقل Dataset بدون ویژگی های راحتی از رابط make_csv_dataset ستون تجزیه هدر، ستون نوع استنباط، برروی آن بکشید خودکار، فایل Interleaving در: تابع.

این سازنده زیر استفاده record_defaults همان راه به عنوان io.parse_csv :

simple_titanic = tf.data.experimental.CsvDataset(titanic_file_path, record_defaults=titanic_types, header=True)

for example in simple_titanic.take(1):
  print([e.numpy() for e in example])
[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n']

کد فوق در اصل معادل:

def decode_titanic_line(line):
  return tf.io.decode_csv(line, titanic_types)

manual_titanic = (
    # Load the lines of text
    tf.data.TextLineDataset(titanic_file_path)
    # Skip the header row.
    .skip(1)
    # Decode the line.
    .map(decode_titanic_line)
)

for example in manual_titanic.take(1):
  print([e.numpy() for e in example])
[0, b'male', 22.0, 1, 0, 7.25, b'Third', b'unknown', b'Southampton', b'n']

چندین پرونده

برای تجزیه مجموعه داده های قلم ها با استفاده از experimental.CsvDataset ، ابتدا باید انواع ستون را برای record_defaults . با بررسی ردیف اول یک پرونده شروع کنید:

font_line = pathlib.Path(font_csvs[0]).read_text().splitlines()[1]
print(font_line)
AGENCY,AGENCY FB,64258,0.400000,0,0.000000,35,21,51,22,20,20,1,1,1,21,101,210,255,255,255,255,255,255,255,255,255,255,255,255,255,255,1,1,1,93,255,255,255,176,146,146,146,146,146,146,146,146,216,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,141,141,141,182,255,255,255,172,141,141,141,115,1,1,1,1,163,255,255,255,255,255,255,255,255,255,255,255,255,255,255,209,1,1,1,1,163,255,255,255,6,6,6,96,255,255,255,74,6,6,6,5,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255,1,1,1,93,255,255,255,70,1,1,1,1,1,1,1,1,163,255,255,255

فقط دو فیلد اول رشته ای هستند ، بقیه ints یا float هستند و با شمارش کاما می توانید تعداد کل ویژگی ها را بدست آورید:

num_font_features = font_line.count(',')+1
font_column_types = [str(), str()] + [float()]*(num_font_features-2)

سازنده CsvDatasaet می تواند لیستی از پرونده های ورودی را بگیرد ، اما آنها را به طور متوالی می خواند. اولین فایل در لیست CSVs است AGENCY.csv :

font_csvs[0]
'fonts/AGENCY.csv'

بنابراین هنگامی که لیست پرونده ها را به CsvDataaset ، سوابق AGENCY.csv ابتدا خوانده می شوند:

simple_font_ds = tf.data.experimental.CsvDataset(
    font_csvs, 
    record_defaults=font_column_types, 
    header=True)
for row in simple_font_ds.take(10):
  print(row[0].numpy())
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'
b'AGENCY'

برای Dataset.interleave چندین پرونده ، از Dataset.interleave استفاده کنید.

در اینجا یک مجموعه داده اولیه وجود دارد که شامل نام پرونده های csv است:

font_files = tf.data.Dataset.list_files("fonts/*.csv")

این نام فایل ها را هر دوره تغییر می دهد:

print('Epoch 1:')
for f in list(font_files)[:5]:
  print("    ", f.numpy())
print('    ...')
print()

print('Epoch 2:')
for f in list(font_files)[:5]:
  print("    ", f.numpy())
print('    ...')
Epoch 1:
     b'fonts/MAIANDRA.csv'
     b'fonts/MODERN.csv'
     b'fonts/VIN.csv'
     b'fonts/CONSTANTIA.csv'
     b'fonts/PROXY.csv'
    ...

Epoch 2:
     b'fonts/ROMAN.csv'
     b'fonts/TAHOMA.csv'
     b'fonts/BRITANNIC.csv'
     b'fonts/OCRA.csv'
     b'fonts/TW.csv'
    ...

interleave روش طول می کشد map_func است که ایجاد یک child- Dataset برای هر عنصر از والدین Dataset .

در اینجا ، می خواهید از هر عنصر مجموعه داده پرونده ها ، یک CsvDataset ایجاد کنید:

def make_font_csv_ds(path):
  return tf.data.experimental.CsvDataset(
    path, 
    record_defaults=font_column_types, 
    header=True)

Dataset برگشت Dataset شده توسط interleave با دوچرخه سواری بر روی تعدادی از کودکان عناصر را برمی گرداند - Dataset ها. در زیر توجه داشته باشید که چطور مجموعه داده بیش از cycle_length)=3 فایل سه قلم:

font_rows = font_files.interleave(make_font_csv_ds,
                                  cycle_length=3)
fonts_dict = {'font_name':[], 'character':[]}

for row in font_rows.take(10):
  fonts_dict['font_name'].append(row[0].numpy().decode())
  fonts_dict['character'].append(chr(row[2].numpy()))

pd.DataFrame(fonts_dict)

کارایی

پیش از این ، اشاره شده بود که io.decode_csv هنگام اجرای روی دسته ای از رشته ها کارآمدتر است.

برای استفاده در بهبود بارگذاری CSV ، می توان هنگام استفاده از اندازه های دسته های بزرگ ، از این واقعیت بهره برد (اما ابتدا حافظه پنهان را امتحان کنید).

با لودر داخلی 20 ، دسته های 2048 نمونه حدود 17 ثانیه طول می کشد.

BATCH_SIZE=2048
fonts_ds = tf.data.experimental.make_csv_dataset(
    file_pattern = "fonts/*.csv",
    batch_size=BATCH_SIZE, num_epochs=1,
    num_parallel_reads=100)
%%time
for i,batch in enumerate(fonts_ds.take(20)):
  print('.',end='')

print()
....................
CPU times: user 27.5 s, sys: 1.53 s, total: 29 s
Wall time: 11.4 s

انتقال تعداد خطوط نوشتاری برای decode_csv با سرعت بیشتری و در حدود 5 decode_csv اجرا می شود:

fonts_files = tf.data.Dataset.list_files("fonts/*.csv")
fonts_lines = fonts_files.interleave(
    lambda fname:tf.data.TextLineDataset(fname).skip(1), 
    cycle_length=100).batch(BATCH_SIZE)

fonts_fast = fonts_lines.map(lambda x: tf.io.decode_csv(x, record_defaults=font_column_types))
%%time
for i,batch in enumerate(fonts_fast.take(20)):
  print('.',end='')

print()
....................
CPU times: user 9.23 s, sys: 0 ns, total: 9.23 s
Wall time: 1.52 s

برای مثال دیگری از افزایش عملکرد csv با استفاده از دسته های بزرگ ، به آموزش overfit و underfit مراجعه کنید .

این نوع روش ممکن است cache ، اما گزینه های دیگری مانند cache و snapshot یا رمزگذاری مجدد داده های خود را به یک قالب ساده تر در نظر بگیرید.