Zobacz na TensorFlow.org | Uruchom w Google Colab | Wyświetl źródło na GitHub | Pobierz notatnik |
Zalecamy używanie tf.keras
jako wysokopoziomowego API do budowania sieci neuronowych. To powiedziawszy, większość interfejsów API TensorFlow nadaje się do użytku z szybkim wykonaniem.
import tensorflow as tf
print(tf.config.list_physical_devices('GPU'))
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
Warstwy: wspólne zestawy przydatnych operacji
W większości przypadków pisząc kod dla modeli uczenia maszynowego chcesz operować na wyższym poziomie abstrakcji niż pojedyncze operacje i manipulacje poszczególnymi zmiennymi.
Wiele modeli uczenia maszynowego można wyrazić jako skład i układanie stosunkowo prostych warstw, a TensorFlow zapewnia zarówno zestaw wielu typowych warstw, jak i łatwe sposoby na napisanie własnych warstw specyficznych dla aplikacji od podstaw lub jako skład istniejące warstwy.
TensorFlow zawiera pełne API Keras w pakiecie tf.keras, a warstwy Keras są bardzo przydatne podczas budowania własnych modeli.
# In the tf.keras.layers package, layers are objects. To construct a layer,
# simply construct the object. Most layers take as a first argument the number
# of output dimensions / channels.
layer = tf.keras.layers.Dense(100)
# The number of input dimensions is often unnecessary, as it can be inferred
# the first time the layer is used, but it can be provided if you want to
# specify it manually, which is useful in some complex models.
layer = tf.keras.layers.Dense(10, input_shape=(None, 5))
Pełną listę wcześniej istniejących warstw można zobaczyć w dokumentacji . Obejmuje Dense (warstwa w pełni połączona), Conv2D, LSTM, BatchNormalization, Dropout i wiele innych.
# To use a layer, simply call it.
layer(tf.zeros([10, 5]))
<tf.Tensor: shape=(10, 10), dtype=float32, numpy= array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>
# Layers have many useful methods. For example, you can inspect all variables
# in a layer using `layer.variables` and trainable variables using
# `layer.trainable_variables`. In this case a fully-connected layer
# will have variables for weights and biases.
layer.variables
[<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy= array([[-0.4370762 , 0.6231566 , -0.44082257, -0.48535 , 0.17860883, -0.521853 , -0.45774594, -0.5409817 , 0.29194772, -0.18690601], [ 0.3304953 , -0.27142242, -0.48322448, -0.19328138, -0.14415592, 0.05973059, 0.56227285, 0.5323917 , -0.4914217 , 0.62182254], [-0.5313885 , 0.54680306, 0.1632638 , -0.10741419, -0.04727739, -0.35414204, 0.07529551, -0.06515282, -0.19732419, 0.25217015], [ 0.49743277, 0.31172627, 0.04989761, 0.1200847 , 0.42642146, 0.5887727 , 0.5771937 , 0.08720696, 0.43024355, -0.17298424], [-0.07610255, 0.04131562, 0.3136508 , -0.6197298 , 0.2331146 , 0.04888463, -0.54215366, 0.41208786, 0.27439958, 0.08524591]], dtype=float32)>, <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]
# The variables are also accessible through nice accessors
layer.kernel, layer.bias
(<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy= array([[-0.4370762 , 0.6231566 , -0.44082257, -0.48535 , 0.17860883, -0.521853 , -0.45774594, -0.5409817 , 0.29194772, -0.18690601], [ 0.3304953 , -0.27142242, -0.48322448, -0.19328138, -0.14415592, 0.05973059, 0.56227285, 0.5323917 , -0.4914217 , 0.62182254], [-0.5313885 , 0.54680306, 0.1632638 , -0.10741419, -0.04727739, -0.35414204, 0.07529551, -0.06515282, -0.19732419, 0.25217015], [ 0.49743277, 0.31172627, 0.04989761, 0.1200847 , 0.42642146, 0.5887727 , 0.5771937 , 0.08720696, 0.43024355, -0.17298424], [-0.07610255, 0.04131562, 0.3136508 , -0.6197298 , 0.2331146 , 0.04888463, -0.54215366, 0.41208786, 0.27439958, 0.08524591]], dtype=float32)>, <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>)
Wdrażanie niestandardowych warstw
Najlepszym sposobem na zaimplementowanie własnej warstwy jest rozszerzenie klasy tf.keras.Layer i zaimplementowanie:
-
__init__
, gdzie możesz wykonać inicjalizację niezależną od danych wejściowych -
build
, gdzie znasz kształty tensorów wejściowych i możesz wykonać resztę inicjalizacji -
call
, gdzie wykonujesz obliczenia w przód
Zauważ, że nie musisz czekać na wywołanie build
, aby utworzyć zmienne, możesz je również utworzyć w __init__
. Jednak zaletą tworzenia ich w build
jest to, że umożliwia późne tworzenie zmiennych na podstawie kształtu danych wejściowych, na których warstwa będzie operować. Z drugiej strony tworzenie zmiennych w __init__
oznaczałoby, że kształty wymagane do utworzenia zmiennych będą musiały zostać wyraźnie określone.
class MyDenseLayer(tf.keras.layers.Layer):
def __init__(self, num_outputs):
super(MyDenseLayer, self).__init__()
self.num_outputs = num_outputs
def build(self, input_shape):
self.kernel = self.add_weight("kernel",
shape=[int(input_shape[-1]),
self.num_outputs])
def call(self, inputs):
return tf.matmul(inputs, self.kernel)
layer = MyDenseLayer(10)
_ = layer(tf.zeros([10, 5])) # Calling the layer `.builds` it.
print([var.name for var in layer.trainable_variables])
['my_dense_layer/kernel:0']
Ogólny kod jest łatwiejszy do odczytania i utrzymania, jeśli używa warstw standardowych, gdy tylko jest to możliwe, ponieważ inni czytelnicy będą zaznajomieni z zachowaniem warstw standardowych. Jeśli chcesz użyć warstwy, której nie ma w tf.keras.layers
, rozważ zgłoszenie problemu na githubie lub, jeszcze lepiej, wyślij nam pull request!
Modele: Komponowanie warstw
Wiele interesujących rzeczy podobnych do warstw w modelach uczenia maszynowego jest implementowanych przez komponowanie istniejących warstw. Na przykład, każdy blok rezydualny w resecie jest kompozycją splotów, normalizacji wsadowych i skrótu. Warstwy mogą być zagnieżdżane wewnątrz innych warstw.
Zazwyczaj dziedziczysz po keras.Model
, gdy potrzebujesz metod modelu, takich jak: Model.fit
, Model.evaluate
i Model.save
(szczegóły można znaleźć w sekcji Niestandardowe warstwy i modele Keras ).
Inną funkcją oferowaną przez keras.Model
(zamiast keras.layers.Layer
) jest to, że oprócz śledzenia zmiennych, keras.Model
śledzi również swoje warstwy wewnętrzne, co ułatwia ich kontrolę.
Na przykład tutaj jest blok ResNet:
class ResnetIdentityBlock(tf.keras.Model):
def __init__(self, kernel_size, filters):
super(ResnetIdentityBlock, self).__init__(name='')
filters1, filters2, filters3 = filters
self.conv2a = tf.keras.layers.Conv2D(filters1, (1, 1))
self.bn2a = tf.keras.layers.BatchNormalization()
self.conv2b = tf.keras.layers.Conv2D(filters2, kernel_size, padding='same')
self.bn2b = tf.keras.layers.BatchNormalization()
self.conv2c = tf.keras.layers.Conv2D(filters3, (1, 1))
self.bn2c = tf.keras.layers.BatchNormalization()
def call(self, input_tensor, training=False):
x = self.conv2a(input_tensor)
x = self.bn2a(x, training=training)
x = tf.nn.relu(x)
x = self.conv2b(x)
x = self.bn2b(x, training=training)
x = tf.nn.relu(x)
x = self.conv2c(x)
x = self.bn2c(x, training=training)
x += input_tensor
return tf.nn.relu(x)
block = ResnetIdentityBlock(1, [1, 2, 3])
_ = block(tf.zeros([1, 2, 3, 3]))
block.layers
[<keras.layers.convolutional.Conv2D at 0x7fc7e439bf90>, <keras.layers.normalization.batch_normalization.BatchNormalization at 0x7fc7dc1e5dd0>, <keras.layers.convolutional.Conv2D at 0x7fc7dc1a1cd0>, <keras.layers.normalization.batch_normalization.BatchNormalization at 0x7fc7dc12c490>, <keras.layers.convolutional.Conv2D at 0x7fc7dc12c8d0>, <keras.layers.normalization.batch_normalization.BatchNormalization at 0x7fc7dc12cf50>]
len(block.variables)
18
block.summary()
Model: "" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) multiple 4 batch_normalization (BatchN multiple 4 ormalization) conv2d_1 (Conv2D) multiple 4 batch_normalization_1 (Batc multiple 8 hNormalization) conv2d_2 (Conv2D) multiple 9 batch_normalization_2 (Batc multiple 12 hNormalization) ================================================================= Total params: 41 Trainable params: 29 Non-trainable params: 12 _________________________________________________________________
Jednak często modele składające się z wielu warstw nazywają po prostu jedną warstwą po drugiej. Można to zrobić w bardzo małym kodzie za pomocą tf.keras.Sequential
:
my_seq = tf.keras.Sequential([tf.keras.layers.Conv2D(1, (1, 1),
input_shape=(
None, None, 3)),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(2, 1,
padding='same'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Conv2D(3, (1, 1)),
tf.keras.layers.BatchNormalization()])
my_seq(tf.zeros([1, 2, 3, 3]))
<tf.Tensor: shape=(1, 2, 3, 3), dtype=float32, numpy= array([[[[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]]], dtype=float32)>
my_seq.summary()
Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_3 (Conv2D) (None, None, None, 1) 4 batch_normalization_3 (Batc (None, None, None, 1) 4 hNormalization) conv2d_4 (Conv2D) (None, None, None, 2) 4 batch_normalization_4 (Batc (None, None, None, 2) 8 hNormalization) conv2d_5 (Conv2D) (None, None, None, 3) 9 batch_normalization_5 (Batc (None, None, None, 3) 12 hNormalization) ================================================================= Total params: 41 Trainable params: 29 Non-trainable params: 12 _________________________________________________________________
Następne kroki
Teraz możesz wrócić do poprzedniego notatnika i dostosować przykład regresji liniowej, aby użyć warstw i modeli w celu uzyskania lepszej struktury.