1. Przegląd
TPU są bardzo szybkie. Strumień danych treningowych musi nadążać za szybkością trenowania. Z tego modułu dowiesz się, jak wczytywać dane z GCS za pomocą interfejsu tf.data.Dataset API, aby przekazywać je do TPU.
Ten moduł jest częścią 1 serii „Keras na TPU”. Możesz wykonać je w podanej kolejności lub niezależnie od siebie.
- [TO ĆWICZENIE] Potoki danych o szybkości TPU: tf.data.Dataset i TFRecords
- Pierwszy model Keras z uczeniem transferowym
- Konwolucyjne sieci neuronowe z użyciem Keras i TPU
- Nowoczesne sieci konwolucyjne, SqueezeNet i Xception z użyciem Keras i TPU

Czego się nauczysz
- Używanie interfejsu tf.data.Dataset API do wczytywania danych treningowych
- Aby używać formatu TFRecord do wydajnego wczytywania danych treningowych z GCS
Prześlij opinię
Jeśli zauważysz w tym module coś nieprawidłowego, poinformuj nas o tym. Opinie można przesyłać za pomocą zgłoszeń w GitHub [link do opinii].
2. Krótkie wprowadzenie do Google Colaboratory
W tym module używamy Google Collaboratory, więc nie musisz niczego konfigurować. Colaboratory to internetowa platforma do tworzenia notatników przeznaczona do celów edukacyjnych. Oferuje bezpłatne szkolenia dotyczące procesorów, układów GPU i TPU.

Możesz otworzyć ten przykładowy notatnik i uruchomić kilka komórek, aby zapoznać się z Colaboratory.
Wybieranie backendu TPU

W menu Colab kliknij Środowisko wykonawcze > Zmień typ środowiska wykonawczego, a następnie wybierz TPU. W tym module nauczysz się korzystać z wydajnej jednostki TPU (Tensor Processing Unit) do trenowania z akceleracją sprzętową. Połączenie z czasem działania nastąpi automatycznie przy pierwszym wykonaniu kodu. Możesz też użyć przycisku „Połącz” w prawym górnym rogu.
Wykonywanie notatnika

Uruchamiaj komórki pojedynczo, klikając je i naciskając Shift + Enter. Możesz też uruchomić cały notatnik, klikając Ś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ą wyświetlać tylko swój tytuł. Jest to funkcja notatnika Colab. Możesz kliknąć je dwukrotnie, aby zobaczyć kod w środku, ale zwykle nie jest on zbyt interesujący. Zwykle są to funkcje pomocnicze lub wizualizacyjne. Nadal musisz uruchomić te komórki, aby zdefiniować funkcje w nich zawarte.
Uwierzytelnianie

Colab może uzyskać dostęp do Twoich prywatnych zasobników Google Cloud Storage, jeśli uwierzytelnienie nastąpi przy użyciu autoryzowanego konta. Powyższy fragment kodu uruchomi proces uwierzytelniania.
3. [INFO] Czym są jednostki Tensor Processing Unit (TPU)?
W skrócie

Kod do trenowania modelu na TPU w Keras (z możliwością powrotu do GPU lub CPU, jeśli TPU nie jest dostępny):
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=...)
Dziś użyjemy TPU do zbudowania i zoptymalizowania klasyfikatora kwiatów w interaktywnym tempie (minuty na sesję trenowania).

Dlaczego jednostki TPU?
Nowoczesne procesory graficzne są zorganizowane wokół programowalnych „rdzeni”, co stanowi bardzo elastyczną architekturę, która umożliwia im wykonywanie różnych zadań, takich jak renderowanie 3D, uczenie głębokie, symulacje fizyczne itp. TPU z kolei łączą klasyczny procesor wektorowy z dedykowaną jednostką mnożenia macierzy i doskonale sprawdzają się w każdym zadaniu, w którym dominują duże mnożenia macierzy, np. w sieciach neuronowych.

Ilustracja: gęsta warstwa sieci neuronowej jako mnożenie macierzy, w którym partia 8 obrazów jest przetwarzana przez sieć neuronową jednocześnie. Wykonaj mnożenie wiersza przez kolumnę, aby sprawdzić, czy rzeczywiście oblicza ważoną sumę wartości wszystkich pikseli obrazu. Warstwy konwolucyjne też można przedstawić jako mnożenie macierzy, choć jest to nieco bardziej skomplikowane ( wyjaśnienie znajdziesz tutaj, w sekcji 1).
Sprzęt
MXU i VPU
Rdzeń TPU v2 składa się z jednostki mnożnika macierzy (MXU), która wykonuje mnożenie macierzy, oraz jednostki przetwarzania wektorowego (VPU), która wykonuje wszystkie inne zadania, takie jak aktywacje, softmax itp. Jednostka VPU obsługuje obliczenia zmiennoprzecinkowe 32-bitowe i całkowitoliczbowe 32-bitowe. MXU działa natomiast w formacie zmiennoprzecinkowym o mieszanej precyzji 16–32 bitów.

Zmiennoprzecinkowe liczby mieszanej precyzji i bfloat16
MXU oblicza mnożenie macierzy przy użyciu danych wejściowych bfloat16 i danych wyjściowych float32. Pośrednie akumulacje są wykonywane z precyzją float32.

Trenowanie sieci neuronowych jest zwykle odporne na szum wprowadzany przez zmniejszoną precyzję zmiennoprzecinkową. W niektórych przypadkach szum pomaga nawet optymalizatorowi osiągnąć zbieżność. 16-bitowa precyzja zmiennoprzecinkowa była tradycyjnie używana do przyspieszania obliczeń, ale formaty float16 i float32 mają bardzo różne zakresy. Zmniejszenie precyzji z float32 do float16 zwykle powoduje przekroczenie zakresu w górę i w dół. Istnieją rozwiązania, ale zwykle wymagają dodatkowej pracy, aby float16 działał prawidłowo.
Dlatego w TPU wprowadziliśmy format bfloat16. Jest to skrócony format float32, który ma dokładnie te same bity wykładnika i zakres co float32. W połączeniu z faktem, że TPU wykonują mnożenie macierzy w mieszanej precyzji z danymi wejściowymi bfloat16, ale danymi wyjściowymi float32, oznacza to, że zwykle nie są potrzebne żadne zmiany w kodzie, aby skorzystać ze wzrostu wydajności wynikającego z mniejszej precyzji.
Macierz systoliczna
MXU wykonuje mnożenie macierzy w sprzęcie za pomocą tzw. architektury „tablicy systolicznej”, w której elementy danych przepływają przez tablicę jednostek obliczeniowych. (W medycynie termin „skurczowy” 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 (ilustracja u góry tej sekcji). W przypadku mnożenia macierzy Y=X*W jeden element wyniku to:
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]
Na procesorze graficznym programuje się ten iloczyn skalarny w „rdzeniu” procesora graficznego, a następnie wykonuje się go równolegle na tylu „rdzeniach”, ile jest dostępnych, aby spróbować obliczyć wszystkie wartości wynikowej macierzy naraz. Jeśli wynikowa macierz ma rozmiar 128 x 128, wymagałoby to 128 x 128=16 tys. „rdzeni”, co zwykle nie jest możliwe. Największe procesory graficzne mają około 4000 rdzeni. TPU z kolei wykorzystuje w jednostkach obliczeniowych MXU absolutne minimum sprzętu: tylko bfloat16 x bfloat16 => float32 mnożarki-akumulatory i nic więcej. Są one tak małe, że jednostka TPU może zaimplementować 16 tys. takich jednostek w macierzy MXU o wymiarach 128 x 128 i przetworzyć to mnożenie macierzy za jednym razem.

Ilustracja: tablica ciśnienia skurczowego MXU. Elementami obliczeniowymi są mnożniki-akumulatory. Wartości jednej macierzy są wczytywane do tablicy (czerwone kropki). Wartości z drugiej macierzy przepływają przez tablicę (szare kropki). Linie pionowe przenoszą wartości w górę. Linie poziome propagują sumy częściowe. Sprawdzenie, czy w miarę przepływu danych przez tablicę po prawej stronie pojawia się wynik mnożenia macierzy, pozostawiamy użytkownikowi.
Dodatkowo podczas obliczania iloczynów skalarnych w MXU sumy pośrednie przepływają między sąsiednimi jednostkami obliczeniowymi. Nie trzeba ich przechowywać ani pobierać z pamięci ani nawet z pliku rejestru. W rezultacie architektura tablicy systolicznej TPU ma znaczną przewagę pod względem gęstości i mocy, a także niepomijalną przewagę pod względem szybkości nad GPU podczas obliczania mnożenia macierzy.
Cloud TPU
Gdy poprosisz o 1 „Cloud TPU v2” na Google Cloud Platform, otrzymasz maszynę wirtualną z płytą TPU podłączoną przez PCI. Płyta TPU ma 4 dwurdzeniowe układy TPU. Każdy rdzeń TPU ma jednostkę VPU (Vector Processing Unit) i jednostkę MXU (MatriX multiply Unit) o wymiarach 128 x 128. Ta „Cloud TPU” jest zwykle połączona przez sieć z maszyną wirtualną, która ją zażądała. Pełny obraz wygląda więc tak:

Ilustracja: maszyna wirtualna z akceleratorem „Cloud TPU” podłączonym do sieci. „Cloud TPU” to maszyna wirtualna z płytą TPU podłączoną przez PCI, na której znajdują się 4 dwurdzeniowe układy TPU.
Pody TPU
W centrach danych Google układy TPU są połączone z interfejsem komputera o dużej mocy obliczeniowej (HPC), dzięki czemu mogą działać jako jeden bardzo duży akcelerator. Google nazywa je podami. Mogą one obejmować do 512 rdzeni TPU v2 lub 2048 rdzeni TPU v3.

Ilustracja: pod TPU v3. Płyty i szafy TPU połączone za pomocą połączenia międzysieciowego HPC.
Podczas trenowania gradienty są wymieniane między rdzeniami TPU za pomocą algorytmu all-reduce ( dobre wyjaśnienie algorytmu all-reduce znajdziesz tutaj). Trenowany model może wykorzystywać sprzęt, trenując na dużych rozmiarach wsadu.

Ilustracja: synchronizacja gradientów podczas trenowania z użyciem algorytmu all-reduce w dwuwymiarowej sieci HPC o topologii toroidu na jednostkach TPU Google.
Oprogramowanie
Trenowanie z dużą wielkością wsadu
Idealna wielkość wsadu dla TPU to 128 elementów danych na rdzeń TPU, ale sprzęt może już wykazywać dobre wykorzystanie od 8 elementów danych na rdzeń TPU. Pamiętaj, że jedna Cloud TPU ma 8 rdzeni.
W tym module użyjemy interfejsu Keras API. W Keras określona przez Ciebie wielkość wsadu jest globalną wielkością wsadu dla całego TPU. Partie zostaną automatycznie podzielone na 8 części i uruchomione na 8 rdzeniach TPU.

Dodatkowe wskazówki dotyczące wydajności znajdziesz w przewodniku po wydajności TPU. W przypadku bardzo dużych rozmiarów partii w niektórych modelach może być wymagana szczególna ostrożność. Więcej informacji znajdziesz w artykule LARSOptimizer.
Dla zaawansowanych: XLA
Programy TensorFlow definiują wykresy obliczeniowe. TPU nie uruchamia bezpośrednio kodu Pythona, ale wykres obliczeniowy zdefiniowany przez program TensorFlow. W tle kompilator XLA (kompilator przyspieszonej algebry liniowej) przekształca graf obliczeniowy TensorFlow w kod maszynowy TPU. Ten kompilator wykonuje też wiele zaawansowanych optymalizacji kodu i układu pamięci. Kompilacja odbywa się automatycznie w miarę przesyłania zadań do TPU. Nie musisz wyraźnie uwzględniać XLA w łańcuchu kompilacji.

Ilustracja: aby uruchomić program na TPU, graf obliczeniowy zdefiniowany przez program TensorFlow jest najpierw tłumaczony na reprezentację XLA (kompilator przyspieszonej algebry liniowej), a następnie kompilowany przez XLA do kodu maszynowego TPU.
Korzystanie z TPU w Keras
TPU są obsługiwane przez interfejs Keras API od wersji Tensorflow 2.1. Obsługa Keras działa na TPU i TPU w podach. 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 (zadania AI Platform, Colaboratory, Kubeflow, maszyny wirtualne do uczenia głębokiego utworzone 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łaj funkcjęTPUClusterResolverz jawnymi parametrami:TPUClusterResolver(tp_uname, zone, project)TPUStrategyto część, która implementuje algorytm dystrybucji i synchronizacji gradientów „all-reduce”.- Strategia jest stosowana w ramach zakresu. Model musi być zdefiniowany w zakresie funkcji strategy().
- Funkcja
tpu_model.fitoczekuje obiektu tf.data.Dataset jako danych wejściowych do trenowania na TPU.
Typowe zadania związane z przenoszeniem kodu na TPU
- Dane do modelu TensorFlow można wczytywać na wiele sposobów, ale w przypadku TPU wymagane jest użycie interfejsu
tf.data.Dataset. - Procesory TPU są bardzo szybkie, więc podczas ich używania wąskim gardłem często staje się wczytywanie danych. W przewodniku po wydajności TPU znajdziesz narzędzia, które pomogą Ci wykryć wąskie gardła danych, oraz inne wskazówki dotyczące wydajności.
- Liczby int8 lub int16 są traktowane jako int32. TPU nie ma sprzętu do liczb całkowitych działającego na mniej niż 32 bitach.
- Niektóre operacje TensorFlow nie są obsługiwane. Lista jest dostępna tutaj. Dobra wiadomość jest taka, że to ograniczenie dotyczy tylko kodu trenującego, czyli przejścia w przód i w tył przez model. W potoku wprowadzania danych nadal możesz używać wszystkich operacji TensorFlow, ponieważ będą one wykonywane na procesorze.
tf.py_funcnie jest obsługiwany na TPU.
4. Wczytuję dane

Będziemy pracować ze zbiorem danych zawierającym zdjęcia kwiatów. Celem jest nauczenie się klasyfikowania ich w 5 rodzajach kwiatów. Wczytywanie danych odbywa się za pomocą interfejsu tf.data.Dataset API. Najpierw zapoznajmy się z interfejsem API.
Praktyczne
Otwórz ten notatnik, uruchom komórki (Shift-ENTER) i postępuj zgodnie z instrukcjami, gdy zobaczysz etykietę „WORK REQUIRED”.
Fun with tf.data.Dataset (playground).ipynb
Informacje dodatkowe
Informacje o zbiorze danych „kwiaty”
Zbiór danych jest podzielony na 5 folderów. Każdy folder zawiera kwiaty jednego rodzaju. Foldery mają nazwy: sunflowers, daisy, dandelion, tulips i roses. 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 szkoleniowych i oceniających. Po wczytaniu danych do zbioru danych interfejs API udostępnia wszystkie typowe funkcje przydatne w przypadku danych treningowych sieci neuronowych:
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 skuteczności i sprawdzone metody dotyczące zbiorów danych znajdziesz w tym artykule. Dokumentacja referencyjna jest dostępna tutaj.
Podstawy tf.data.Dataset
Dane zwykle pochodzą z wielu plików, w tym przypadku obrazów. 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 „mapujesz” funkcję na każdą nazwę pliku, która zwykle wczytuje i dekoduje plik do 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 uczeniu nadzorowanym 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. Otrzymasz wtedy zbiór danych krotek, a krotki będą zwracane podczas iteracji. Zwracane wartości to tensory TensorFlow gotowe do użycia przez model. Możesz wywołać funkcję .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:wczytywanie obrazów pojedynczo jest powolne!
W miarę iteracji tego zbioru danych zobaczysz, że możesz wczytywać około 1–2 obrazy na sekundę. To za wolno! Akceleratory sprzętowe, których będziemy używać do trenowania, mogą utrzymać wielokrotnie wyższą szybkość. W następnej sekcji dowiesz się, jak to osiągniemy.
Rozwiązanie
Oto notatnik z rozwiązaniem. Możesz z niej skorzystać, jeśli utkniesz w martwym punkcie.
Fun with tf.data.Dataset (solution).ipynb
Omówione zagadnienia
- 🤔 tf.data.Dataset.list_files
- 🤔 tf.data.Dataset.map
- 🤔 Zbiory danych krotek
- 😀 iterowanie po zbiorach danych;
Poświęć chwilę na przejrzenie tej listy kontrolnej.
5. Szybkie wczytywanie danych
Akceleratory sprzętowe Tensor Processing Unit (TPU), których będziemy używać w tym module, są bardzo szybkie. Często problemem jest dostarczanie im danych wystarczająco szybko, aby nie były bezczynne. Google Cloud Storage (GCS) może utrzymywać bardzo wysoką przepustowość, ale podobnie jak w przypadku wszystkich systemów pamięci w chmurze, nawiązanie połączenia wiąże się z pewnymi kosztami związanymi z ruchem sieciowym. Dlatego przechowywanie danych w tysiącach pojedynczych plików nie jest idealnym rozwiązaniem. Zgrupujemy je w mniejszej liczbie plików i wykorzystamy możliwości tf.data.Dataset, aby odczytywać dane z wielu plików równolegle.
Czytanie na głos
Kod, który wczytuje pliki obrazów, zmienia ich rozmiar na wspólny, a następnie zapisuje je w 16 plikach TFRecord, znajduje się w tym notatniku. Przejrzyj go szybko. Nie jest to konieczne, ponieważ w pozostałej części samouczka będą dostępne dane w odpowiednim formacie TFRecord.
Flower pictures to TFRecords.ipynb
Idealny układ danych zapewniający optymalną przepustowość GCS
Format pliku TFRecord
Preferowanym formatem plików do przechowywania danych w TensorFlow jest format TFRecord oparty na protobuf. Działają też inne formaty serializacji, ale zbiór danych z plików TFRecord możesz wczytać bezpośrednio, wpisując:
filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below
Aby uzyskać optymalną wydajność, zalecamy użycie bardziej złożonego kodu do odczytywania danych z wielu plików TFRecord jednocześnie. Ten kod będzie odczytywać dane z N plików równolegle i ignorować 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 dotycząca TFRecord
W plikach TFRecords można przechowywać 3 typy danych: ciągi bajtów (lista bajtów), 64-bitowe liczby całkowite i 32-bitowe liczby zmiennoprzecinkowe. Są one zawsze przechowywane jako listy, a pojedynczy element danych będzie listą o rozmiarze 1. Do zapisywania danych w plikach TFRecord możesz używać tych funkcji pomocniczych.
zapisywanie 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 pływające
def _float_feature(list_of_floats): # float32
return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))
zapisywanie pliku TFRecord przy użyciu powyższych funkcji pomocniczych;
# 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 odczytać dane z plików TFRecord, musisz najpierw zadeklarować układ przechowywanych rekordów. W deklaracji możesz uzyskać dostęp do dowolnego nazwanego pola jako listy o stałej lub 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
odczytywanie 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 rzadki, więc po dekodowaniu pliku TFRecord wymagany jest dodatkowy krok:
dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])
W TFRecords mogą też występować pola opcjonalne. Jeśli podczas odczytywania pola określisz wartość domyślną, w przypadku braku pola zostanie zwrócona wartość domyślna zamiast błędu.
tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional
Omówione zagadnienia
- 🤔 fragmentacja plików danych w celu szybkiego dostępu z GCS
- 😓 jak pisać pliki TFRecord. (Już zapomniałeś(-aś) składni? (OK, dodaj tę stronę do zakładek jako ściągę)
- 🤔 wczytywanie zbioru danych z TFRecords za pomocą TFRecordDataset
Poświęć chwilę na przejrzenie tej listy kontrolnej.
6. Gratulacje!
Możesz teraz przekazywać dane do TPU. Przejdź do następnego laboratorium
- [TO ĆWICZENIE] Potoki danych o szybkości TPU: tf.data.Dataset i TFRecords
- Pierwszy model Keras z uczeniem transferowym
- Konwolucyjne sieci neuronowe z użyciem Keras i TPU
- Nowoczesne sieci konwolucyjne, SqueezeNet i Xception z użyciem Keras i TPU
TPU w praktyce
TPU i GPU są dostępne na AI Platform w Google Cloud:
- Na maszynach wirtualnych do deep learningu
- W sekcji Notatniki w AI Platform
- W zadaniach trenowania w AI Platform
Na koniec dodamy, że chętnie poznamy Twoją opinię. Jeśli zauważysz w tym module coś nieprawidłowego lub uważasz, że można go ulepszyć, daj nam znać. Opinie można przesyłać za pomocą zgłoszeń w GitHub [link do opinii].

|
|

