Datasets documentation
Menggunakan Datasets dengan TensorFlow
Menggunakan Datasets dengan TensorFlow
Dokumen ini adalah pengantar singkat tentang penggunaan datasets dengan TensorFlow, dengan fokus khusus pada cara mendapatkan objek tf.Tensor dari dataset kami, dan cara mengalirkan data dari objek Dataset Hugging Face ke metode Keras
seperti model.fit().
Format dataset
Secara default, dataset mengembalikan objek Python biasa: bilangan bulat, bilangan desimal, string, daftar, dan sebagainya.
Untuk mendapatkan tensor TensorFlow, Anda dapat mengatur format dataset menjadi tf:
>>> from datasets import Dataset
>>> data = [[1, 2],[3, 4]]
>>> ds = Dataset.from_dict({"data": data})
>>> ds = ds.with_format("tf")
>>> ds[0]
{'data': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([1, 2])>}
>>> ds[:2]
{'data': <tf.Tensor: shape=(2, 2), dtype=int64, numpy=
array([[1, 2],
[3, 4]])>}Objek Dataset adalah pembungkus dari tabel Arrow, yang memungkinkan pembacaan cepat dari array dalam dataset ke tensor TensorFlow.
Hal ini dapat berguna untuk mengonversi dataset Anda menjadi dict dari objek Tensor, atau untuk menulis generator guna memuat sampel TF darinya. Jika Anda ingin mengonversi seluruh dataset menjadi Tensor, cukup kueri dataset penuh:
>>> ds[:]
{'data': <tf.Tensor: shape=(2, 2), dtype=int64, numpy=
array([[1, 2],
[3, 4]])>}Array N-dimensi
Jika dataset Anda terdiri dari array N-dimensi, Anda akan melihat bahwa secara default mereka dianggap sebagai tensor yang sama jika bentuknya tetap:
>>> from datasets import Dataset
>>> data = [[[1, 2],[3, 4]],[[5, 6],[7, 8]]] # fixed shape
>>> ds = Dataset.from_dict({"data": data})
>>> ds = ds.with_format("tf")
>>> ds[0]
{'data': <tf.Tensor: shape=(2, 2), dtype=int64, numpy=
array([[1, 2],
[3, 4]])>}Jika tidak, dataset berformat TensorFlow akan mengoutputkan RaggedTensor alih-alih satu tensor:
>>> from datasets import Dataset
>>> data = [[[1, 2],[3]],[[4, 5, 6],[7, 8]]] # varying shape
>>> ds = Dataset.from_dict({"data": data})
>>> ds = ds.with_format("torch")
>>> ds[0]
{'data': <tf.RaggedTensor [[1, 2], [3]]>}Namun logika ini sering kali memerlukan perbandingan bentuk (shape) dan penyalinan data yang lambat.
Untuk menghindarinya, Anda harus secara eksplisit menggunakan tipe fitur Array dan menentukan bentuk tensor Anda:
>>> from datasets import Dataset, Features, Array2D
>>> data = [[[1, 2],[3, 4]],[[5, 6],[7, 8]]]
>>> features = Features({"data": Array2D(shape=(2, 2), dtype='int32')})
>>> ds = Dataset.from_dict({"data": data}, features=features)
>>> ds = ds.with_format("tf")
>>> ds[0]
{'data': <tf.Tensor: shape=(2, 2), dtype=int64, numpy=
array([[1, 2],
[3, 4]])>}
>>> ds[:2]
{'data': <tf.Tensor: shape=(2, 2, 2), dtype=int64, numpy=
array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])>}Jenis fitur lainnya
Data ClassLabel dikonversi dengan benar menjadi tensor:
>>> from datasets import Dataset, Features, ClassLabel
>>> labels = [0, 0, 1]
>>> features = Features({"label": ClassLabel(names=["negative", "positive"])})
>>> ds = Dataset.from_dict({"label": labels}, features=features)
>>> ds = ds.with_format("tf")
>>> ds[:3]
{'label': <tf.Tensor: shape=(3,), dtype=int64, numpy=array([0, 0, 1])>}String dan objek biner juga didukung:
>>> from datasets import Dataset, Features
>>> text = ["foo", "bar"]
>>> data = [0, 1]
>>> ds = Dataset.from_dict({"text": text, "data": data})
>>> ds = ds.with_format("tf")
>>> ds[:2]
{'text': <tf.Tensor: shape=(2,), dtype=string, numpy=array([b'foo', b'bar'], dtype=object)>,
'data': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([0, 1])>}Anda juga dapat secara eksplisit memformat kolom tertentu dan membiarkan kolom lainnya tidak diformat:
>>> ds = ds.with_format("tf", columns=["data"], output_all_columns=True)
>>> ds[:2]
{'data': <tf.Tensor: shape=(2,), dtype=int64, numpy=array([0, 1])>,
'text': ['foo', 'bar']}Objek string dan biner tidak berubah, karena PyTorch hanya mendukung angka.
Jenis fitur Image dan Audio juga didukung.
Untuk menggunakan tipe fitur Image, Anda perlu menginstal ekstra
visionsebagaipip install datasets[vision].
>>> from datasets import Dataset, Features, Audio, Image
>>> images = ["path/to/image.png"] * 10
>>> features = Features({"image": Image()})
>>> ds = Dataset.from_dict({"image": images}, features=features)
>>> ds = ds.with_format("tf")
>>> ds[0]
{'image': <tf.Tensor: shape=(512, 512, 4), dtype=uint8, numpy=
array([[[255, 215, 106, 255],
[255, 215, 106, 255],
...,
[255, 255, 255, 255],
[255, 255, 255, 255]]], dtype=uint8)>}
>>> ds[:2]
{'image': <tf.Tensor: shape=(2, 512, 512, 4), dtype=uint8, numpy=
array([[[[255, 215, 106, 255],
[255, 215, 106, 255],
...,
[255, 255, 255, 255],
[255, 255, 255, 255]]]], dtype=uint8)>}Untuk menggunakan tipe fitur Audio, Anda perlu menginstal ekstra
audiosebagaipip install datasets[audio].
>>> from datasets import Dataset, Features, Audio, Image
>>> audio = ["path/to/audio.wav"] * 10
>>> features = Features({"audio": Audio()})
>>> ds = Dataset.from_dict({"audio": audio}, features=features)
>>> ds = ds.with_format("tf")
>>> ds[0]["audio"]["array"]
<tf.Tensor: shape=(202311,), dtype=float32, numpy=
array([ 6.1035156e-05, 1.5258789e-05, 1.6784668e-04, ...,
-1.5258789e-05, -1.5258789e-05, 1.5258789e-05], dtype=float32)>
>>> ds[0]["audio"]["sampling_rate"]
<tf.Tensor: shape=(), dtype=int32, numpy=44100>Memuat data
Meskipun Anda dapat memuat sampel dan batch individual hanya dengan mengindeks dataset Anda, hal ini tidak akan berfungsi jika Anda ingin menggunakan metode Keras seperti fit() dan predict(). Anda bisa menulis fungsi generator yang mengacak dan memuat batch dari dataset Anda lalu fit() pada generator tersebut, tetapi itu terdengar seperti banyak pekerjaan yang tidak perlu. Sebagai gantinya, jika Anda ingin mengalirkan data dari dataset Anda secara langsung, kami merekomendasikan untuk mengonversi dataset Anda menjadi tf.data.Dataset menggunakan metode to_tf_dataset().
The tf.data.Dataset class covers a wide range of use-cases - it is often created from Tensors in memory, or using a load function to read files on disc
or external storage. The dataset can be transformed arbitrarily with the map() method, or methods like batch() and shuffle() can be used to create a dataset that’s ready for training. These methods do not modify the stored data
in any way - instead, the methods build a data pipeline graph that will be executed when the dataset is iterated over,
usually during model training or inference. This is different from the map() method of Hugging Face Dataset objects,
which runs the map function immediately and saves the new or changed columns.
Karena seluruh pipeline pra-pemrosesan data dapat dikompilasi dalam tf.data.Dataset, pendekatan ini memungkinkan pemuatan data dan pelatihan yang paralel secara masif serta asinkron. Namun, persyaratan kompilasi graf dapat menjadi keterbatasan, khususnya untuk tokenizer Hugging Face, yang biasanya belum (belum!) dapat dikompilasi sebagai bagian dari graf TF. Akibatnya, kami biasanya menyarankan untuk memproses dataset terlebih dahulu sebagai dataset Hugging Face, di mana fungsi Python apa pun dapat digunakan, dan kemudian mengonversinya menjadi tf.data.Dataset setelahnya menggunakan to_tf_dataset() untuk mendapatkan dataset yang sudah di-batch dan siap untuk pelatihan. Untuk melihat contoh pendekatan ini, silakan lihat contoh atau notebook untuk transformers.
Menggunakan to_tf_dataset()
Menggunakan to_tf_dataset() sangat mudah. Setelah dataset Anda dipreprocess dan siap, cukup panggil seperti ini:
>>> from datasets import Dataset
>>> data = {"inputs": [[1, 2],[3, 4]], "labels": [0, 1]}
>>> ds = Dataset.from_dict(data)
>>> tf_ds = ds.to_tf_dataset(
columns=["inputs"],
label_cols=["labels"],
batch_size=2,
shuffle=True
)Objek tf_ds yang dikembalikan di sini kini sepenuhnya siap untuk dilatih, dan dapat langsung diteruskan ke model.fit(). Perhatikan bahwa Anda mengatur ukuran batch saat membuat dataset, sehingga Anda tidak perlu menentukannya saat memanggil fit():
>>> model.fit(tf_ds, epochs=2)Untuk deskripsi lengkap argumen, silakan lihat dokumentasi to_tf_dataset(). Dalam banyak kasus,
Anda juga perlu menambahkan collate_fn ke pemanggilan Anda. Ini adalah fungsi yang mengambil beberapa elemen dari dataset
dan menggabungkannya menjadi satu batch. Ketika semua elemen memiliki panjang yang sama, collator bawaan default akan
cukup, tetapi untuk tugas yang lebih kompleks, collator kustom mungkin diperlukan. Secara khusus, banyak tugas memiliki sampel
dengan panjang sekuens yang bervariasi, yang akan memerlukan data collator yang dapat melakukan padding batch dengan benar. Anda dapat melihat contoh
dari ini di transformers NLP examples dan notebooks, di mana panjang sekuens yang bervariasi sangat umum.
Jika Anda menemukan bahwa pemuatan dengan to_tf_dataset lambat, Anda juga dapat menggunakan argumen num_workers. Argumen ini menjalankan beberapa proses anak untuk memuat data secara paralel. Fitur ini baru dan masih agak eksperimental - silakan laporkan masalah jika Anda menemukan bug saat menggunakannya!
Kapan menggunakan to_tf_dataset
Pembaca yang cermat mungkin telah menyadari pada titik ini bahwa kami telah menawarkan dua pendekatan untuk mencapai tujuan yang sama - jika Anda ingin meneruskan dataset Anda ke model TensorFlow, Anda dapat mengonversi dataset menjadi Tensor atau dict dari Tensors menggunakan .with_format('tf'), atau Anda dapat mengonversi dataset menjadi tf.data.Dataset dengan to_tf_dataset(). Keduanya dapat diteruskan ke model.fit(), jadi mana yang harus Anda pilih?
Hal penting yang perlu dipahami adalah bahwa ketika Anda mengonversi seluruh dataset menjadi Tensor, data tersebut bersifat statis dan sepenuhnya dimuat ke dalam RAM. Pendekatan ini sederhana dan praktis, tetapi jika salah satu kondisi berikut berlaku, sebaiknya gunakan to_tf_dataset() sebagai gantinya:
- Dataset Anda terlalu besar untuk muat di RAM.
to_tf_dataset()hanya mengalirkan satu batch pada satu waktu, sehingga bahkan dataset yang sangat besar pun dapat ditangani dengan metode ini. - Anda ingin menerapkan transformasi acak menggunakan
dataset.with_transform()ataucollate_fn. Hal ini umum terjadi pada beberapa modalitas, seperti augmentasi gambar saat melatih model visi, atau masking acak saat melatih masked language models. Menggunakanto_tf_dataset()akan menerapkan transformasi tersebut pada saat batch dimuat, yang berarti sampel yang sama akan mendapatkan augmentasi yang berbeda setiap kali dimuat. Ini biasanya yang Anda inginkan. - Data Anda memiliki dimensi yang bervariasi, seperti teks input dalam NLP yang terdiri dari jumlah token yang berbeda-beda. Saat Anda membuat batch dengan sampel yang memiliki dimensi bervariasi, solusi standar adalah mengisi sampel yang lebih pendek hingga panjang sampel terpanjang. Saat Anda mengalirkan sampel dari dataset dengan
to_tf_dataset, Anda dapat menerapkan padding ini ke setiap batch melaluicollate_fnAnda. Namun, jika Anda ingin mengonversi dataset seperti itu menjadiTensorpadat, Anda harus mengisi sampel hingga panjang sampel terpanjang di seluruh dataset! Hal ini dapat menghasilkan jumlah padding yang sangat besar, yang membuang-buang memori dan mengurangi kecepatan model Anda.
Catatan dan batasan
Saat ini, to_tf_dataset() selalu mengembalikan dataset yang sudah di-batch - kami akan segera menambahkan dukungan untuk dataset yang tidak di-batch!