1. Omówienie
TPU są bardzo szybkie. Strumień danych treningowych musi na bieżąco odpowiadać szybkości trenowania. W tym module nauczysz się wczytywać dane z GCS za pomocą interfejsu tf.data.Dataset API, aby podawać je do TPU.
Ten moduł jest częścią 1 z serii „Keras na TPU”. Możesz je wykonać w podanej kolejności lub niezależnie od siebie.
- [TO LAB] Potoki danych działające z szybkością TPU: tf.data.Dataset i TFRecords
- Pierwszy model Keras z wykorzystaniem uczenia transferowego
- Splotowe sieci neuronowe z Keras i TPU
- Nowoczesne sieci konwolucyjne, squeezenet, Xception, z Keras i TPU
Czego się nauczysz
- Aby załadować dane treningowe, użyj interfejsu tf.data.Dataset API
- Aby efektywnie wczytywać dane treningowe z GCS, używaj formatu TFRecord
Prześlij opinię
Jeśli zauważysz, że w tym laboratorium z kodem coś jest nie tak, daj nam znać. Opinię można przesłać, korzystając z formularza dotyczącego problemów na GitHubie [link do przesyłania opinii].
2. Krótki przewodnik po Google Colaboratory
Ten moduł wykorzystuje Google Collaboratory i nie wymaga żadnej konfiguracji. Colaboratory to internetowa platforma do obsługi notatników do celów edukacyjnych. Oferuje on bezpłatne szkolenie dotyczące procesora CPU, GPU i TPU.
Aby zapoznać się z Colaboratory, możesz otworzyć ten przykładowy notatnik i przejrzeć kilka komórek.
Wybierz backend TPU
W menu Colab wybierz Środowisko wykonawcze > Zmień typ środowiska wykonawczego, a następnie wybierz TPU. W tym laboratorium kodu skorzystasz z wydajnego TPU (jednostki Tensor Processing Unit) z przyspieszeniem sprzętowym. Połączenie z runtime nastąpi automatycznie przy pierwszym uruchomieniu lub możesz użyć przycisku „Połącz” w prawym górnym rogu.
Wykonywanie notatnika
Uruchom po kolei komórki, klikając wybraną komórkę i naciskając klawisze Shift+ENTER. Aby uruchomić cały notatnik, możesz też kliknąć Środowisko wykonawcze > Uruchom wszystko.
Spis treści
Wszystkie notatniki mają spis treści. Możesz go otworzyć, klikając czarną strzałkę po lewej stronie.
Ukryte komórki
Niektóre komórki będą zawierać tylko tytuł. Jest to funkcja notatnika specyficzna dla Colab. Można je dwukrotnie kliknąć, aby zobaczyć w nich kod, ale zwykle nie jest to zbyt interesujące. Zwykle są to funkcje wspomagające lub wizualizacyjne. Aby zdefiniować funkcje, musisz uruchomić te komórki.
Uwierzytelnianie
Colab może uzyskać dostęp do Twoich prywatnych zasobników Google Cloud Storage, jeśli uwierzytnisz się za pomocą autoryzowanego konta. Powyższy fragment kodu aktywuje proces uwierzytelniania.
3. [INFO] Czym są jednostki Tensor Processing Unit (TPU)?
W skrócie
Kod do trenowania modelu w TPU w Keras (i korzystania z GPU lub CPU, jeśli jednostka TPU jest niedostępna):
try: # detect TPUs
tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines
# use TPUStrategy scope to define model
with strategy.scope():
model = tf.keras.Sequential( ... )
model.compile( ... )
# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)
Wykorzystamy dziś jednostki TPU do utworzenia i zoptymalizowania klasyfikatora kwiatów z szybkością interaktywną (minuty na bieg trenowania).
Dlaczego TPU?
Nowoczesne procesory graficzne są zorganizowane wokół programowalnych „rdzeni”, czyli bardzo elastycznej architektury, która umożliwia im wykonywanie różnych zadań, takich jak renderowanie 3D, deep learning, symulacje fizyczne itp. TPU łączy klasyczny procesor wektorowy z dedykowaną jednostką mnożenia macierzy i doskonale sprawdza się w przypadku zadań, w których dominuje mnożenie dużych macierzy, np. w sieciach neuronowych.
Ilustracja: gęsta warstwa sieci neuronowej jako mnożenie macierzy z ośmioma obrazami przetwarzanymi przez sieć neuronową jednocześnie. Sprawdź, czy mnożenie 1 wiersza z kolumną ma ważoną sumę wszystkich wartości pikseli na obrazie. Warstwy splotowe można również przedstawić jako mnożniki macierzy, chociaż jest to nieco bardziej skomplikowane ( wyjaśnienie znajduje się w sekcji 1).
Sprzęt
MXU i VPU
Rdzeń TPU v2 składa się z jednostki mnożenia macierzy (MXU), która wykonuje mnożenie macierzy, oraz jednostki przetwarzania wektorów (VPU) do wykonywania wszystkich innych zadań, takich jak aktywacje, softmax itp. VPU obsługuje obliczenia float32 i int32. Z kolei moduł MXU działa w mieszanym, 16-32-bitowym formacie zmiennoprzecinkowym o mieszanej dokładności.
Mieszana precyzja zmiennoprzecinkowa i bfloat16
MXU oblicza mnożniki macierzy, używając danych wejściowych bfloat16 i danych wyjściowych float32. Zbiorcze gromadzenie danych jest wykonywane z dokładnością do float32.
Trenowanie sieci neuronowej jest zwykle odporne na szum spowodowany zmniejszoną precyzją liczby zmiennoprzecinkowej. W niektórych przypadkach szum może nawet pomóc optymalizatorowi w konwergencji. 16-bitowa precyzja liczby zmiennoprzecinkowej była tradycyjnie używana do przyspieszania obliczeń, ale formaty float16 i float32 mają bardzo różne zakresy. Zmniejszenie precyzji z float32 na float16 zwykle powoduje przepełnienie i niedopełnienie. Istnieją rozwiązania, ale aby je zastosować, zwykle trzeba wykonać dodatkowe czynności.
Dlatego w procesorach TPU wprowadziliśmy format bfloat16. Jest to skrócona wersja typu float32 z tymi samymi bitami wykładniczymi i zakresem co typ float32. W związku z tym, że jednostki TPU mnożą macierz obliczeniową z mieszaną precyzją z danymi wejściowymi bfloat16, ale z danymi wyjściowymi float32, oznacza to, że zwykle nie trzeba wprowadzać żadnych zmian w kodzie, aby skorzystać ze zmniejszonej dokładności, aby uzyskać wzrost wydajności.
Tablica skurczowa
MXU implementuje mnożenia macierzy w sprzęcie za pomocą tak zwanej „tablicy skurczowej”, w którym elementy danych przepływają przez szereg sprzętowych jednostek obliczeniowych. (W medycynie „skurcz” odnosi się do skurczów serca i przepływu krwi, a w tym przypadku do przepływu danych).
Podstawowym elementem mnożenia macierzy jest iloczyn skalarny wiersza jednej macierzy i kolumny drugiej macierzy (patrz ilustracja na początku tej sekcji). W przypadku mnożenia macierzy Y=X*W jednym z elementów wyniku będzie:
Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]
W przypadku GPU zaprogramowano ten iloczyn skalarny na „rdzeń” GPU, a następnie uruchamiał go równolegle na dowolnej liczbie dostępnych rdzeni, aby spróbować naraz obliczyć wszystkie wartości wynikowej macierzy. Jeśli wynikowa matryca ma rozmiar 128 x 128, wymaga to dostępności 128 x 128 = 16 tys. „rdzeni”, co zwykle jest niemożliwe. Największe procesory graficzne mają około 4000 rdzeni. Z drugiej strony TPU używa minimalnej ilości sprzętu dla jednostek obliczeniowych w MXU: tylko bfloat16 x bfloat16 => float32
mnożniki i akumulatory, nic więcej. Są one tak małe, że TPU może zaimplementować 16 tys. z nich w MXU 128 × 128 i przetworzyć to mnożenie macierzy jednym poleceniem.
Ilustracja: tablica skurczowa MXU. Elementy obliczeniowe to zasobniki pomnożone. Wartości jednej macierzy są wczytywane do tablicy (czerwone kropki). Wartości z innej macierzy przepływają przez tablicę (szare kropki). Linie pionowe propagują wartości w górę. Linie poziome przekazują częściowe sumy. W ramach ćwiczenia dla użytkownika należy sprawdzić, czy w miarę przepływu danych przez tablicę pojawia się wynik mnożenia macierzy po prawej stronie.
Dodatkowo, gdy iloczyny są obliczane w MXU, sumy pośrednie są po prostu przesyłane między sąsiednimi jednostkami obliczeniowymi. Nie muszą być przechowywane ani pobierane z pamięci ani nawet z pliku rejestru. W efekcie architektura układów skurczowych TPU charakteryzuje się znaczną gęstością i mocą, a przy mnożeniu macierzy ma istotny wzrost szybkości w porównaniu z GPU.
Cloud TPU
Jeśli wyślesz żądanie Cloud TPU v2 w Google Cloud Platform, otrzymasz maszynę wirtualną z płytką TPU dołączoną przez PCI. Karta TPU ma 4 podwójne rdzenie TPU. Każdy rdzeń TPU obejmuje jednostkę VPU (Vector Processing Unit) i jednostkę mnożenia matriX o wymiarach 128 x 128 MXU. Ta „Cloud TPU” jest wtedy zazwyczaj połączona przez sieć z maszyną wirtualną, która jej zażądała. Pełny obraz wygląda tak:
Ilustracja: maszyna wirtualna z podłączonym do sieci akceleratorem „Cloud TPU” „Cloud TPU” składa się z maszyny wirtualnej z kartą TPU podłączoną do gniazda PCI z 4 podwójnymi rdzeniami TPU.
Pody TPU
W centrach danych Google jednostki TPU są połączone z połączeniami międzysieciowymi o wysokiej wydajności (HPC), co może sprawić, że będą one postrzegane jako jeden bardzo duży akcelerator. Google nazywa je podami i mogą obejmować do 512 rdzeni TPU v2 lub 2048 rdzeni TPU v3.
Ilustracja: pod TPU v3. Płyty i racki TPU połączone za pomocą interfejsu HPC.
Podczas trenowania gradienty są wymieniane między rdzeniami TPU za pomocą algorytmu all-reduce (dobry opis algorytmu all-reduce tutaj). Wytrenowany model może wykorzystywać możliwości sprzętowe przez trenowanie na dużych wielkościach wsadu.
Ilustracja: synchronizacja gradientów podczas trenowania z wykorzystaniem algorytmu all-reduce w Google TPU w sieci toroidalnej sieci HPC 2-D typu mesh.
Oprogramowanie
Trenowanie na dużym wsadzie
Idealna wielkość partii dla TPU to 128 elementów danych na rdzeń TPU, ale sprzęt może już dobrze wykorzystać 8 elementów danych na rdzeń TPU. Pamiętaj, że jedna z Cloud TPU ma 8 rdzeni.
W tym laboratorium kodu będziemy używać interfejsu Keras API. W Keras określona wsad jest reprezentowana przez globalny rozmiar wsadu dla całej jednostki TPU. Wsady zostaną automatycznie podzielone na 8 i będą uruchamiane w 8 rdzeniach TPU.
Więcej wskazówek dotyczących wydajności znajdziesz w przewodniku po wydajności TPU. W przypadku niektórych modeli należy zachować szczególną ostrożność w przypadku bardzo dużych wsadów. Więcej informacji znajdziesz w artykule LARSOptimizer.
Na zapleczu: XLA
Programy Tensorflow definiują grafy obliczeniowe. TPU nie uruchamia bezpośrednio kodu w Pythonie, tylko uruchamia wykres obliczeniowy zdefiniowany przez program Tensorflow. W tle kompilator XLA (kompilator przyspieszonej algebry liniowej) przekształca graf Tensorflow z węzłami obliczeniowymi w kod maszynowy TPU. Kompilator ten wykonuje też wiele zaawansowanych optymalizacji kodu i układu pamięci. Kompilacja odbywa się automatycznie, gdy zadanie jest wysyłane do TPU. Nie musisz dodawać XLA do łańcucha tworzenia.
Ilustracja: aby działał w TPU, graf obliczeniowy zdefiniowany w programie Tensorflow jest najpierw przekształcany w reprezentację formatu XLA (przyspieszonego kompilatora algebry liniowej), a następnie skompilowany przez XLA do kodu maszynowego TPU.
Używanie TPU w Keras
Od wersji Tensorflow 2.1 TPU są obsługiwane przez interfejs Keras API. Obsługa Keras działa na TPU i podach TPU. Oto przykład, który działa na TPU, GPU i CPU:
try: # detect TPUs
tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines
# use TPUStrategy scope to define model
with strategy.scope():
model = tf.keras.Sequential( ... )
model.compile( ... )
# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)
W tym fragmencie kodu:
TPUClusterResolver().connect()
znajduje TPU w sieci. Działa bez parametrów w większości systemów Google Cloud (zadań na AI Platform, Colaboratory, Kubeflow, maszyn wirtualnych do deep learningu utworzonych za pomocą narzędzia „ctpu up”). Te systemy wiedzą, gdzie znajduje się ich TPU dzięki zmiennej środowiskowej TPU_NAME. Jeśli tworzysz TPU ręcznie, ustaw zmienną środowiskową TPU_NAME na maszynie wirtualnej, z której korzystasz, lub wywołajTPUClusterResolver
z jawnymi parametrami:TPUClusterResolver(tp_uname, zone, project)
- Element
TPUStrategy
implementuje rozkład i algorytm synchronizacji gradientu „all-reduce”. - Strategia jest stosowana w ramach zakresu. Model musi być zdefiniowany w zakresie strategii (zakres).
- Funkcja
tpu_model.fit
oczekuje obiektu tf.data.Dataset na potrzeby danych wejściowych na potrzeby trenowania TPU.
Typowe zadania przenoszenia TPU
- Dane do modelu Tensorflow można wczytywać na wiele sposobów, ale w przypadku TPU wymagane jest użycie interfejsu
tf.data.Dataset
API. - TPU są bardzo szybkie, a pozyskiwanie danych często staje się wąskim gardłem działające na nich. W przewodniku po skuteczności TPU znajdziesz narzędzia do wykrywania wąskich gardeł danych oraz inne wskazówki dotyczące wydajności.
- Liczby int8 i int16 są traktowane jako int32. TPU nie ma sprzętu z liczbami całkowitymi działającymi na mniej niż 32 bitach.
- Niektóre operacje Tensorflow nie są obsługiwane. Listę znajdziesz tutaj. Dobra wiadomość jest taka, że to ograniczenie dotyczy tylko kodu treningowego, czyli przejść do przodu i do tyłu przez model. W swojej ścieżce przetwarzania danych możesz nadal używać wszystkich operacji Tensorflow, ponieważ będą one wykonywane na procesorze.
tf.py_func
nie jest obsługiwany na TPU.
4. Wczytuję dane
Będziemy pracować nad zbiorem danych zawierającym zdjęcia kwiatów. Celem jest nauczenie się podziału kwiatów na 5 typów. Dane są wczytywane za pomocą interfejsu API tf.data.Dataset
. Najpierw poznajmy interfejs API.
Nauka praktyczna
Otwórz ten notatnik, uruchom komórki (Shift-Enter) i postępuj zgodnie z instrukcjami, które pojawiają się w miejscach oznaczonych etykietą „WYMAGANE DZIAŁANIA”.
Fun with tf.data.Dataset (playground).ipynb
Informacje dodatkowe
Informacje o zbiorze danych „flowers”
Zbiór danych jest podzielony na 5 folderów. Każdy folder zawiera kwiaty jednego rodzaju. Foldery te mają nazwy: słoneczniki, stokrotka, mniszek, tulipany i róże. Dane są przechowywane w publicznym zasobniku w Google Cloud Storage. Fragment:
gs://flowers-public/sunflowers/5139971615_434ff8ed8b_n.jpg
gs://flowers-public/daisy/8094774544_35465c1c64.jpg
gs://flowers-public/sunflowers/9309473873_9d62b9082e.jpg
gs://flowers-public/dandelion/19551343954_83bb52f310_m.jpg
gs://flowers-public/dandelion/14199664556_188b37e51e.jpg
gs://flowers-public/tulips/4290566894_c7f061583d_m.jpg
gs://flowers-public/roses/3065719996_c16ecd5551.jpg
gs://flowers-public/dandelion/8168031302_6e36f39d87.jpg
gs://flowers-public/sunflowers/9564240106_0577e919da_n.jpg
gs://flowers-public/daisy/14167543177_cd36b54ac6_n.jpg
Dlaczego tf.data.Dataset?
Keras i Tensorflow akceptują zbiory danych we wszystkich funkcjach trenowania i oceny. Po załadowaniu danych do zbioru danych interfejs API udostępnia wszystkie podstawowe funkcje przydatne do danych do trenowania sieci neuronowej:
dataset = ... # load something (see below)
dataset = dataset.shuffle(1000) # shuffle the dataset with a buffer of 1000
dataset = dataset.cache() # cache the dataset in RAM or on disk
dataset = dataset.repeat() # repeat the dataset indefinitely
dataset = dataset.batch(128) # batch data elements together in batches of 128
AUTOTUNE = tf.data.AUTOTUNE
dataset = dataset.prefetch(AUTOTUNE) # prefetch next batch(es) while training
Wskazówki dotyczące wydajności i sprawdzone metody dotyczące zbiorów danych znajdziesz w tym artykule. Dokumentacja referencyjna znajduje się tutaj.
tf.data.Dataset – podstawy
Dane zwykle występują w kilku plikach, tutaj w obrazach. Zbiór danych z nazwami plików możesz utworzyć, wywołując:
filenames_dataset = tf.data.Dataset.list_files('gs://flowers-public/*/*.jpg')
# The parameter is a "glob" pattern that supports the * and ? wildcards.
Następnie „mapuj” funkcję na każdą nazwę pliku, która normalnie wczyta i zdekoduje plik w rzeczywistych danych w pamięci:
def decode_jpeg(filename):
bits = tf.io.read_file(filename)
image = tf.io.decode_jpeg(bits)
return image
image_dataset = filenames_dataset.map(decode_jpeg)
# this is now a dataset of decoded images (uint8 RGB format)
Aby iterować po zbiorze danych:
for data in my_dataset:
print(data)
Zbiory danych krotek
W przypadku uczenia nadzorowanego zbiór danych treningowych składa się zwykle z par danych treningowych i prawidłowych odpowiedzi. Aby to umożliwić, funkcja dekodowania może zwracać krotki. W ten sposób uzyskasz zbiór danych z tuplami, które będą zwracane podczas iteracji. Zwracane wartości to tensory Tensorflow gotowe do wykorzystania przez model. Możesz wywołać dla nich metodę .numpy()
, aby wyświetlić nieprzetworzone wartości:
def decode_jpeg_and_label(filename):
bits = tf.read_file(filename)
image = tf.io.decode_jpeg(bits)
label = ... # extract flower name from folder name
return image, label
image_dataset = filenames_dataset.map(decode_jpeg_and_label)
# this is now a dataset of (image, label) pairs
for image, label in dataset:
print(image.numpy().shape, label.numpy())
Wniosek:ładowanie pojedynczych obrazów jest powolne.
Podczas iteracji nad tym zbiorem danych zobaczysz, że możesz wczytywać około 1–2 obrazów na sekundę. To jest zbyt wolne! Akceleratory sprzętowe, których użyjemy do treningu, mogą osiągnąć wielokrotnie wyższą szybkość. Przejdź do następnej sekcji, aby dowiedzieć się, jak nam to pozwoli.
Rozwiązanie
Oto notatnik z rozwiązaniem. Możesz z niego skorzystać, jeśli utkniesz.
Fun with tf.data.Dataset (solution).ipynb
Omówione zagadnienia
- 🤔 tf.data.Dataset.list_files
- 🤔 tf.data.Dataset.map
- 🤔 Zbiory danych z tuplami
- 😀 powtarzanie się z wykorzystaniem zbiorów danych
Poświęć chwilę na przejrzenie tej listy kontrolnej.
5. Szybkie wczytywanie danych
Akceleratory sprzętowe Tensor Processing Unit (TPU), których użyjemy w tym module, są bardzo szybkie. Często wyzwaniem jest jednak na tyle szybko, by dostarczyć im dane, by utrzymać ich zainteresowanie. Google Cloud Storage (GCS) jest w stanie utrzymać bardzo dużą przepustowość, ale tak jak w przypadku wszystkich systemów pamięci masowej w chmurze, inicjowanie połączenia z siecią wiąże się z pewnymi kosztami. Dlatego przechowywanie danych w tysiącach osobnych plików nie jest optymalnym rozwiązaniem. Podzielimy je na mniejszą liczbę plików i wykorzystamy możliwości zbioru tf.data.Dataset do równoległego odczytu z wielu plików.
Odczyt
Kod, który wczytuje pliki graficzne, zmienia ich rozmiar do wspólnego rozmiaru, a następnie zapisuje je w 16 plikach TFRecord, znajduje się w poniższym notatniku. Prosimy o szybkie zapoznanie się z nim. Jego wykonywanie nie jest konieczne, ponieważ w pozostałej części ćwiczenia z programowania otrzymasz dane w prawidłowym formacie TFRecord.
Flower pictures to TFRecords.ipynb
Optymalny układ danych zapewniający optymalną przepustowość usługi GCS
Format pliku TFRecord
Preferowanym przez Tensorflow formatem plików do przechowywania danych jest format TFRecord oparty na protobuf. Mogą też działać inne formaty serializacji, ale możesz załadować zbiór danych z plików TFRecord bezpośrednio, pisząc:
filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below
W celu uzyskania optymalnej wydajności zalecamy używanie poniższego bardziej złożonego kodu do odczytu z wielu plików TFRecord jednocześnie. Ten kod będzie równolegle odczytywać N plików, ignorując kolejność danych na rzecz szybkości odczytu.
AUTOTUNE = tf.data.AUTOTUNE
ignore_order = tf.data.Options()
ignore_order.experimental_deterministic = False
filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
dataset = dataset.with_options(ignore_order)
dataset = dataset.map(...) # do the TFRecord decoding here - see below
Ściągawka TFRecord
W plikach TFRecord można przechowywać 3 typy danych: ciągi bajtów (lista bajtów), 64-bitowe liczby całkowite i 32-bitowe ułamki zmiennoprzecinkowe. Są one zawsze przechowywane jako listy, a pojedynczy element danych będzie listą o rozmiarze 1. Aby zapisać dane w pliku TFRecord, możesz użyć poniższych funkcji pomocniczych.
zapis ciągów bajtów
# warning, the input is a list of byte strings, which are themselves lists of bytes
def _bytestring_feature(list_of_bytestrings):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))
zapisywanie liczb całkowitych
def _int_feature(list_of_ints): # int64
return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))
pisanie liczba zmiennoprzecinkowa
def _float_feature(list_of_floats): # float32
return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))
napisanie TFRecord, korzystając z powyższych wskazówek
# input data in my_img_bytes, my_class, my_height, my_width, my_floats
with tf.python_io.TFRecordWriter(filename) as out_file:
feature = {
"image": _bytestring_feature([my_img_bytes]), # one image in the list
"class": _int_feature([my_class]), # one class in the list
"size": _int_feature([my_height, my_width]), # fixed length (2) list of ints
"float_data": _float_feature(my_floats) # variable length list of floats
}
tf_record = tf.train.Example(features=tf.train.Features(feature=feature))
out_file.write(tf_record.SerializeToString())
Aby odczytywać dane z rekordów TFRecord, musisz najpierw zadeklarować układ przechowywanych rekordów. W deklaracji możesz uzyskać dostęp do dowolnego nazwanego pola w postaci listy o stałej długości lub listy o zmiennej długości:
odczytywanie z plików TFRecord
def read_tfrecord(data):
features = {
# tf.string = byte string (not text string)
"image": tf.io.FixedLenFeature([], tf.string), # shape [] means scalar, here, a single byte string
"class": tf.io.FixedLenFeature([], tf.int64), # shape [] means scalar, i.e. a single item
"size": tf.io.FixedLenFeature([2], tf.int64), # two integers
"float_data": tf.io.VarLenFeature(tf.float32) # a variable number of floats
}
# decode the TFRecord
tf_record = tf.io.parse_single_example(data, features)
# FixedLenFeature fields are now ready to use
sz = tf_record['size']
# Typical code for decoding compressed images
image = tf.io.decode_jpeg(tf_record['image'], channels=3)
# VarLenFeature fields require additional sparse.to_dense decoding
float_data = tf.sparse.to_dense(tf_record['float_data'])
return image, sz, float_data
# decoding a tf.data.TFRecordDataset
dataset = dataset.map(read_tfrecord)
# now a dataset of triplets (image, sz, float_data)
Przydatne fragmenty kodu:
odczytywanie pojedynczych elementów danych
tf.io.FixedLenFeature([], tf.string) # for one byte string
tf.io.FixedLenFeature([], tf.int64) # for one int
tf.io.FixedLenFeature([], tf.float32) # for one float
czytanie list elementów o stałym rozmiarze
tf.io.FixedLenFeature([N], tf.string) # list of N byte strings
tf.io.FixedLenFeature([N], tf.int64) # list of N ints
tf.io.FixedLenFeature([N], tf.float32) # list of N floats
odczytywanie zmiennej liczby elementów danych
tf.io.VarLenFeature(tf.string) # list of byte strings
tf.io.VarLenFeature(tf.int64) # list of ints
tf.io.VarLenFeature(tf.float32) # list of floats
Funkcja VarLenFeature zwraca wektor rozproszony i po zdekodowaniu pliku TFRecord jest wymagany dodatkowy krok:
dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])
W plikach TFRecord można też mieć opcjonalne pola. Jeśli podczas odczytu pola określisz wartość domyślną, w przypadku braku pola zwrócona zostanie wartość domyślna, a nie błąd.
tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional
Omówione zagadnienia
- 🤔 fragmentacja plików danych z myślą o szybkim dostępie z GCS
- 😓 jak zapisywać pliki TFRecord. (Nie pamiętasz już składni? Nie szkodzi. Dodaj tę stronę do zakładek jako ściągawkę).
- 🤔 wczytuję zbiór danych z plików TFRecord przy użyciu TFRecordDataset
Poświęć chwilę na przejrzenie tej listy kontrolnej.
6. Gratulacje!
Możesz teraz przesyłać dane do TPU. Przejdź do następnego modułu
- [LABORATORIUM] Potoki danych o szybkości TPU: tf.data.Dataset i TFRecords
- Twój pierwszy model Keras z nauką przenoszenia
- Splotowe sieci neuronowe wykorzystujące Keras i TPU
- Nowoczesne konwnety, squeezenet, Xception z wykorzystaniem Keras i TPU
TPU w praktyce
Układy TPU i GPU są dostępne w Cloud AI Platform:
- na maszynach wirtualnych deep learning.
- W notatkach w AI Platform
- w zadaniach AI Platform Training,
Na koniec – chętnie poznamy Twoją opinię. Poinformuj nas, jeśli zauważysz w tym module coś nie tak lub jeśli uważasz, że można go ulepszyć. Opinie można przesyłać za pomocą zgłoszeń na GitHubie [link do opinii].
|