Ngày Cộng đồng ML là ngày 9 tháng 11! Tham gia với chúng tôi để cập nhật từ TensorFlow, JAX, và nhiều hơn nữa Tìm hiểu thêm

Tải dữ liệu CSV

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHubTải xuống sổ ghi chép

Hướng dẫn này cung cấp các ví dụ về cách sử dụng dữ liệu CSV với TensorFlow.

Có hai phần chính cho điều này:

  1. Đang tải dữ liệu ra đĩa
  2. Sơ chế nó thành một dạng phù hợp để đào tạo.

Hướng dẫn này tập trung vào việc tải và đưa ra một số ví dụ nhanh về tiền xử lý. Để xem hướng dẫn tập trung vào các khía cạnh tiền xử lý xem các hướng dẫn lớp tiền xử lýhướng dẫn .

Cài đặt

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

Trong dữ liệu bộ nhớ

Đối với bất kỳ tập dữ liệu CSV nhỏ nào, cách đơn giản nhất để đào tạo mô hình TensorFlow trên đó là tải nó vào bộ nhớ dưới dạng Khung dữ liệu gấu trúc hoặc mảng NumPy.

Một ví dụ tương đối đơn giản là tập dữ liệu bào ngư .

  • Tập dữ liệu nhỏ.
  • Tất cả các tính năng đầu vào đều là giá trị dấu phẩy động trong phạm vi giới hạn.

Dưới đây là làm thế nào để tải dữ liệu vào một 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()

Bộ dữ liệu chứa một tập hợp các phép đo của bào ngư , một loại ốc biển.

vỏ bào ngư

“Abalone vỏ” (bởi Nicki Dugan Pogue , CC BY-SA 2.0)

Nhiệm vụ danh nghĩa cho tập dữ liệu này là dự đoán tuổi từ các phép đo khác, vì vậy hãy tách các tính năng và nhãn để đào tạo:

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

Đối với tập dữ liệu này, bạn sẽ xử lý tất cả các tính năng giống nhau. Đóng gói các tính năng vào một mảng NumPy duy nhất:

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

Tiếp theo hãy lập mô hình hồi quy dự đoán tuổi. Vì chỉ có một tensor đầu vào duy nhất, một keras.Sequential mô hình là đủ đây.

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

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

Đào tạo mô hình đó, thông qua các tính năng và nhãn để Model.fit :

abalone_model.fit(abalone_features, abalone_labels, epochs=10)
Epoch 1/10
104/104 [==============================] - 1s 2ms/step - loss: 68.1297
Epoch 2/10
104/104 [==============================] - 0s 2ms/step - loss: 13.3981
Epoch 3/10
104/104 [==============================] - 0s 1ms/step - loss: 8.9458
Epoch 4/10
104/104 [==============================] - 0s 1ms/step - loss: 8.3894
Epoch 5/10
104/104 [==============================] - 0s 1ms/step - loss: 7.8835
Epoch 6/10
104/104 [==============================] - 0s 1ms/step - loss: 7.4897
Epoch 7/10
104/104 [==============================] - 0s 1ms/step - loss: 7.1716
Epoch 8/10
104/104 [==============================] - 0s 1ms/step - loss: 6.9468
Epoch 9/10
104/104 [==============================] - 0s 1ms/step - loss: 6.7714
Epoch 10/10
104/104 [==============================] - 0s 1ms/step - loss: 6.6458
<tensorflow.python.keras.callbacks.History at 0x7f7bf0178110>

Bạn vừa xem cách cơ bản nhất để đào tạo một mô hình sử dụng dữ liệu CSV. Tiếp theo, bạn sẽ học cách áp dụng tiền xử lý để chuẩn hóa các cột số.

Tiền xử lý cơ bản

Thực hành tốt để chuẩn hóa các đầu vào cho mô hình của bạn. Các experimental.preprocessing lớp cung cấp một cách thuận tiện để xây dựng bình thường này vào mô hình của bạn.

Lớp sẽ tính toán trước giá trị trung bình và phương sai của mỗi cột và sử dụng chúng để chuẩn hóa dữ liệu.

Đầu tiên, bạn tạo lớp:

normalize = preprocessing.Normalization()

Sau đó, bạn sử dụng Normalization.adapt() phương pháp để thích ứng với các lớp bình thường để dữ liệu của bạn.

normalize.adapt(abalone_features)

Sau đó, sử dụng lớp chuẩn hóa trong mô hình của bạn:

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: 91.9882
Epoch 2/10
104/104 [==============================] - 0s 2ms/step - loss: 52.3517
Epoch 3/10
104/104 [==============================] - 0s 1ms/step - loss: 16.0901
Epoch 4/10
104/104 [==============================] - 0s 1ms/step - loss: 5.8372
Epoch 5/10
104/104 [==============================] - 0s 1ms/step - loss: 5.0929
Epoch 6/10
104/104 [==============================] - 0s 2ms/step - loss: 5.0442
Epoch 7/10
104/104 [==============================] - 0s 1ms/step - loss: 5.0062
Epoch 8/10
104/104 [==============================] - 0s 1ms/step - loss: 4.9882
Epoch 9/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9629
Epoch 10/10
104/104 [==============================] - 0s 2ms/step - loss: 4.9666
<tensorflow.python.keras.callbacks.History at 0x7f7be008f910>

Các kiểu dữ liệu hỗn hợp

Bộ dữ liệu "Titanic" chứa thông tin về các hành khách trên tàu Titanic. Nhiệm vụ danh nghĩa trên tập dữ liệu này là dự đoán ai sống sót.

Tàu Titanic

Hình ảnh từ Wikimedia

Các dữ liệu thô có thể dễ dàng được nạp như một Pandas DataFrame , nhưng không phải là ngay lập tức có thể sử dụng như là đầu vào cho một mô hình TensorFlow.

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

Bởi vì các loại dữ liệu khác nhau và phạm vi bạn không thể chỉ đơn giản là ngăn xếp các tính năng vào mảng NumPy và vượt qua nó để một keras.Sequential mô hình. Mỗi cột cần được xử lý riêng lẻ.

Là một tùy chọn, bạn có thể xử lý trước dữ liệu của mình ngoại tuyến (sử dụng bất kỳ công cụ nào bạn thích) để chuyển đổi các cột phân loại thành cột số, sau đó chuyển đầu ra đã xử lý sang mô hình TensorFlow của bạn. Điểm bất lợi của cách tiếp cận đó là nếu bạn lưu và xuất mô hình của mình, quá trình xử lý trước sẽ không được lưu cùng với nó. Các experimental.preprocessing lớp tránh vấn đề này bởi vì chúng là một phần của mô hình.

Trong ví dụ này, bạn sẽ xây dựng một mô hình cụ logic tiền xử lý sử dụng Keras API chức năng . Bạn cũng có thể làm điều đó bởi subclassing .

API chức năng hoạt động trên các tenxơ "tượng trưng". Các tensors "háo hức" bình thường có một giá trị. Ngược lại, những tenxơ "tượng trưng" này thì không. Thay vào đó, họ theo dõi các hoạt động nào được chạy trên chúng và xây dựng biểu diễn của phép tính mà bạn có thể chạy sau này. Đây là một ví dụ nhanh:

# 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

Để xây dựng mô hình tiền xử lý, bắt đầu bằng việc xây dựng một tập hợp các biểu tượng keras.Input đối tượng, phù hợp với tên và dữ liệu dạng hoá các cột 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')>}

Bước đầu tiên trong logic tiền xử lý của bạn là nối các đầu vào số với nhau và chạy chúng qua một lớp chuẩn hóa:

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

Thu thập tất cả các kết quả tiền xử lý tượng trưng, ​​để nối chúng sau này.

preprocessed_inputs = [all_numeric_inputs]

Đối với chuỗi đầu vào sử dụng preprocessing.StringLookup chức năng để lập bản đồ từ chuỗi để chỉ số nguyên trong một từ vựng. Tiếp theo, sử dụng preprocessing.CategoryEncoding để chuyển đổi các chỉ số thành float32 thích hợp dữ liệu cho mô hình.

Các thiết lập mặc định cho preprocessing.CategoryEncoding lớp tạo một nóng vector cho mỗi đầu vào. Một layers.Embedding cũng sẽ làm việc. Xem hướng dẫn lớp tiền xử lýhướng dẫn để biết thêm về chủ đề này.

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.

Với bộ sưu tập của inputsprocessed_inputs , bạn có thể nối tất cả đầu vào xử lý trước với nhau, và xây dựng một mô hình xử lý các tiền xử lý:

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

Đây model chỉ chứa tiền xử lý đầu vào. Bạn có thể chạy nó để xem nó ảnh hưởng gì đến dữ liệu của bạn. Mô hình Keras không tự động chuyển đổi Pandas DataFrames vì nó không phải là rõ ràng nếu nó phải được chuyển đổi sang một tensor hoặc một cuốn từ điển của tensors. Vì vậy, hãy chuyển nó thành một từ điển của tenxơ:

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

Cắt bỏ ví dụ đào tạo đầu tiên và chuyển nó vào mô hình tiền xử lý này, bạn sẽ thấy các tính năng số và chuỗi một-hots tất cả được nối với nhau:

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

Bây giờ xây dựng mô hình trên đầu trang này:

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)

Khi bạn đào tạo các mô hình, vượt qua các từ điển của các tính năng như x , và các nhãn như y .

titanic_model.fit(x=titanic_features_dict, y=titanic_labels, epochs=10)
Epoch 1/10
20/20 [==============================] - 1s 3ms/step - loss: 0.5665
Epoch 2/10
20/20 [==============================] - 0s 3ms/step - loss: 0.4980
Epoch 3/10
20/20 [==============================] - 0s 3ms/step - loss: 0.4643
Epoch 4/10
20/20 [==============================] - 0s 3ms/step - loss: 0.4463
Epoch 5/10
20/20 [==============================] - 0s 3ms/step - loss: 0.4333
Epoch 6/10
20/20 [==============================] - 0s 3ms/step - loss: 0.4297
Epoch 7/10
20/20 [==============================] - 0s 3ms/step - loss: 0.4252
Epoch 8/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4234
Epoch 9/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4213
Epoch 10/10
20/20 [==============================] - 0s 4ms/step - loss: 0.4202
<tensorflow.python.keras.callbacks.History at 0x7f7c8ff43510>

Vì tiền xử lý là một phần của mô hình, bạn có thể lưu mô hình và tải lại ở một nơi khác và nhận được kết quả giống hệt nhau:

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.843]], shape=(1, 1), dtype=float32)
tf.Tensor([[-1.843]], shape=(1, 1), dtype=float32)

Sử dụng tf.data

Trong phần trước, bạn đã dựa vào việc trộn và trộn dữ liệu có sẵn của mô hình trong khi đào tạo mô hình.

Nếu bạn cần kiểm soát nhiều hơn các đường ống dữ liệu đầu vào hoặc nhu cầu sử dụng dữ liệu mà không dễ dàng phù hợp với bộ nhớ: sử dụng tf.data .

Để biết thêm ví dụ thấy hướng dẫn tf.data .

Bật trong dữ liệu bộ nhớ

Như một ví dụ đầu tiên của việc áp dụng tf.data dữ liệu CSV xem xét đoạn mã sau để lát bằng tay lên các từ điển của các tính năng từ phần trước. Đối với mỗi chỉ mục, nó sẽ lấy chỉ mục đó cho từng tính năng:

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

Chạy cái này và in ví dụ đầu tiên:

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

Cơ bản nhất tf.data.Dataset trong bộ nhớ dữ liệu nạp là Dataset.from_tensor_slices constructor. Lợi nhuận này một tf.data.Dataset mà thực hiện một phiên bản khái quát hóa những điều trên slices chức năng, trong TensorFlow.

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

Bạn có thể lặp lại trên một tf.data.Dataset giống như bất kỳ python khác iterable:

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'

Các from_tensor_slices chức năng có thể xử lý bất kỳ cấu trúc của từ điển lồng nhau hoặc các bộ. Các mã sau đây làm cho một tập dữ liệu của (features_dict, labels) cặp:

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

Để đào tạo một mô hình sử dụng này Dataset , bạn sẽ cần phải ít nhất shufflebatch các dữ liệu.

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

Thay vì đi qua featureslabels để Model.fit , bạn vượt qua bộ dữ liệu:

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

Từ một tệp duy nhất

Cho đến nay, hướng dẫn này đã hoạt động với dữ liệu trong bộ nhớ. tf.data là một bộ công cụ đánh giá cao khả năng mở rộng cho việc xây dựng đường ống dẫn dữ liệu, và cung cấp một vài chức năng để xử lý các file tải 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

Bây giờ đọc dữ liệu CSV từ các tập tin và tạo ra một tf.data.Dataset .

(Đối với các tài liệu hướng dẫn đầy đủ, xem 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,)

Chức năng này bao gồm nhiều tính năng tiện lợi nên dữ liệu rất dễ làm việc. Điêu nay bao gôm:

  • Sử dụng tiêu đề cột làm khóa từ điển.
  • Tự động xác định loại của mỗi cột.
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'female' b'male' b'male' b'male']
age                 : [28. 28. 70.  1. 28.]
n_siblings_spouses  : [1 0 1 5 1]
parch               : [0 0 1 2 0]
fare                : [82.171  7.225 71.    46.9   15.85 ]
class               : [b'First' b'Third' b'First' b'Third' b'Third']
deck                : [b'unknown' b'unknown' b'B' b'unknown' b'unknown']
embark_town         : [b'Cherbourg' b'Cherbourg' b'Southampton' b'Southampton' b'Southampton']
alone               : [b'n' b'y' b'n' b'n' b'n']

label               : [0 1 0 0 0]

Nó cũng có thể giải nén dữ liệu một cách nhanh chóng. Đây là một tập tin CSV đã giải nén có chứa các dữ liệu giao thông giữa các bang metro

Ùn tắc giao thông.

Hình ảnh từ Wikimedia

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

Đặt compression_type lập luận để đọc trực tiếp từ các tập tin nén:

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                : [275.36 264.13 265.53 278.63 289.91]
rain_1h             : [0.   0.   0.   0.   1.52]
snow_1h             : [0. 0. 0. 0. 0.]
clouds_all          : [90 90 75 90 80]
weather_main        : [b'Rain' b'Clouds' b'Clouds' b'Rain' b'Mist']
weather_description : [b'light rain' b'overcast clouds' b'broken clouds' b'light rain' b'mist']
date_time           : [b'2013-03-10 19:00:00' b'2013-01-02 19:00:00' b'2012-12-06 06:00:00'
 b'2013-04-25 18:00:00' b'2013-07-31 04:00:00']

label               : [2743 2687 5545 5020  822]

Bộ nhớ đệm

Có một số chi phí để phân tích cú pháp dữ liệu csv. Đối với những người mẫu nhỏ đây có thể là điểm nghẽn trong đào tạo.

Tùy thuộc vào trường hợp sử dụng của bạn có thể là một ý tưởng tốt để sử dụng Dataset.cache hoặc data.experimental.snapshot để các dữ liệu csv chỉ phân tích trên kỷ nguyên đầu tiên.

Sự khác biệt chính giữa cachesnapshot các phương pháp là cache file chỉ có thể được sử dụng bởi quá trình TensorFlow đã tạo ra chúng, nhưng snapshot tập tin có thể được đọc bởi các quá trình khác.

Ví dụ, lặp lại trong traffic_volume_csv_gz_ds 20 lần, mất ~ 15 giây mà không có bộ nhớ đệm, hoặc ~ 2s với bộ nhớ đệm.

%%time
for i, (batch, label) in enumerate(traffic_volume_csv_gz_ds.repeat(20)):
  if i % 40 == 0:
    print('.', end='')
print()
...............................................................................................
CPU times: user 14.9 s, sys: 3.58 s, total: 18.5 s
Wall time: 11 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.42 s, sys: 115 ms, total: 1.53 s
Wall time: 1.22 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.26 s, sys: 431 ms, total: 2.69 s
Wall time: 1.62 s

Nếu tải dữ liệu của bạn bị chậm bởi các tập tin tải csv, và cachesnapshot không đủ đối với trường hợp sử dụng của bạn, hãy xem xét tái mã hóa dữ liệu của bạn sang một định dạng sắp xếp hợp lý hơn.

Nhiều tệp

Tất cả các ví dụ cho đến nay trong phần này có thể dễ dàng được thực hiện mà không tf.data . Một nơi tf.data thực sự có thể đơn giản hóa mọi thứ là khi giao dịch với các bộ sưu tập các tập tin.

Ví dụ, hình ảnh chữ kí tự dữ liệu được phân phối như một bộ sưu tập các tập tin csv, mỗi phông chữ.

Phông chữ

Hình ảnh bằng cách Willi Heidelbach từ Pixabay

Tải xuống tập dữ liệu và xem các tệp bên trong:

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

Khi giao dịch với một loạt các tập tin mà bạn có thể vượt qua một glob kiểu file_pattern đến experimental.make_csv_dataset chức năng. Thứ tự của các tệp được xáo trộn mỗi lần lặp lại.

Sử dụng các num_parallel_reads lập luận để thiết lập có bao nhiêu tập tin được đọc song song và xen kẽ với nhau.

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)

Các tệp csv này có các hình ảnh được làm phẳng thành một hàng. Các tên cột được định dạng r{row}c{column} . Đây là đợt đầu tiên:

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'GLOUCESTER' b'REFERENCE' b'TREBUCHET' b'MONEY' b'GLOUCESTER' b'MONEY'
 b'GLOUCESTER' b'JUICE' b'CAMBRIA' b'BRUSH']
fontVariant         : [b'GLOUCESTER MT EXTRA CONDENSED' b'MS REFERENCE SANS SERIF'
 b'TREBUCHET MS' b'scanned' b'GLOUCESTER MT EXTRA CONDENSED' b'scanned'
 b'GLOUCESTER MT EXTRA CONDENSED' b'JUICE ITC' b'CAMBRIA'
 b'BRUSH SCRIPT MT']
m_label             : [  116 63521   507    53   402    54  8747   213 10766  8776]
strength            : [0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4 0.4]
italic              : [1 0 0 0 0 0 0 1 0 1]
orientation         : [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
m_top               : [41 21 23  0 31  0 22 20 25 44]
m_left              : [25 26 23  0 15  0 20 27 23 24]
originalH           : [42 68 64 32 63 27 68 61 73 25]
originalW           : [18 30 30 19 22 16 18 33 32 36]
h                   : [20 20 20 20 20 20 20 20 20 20]
w                   : [20 20 20 20 20 20 20 20 20 20]
r0c0                : [1 1 1 1 1 1 1 1 1 1]
r0c1                : [ 1  1  1 91  1  1  1  1  1  1]
r0c2                : [  1   1   1 239   1   1   1   1   1  40]
r0c3                : [  1   1   1 255   1   1   1   1   1  74]
...
[total: 412 features]

Tùy chọn: Các trường đóng gói

Bạn có thể không muốn làm việc với từng pixel trong các cột riêng biệt như thế này. Trước khi cố gắng sử dụng tập dữ liệu này, hãy đảm bảo đóng gói các pixel thành một bộ căng hình ảnh.

Đây là mã phân tích cú pháp tên cột để tạo hình ảnh cho từng ví dụ:

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

Áp dụng chức năng đó cho từng lô trong tập dữ liệu:

fonts_image_ds = fonts_ds.map(make_images)

for features in fonts_image_ds.take(1):
  break

Vẽ các hình ảnh kết quả:

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

png

Các chức năng cấp thấp hơn

Cho đến nay, hướng dẫn này đã tập trung vào các tiện ích cấp cao nhất để đọc dữ liệu csv. Có hai API khác có thể hữu ích cho người dùng nâng cao nếu trường hợp sử dụng của bạn không phù hợp với các mẫu cơ bản.

Đây chức năng phần tái tạo được cung cấp bởi make_csv_dataset , để chứng minh như thế nào chức năng cấp thấp hơn này có thể được sử dụng.

tf.io.decode_csv

Hàm này giải mã một chuỗi hoặc danh sách các chuỗi thành một danh sách các cột.

Không giống như make_csv_dataset chức năng này không cố gắng đoán cột dữ liệu loại. Bạn chỉ rõ loại cột bằng cách cung cấp một danh sách các record_defaults chứa một giá trị đúng loại, cho mỗi cột.

Để đọc dữ liệu Titanic như dây đàn sử dụng decode_csv bạn sẽ nói:

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

Để phân tích chúng với các loại thực tế của họ, tạo ra một danh sách các record_defaults các loại tương ứng:

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

Các tf.data.experimental.CsvDataset lớp cung cấp một CSV tối thiểu Dataset giao diện mà không cần các tính năng tiện lợi của make_csv_dataset chức năng: Tiêu đề cột phân tích, cột kiểu suy luận, xáo trộn tự động, tập tin đan xen.

Constructor này sau sử dụng record_defaults theo cùng một cách như 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']

Đoạn mã trên về cơ bản tương đương với:

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

Nhiều tệp

Để phân tích các phông chữ tập dữ liệu sử dụng experimental.CsvDataset , trước tiên bạn cần phải xác định các loại cột cho record_defaults . Bắt đầu bằng cách kiểm tra hàng đầu tiên của một tệp:

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

Chỉ hai trường đầu tiên là chuỗi, phần còn lại là int hoặc float và bạn có thể nhận tổng số đối tượng bằng cách đếm dấu phẩy:

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

Các CsvDatasaet constructor có thể mất một danh sách các tập tin đầu vào, nhưng đọc chúng liên tục. Các tập tin đầu tiên trong danh sách các CSV là AGENCY.csv :

font_csvs[0]
'fonts/AGENCY.csv'

Vì vậy, khi bạn vượt qua vượt qua danh sách các tập tin để CsvDataaset các hồ sơ từ AGENCY.csv được đọc đầu tiên:

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'

Để đan xen nhiều file, sử dụng Dataset.interleave .

Đây là tập dữ liệu ban đầu chứa tên tệp csv:

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

Thao tác này xáo trộn các tên tệp từng kỷ nguyên:

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/BROADWAY.csv'
     b'fonts/COPPERPLATE.csv'
     b'fonts/STENCIL.csv'
     b'fonts/COOPER.csv'
     b'fonts/GABRIOLA.csv'
    ...

Epoch 2:
     b'fonts/MONOSPAC821.csv'
     b'fonts/ONYX.csv'
     b'fonts/HARLOW.csv'
     b'fonts/TIMES.csv'
     b'fonts/JOKERMAN.csv'
    ...

Các interleave phương pháp mất một map_func tạo ra một từ trẻ Dataset cho mỗi phần tử của huynh Dataset .

Ở đây, bạn muốn tạo một CsvDataset từ mỗi phần tử của tập dữ liệu của tập tin:

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

Các Dataset được trả về bởi các yếu tố lợi nhuận xen kẽ bằng đi xe đạp trên một số các từ trẻ Dataset s. Lưu ý, dưới đây, làm thế nào các chu kỳ bộ dữ liệu trên cycle_length)=3 ba file font:

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)

Màn biểu diễn

Trước đó, nó đã được ghi nhận rằng io.decode_csv là hiệu quả hơn khi chạy trên một loạt các chuỗi.

Có thể tận dụng lợi thế của thực tế này, khi sử dụng quy mô lô lớn, để cải thiện hiệu suất tải CSV (nhưng thử bộ nhớ đệm đầu tiên).

Với bộ nạp 20 tích hợp, các lô ví dụ 2048 mất khoảng 17 giây.

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 26.8 s, sys: 1.75 s, total: 28.6 s
Wall time: 11.1 s

Đi qua đợt dòng văn bản để decode_csv chạy nhanh hơn, trong khoảng 5s:

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.29 s, sys: 0 ns, total: 9.29 s
Wall time: 1.48 s

Đối với một ví dụ khác của việc tăng hiệu suất csv bằng cách sử dụng lô lớn thấy overfit và hướng dẫn underfit .

Điều này loại phương pháp có thể làm việc, nhưng xem xét các lựa chọn khác như cachesnapshot , hoặc tái enncoding dữ liệu của bạn sang một định dạng sắp xếp hợp lý hơn.