Podstawowe pętle treningowe

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

W poprzednich przewodnikach poznałeś tensory , zmienne , taśmę gradientową i moduły . W tym przewodniku dopasujesz je wszystkie, aby trenować modele.

TensorFlow zawiera również tf.Keras API , wysokopoziomowy interfejs API sieci neuronowej, który zapewnia przydatne abstrakcje w celu ograniczenia schematu. Jednak w tym poradniku użyjesz podstawowych klas.

Ustawiać

import tensorflow as tf

import matplotlib.pyplot as plt

colors = plt.rcParams['axes.prop_cycle'].by_key()['color']

Rozwiązywanie problemów z uczeniem maszynowym

Rozwiązanie problemu z uczeniem maszynowym zwykle składa się z następujących kroków:

  • Uzyskaj dane treningowe.
  • Zdefiniuj model.
  • Zdefiniuj funkcję straty.
  • Przejrzyj dane treningowe, obliczając stratę z idealnej wartości
  • Oblicz gradienty dla tej straty i użyj optymalizatora , aby dopasować zmienne do danych.
  • Oceń swoje wyniki.

W celach ilustracyjnych w tym przewodniku opracujesz prosty model liniowy \(f(x) = x * W + b\), który ma dwie zmienne: \(W\) (wagi) i \(b\) (bias).

Jest to najbardziej podstawowy problem z uczeniem maszynowym: Biorąc pod uwagę \(x\) i \(y\), spróbuj znaleźć nachylenie i przesunięcie linii za pomocą prostej regresji liniowej .

Dane

Uczenie nadzorowane wykorzystuje dane wejściowe (zwykle oznaczane jako x ) i wyniki (oznaczane jako y , często nazywane etykietami ). Celem jest uczenie się na podstawie sparowanych danych wejściowych i wyjściowych, aby można było przewidzieć wartość danych wyjściowych z danych wejściowych.

Każde wejście danych w TensorFlow jest prawie zawsze reprezentowane przez tensor i często jest wektorem. W nadzorowanym treningu wyjście (lub wartość, którą chcesz przewidzieć) jest również tensorem.

Oto niektóre dane zsyntetyzowane przez dodanie szumu gaussowskiego (normalnego) do punktów wzdłuż linii.

# The actual line
TRUE_W = 3.0
TRUE_B = 2.0

NUM_EXAMPLES = 201

# A vector of random x values
x = tf.linspace(-2,2, NUM_EXAMPLES)
x = tf.cast(x, tf.float32)

def f(x):
  return x * TRUE_W + TRUE_B

# Generate some noise
noise = tf.random.normal(shape=[NUM_EXAMPLES])

# Calculate y
y = f(x) + noise
# Plot all the data
plt.plot(x, y, '.')
plt.show()

png

Tensory są zwykle gromadzone w partiach lub grupach wejść i wyjść ułożonych razem. Grupowanie może przynieść pewne korzyści szkoleniowe i dobrze współpracuje z akceleratorami i obliczeniami wektorowymi. Biorąc pod uwagę, jak mały jest ten zestaw danych, możesz traktować cały zestaw danych jako pojedynczą partię.

Zdefiniuj model

Użyj tf.Variable do reprezentowania wszystkich wag w modelu. tf.Variable przechowuje wartość i w razie potrzeby udostępnia ją w postaci tensorowej. Więcej informacji znajdziesz w przewodniku po zmiennych .

Użyj tf.Module do hermetyzacji zmiennych i obliczeń. Możesz użyć dowolnego obiektu Pythona, ale w ten sposób można go łatwo zapisać.

Tutaj definiujesz zarówno w , jak i b jako zmienne.

class MyModel(tf.Module):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)
    # Initialize the weights to `5.0` and the bias to `0.0`
    # In practice, these should be randomly initialized
    self.w = tf.Variable(5.0)
    self.b = tf.Variable(0.0)

  def __call__(self, x):
    return self.w * x + self.b

model = MyModel()

# List the variables tf.modules's built-in variable aggregation.
print("Variables:", model.variables)

# Verify the model works
assert model(3.0).numpy() == 15.0
Variables: (<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=0.0>, <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=5.0>)
2021-12-08 17:11:44.542944: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.

Początkowe zmienne są tutaj ustawione w ustalony sposób, ale Keras jest dostarczany z dowolnym z wielu inicjatorów , których można użyć, z resztą Keras lub bez.

Zdefiniuj funkcję straty

Funkcja straty mierzy, jak dobrze dane wyjściowe modelu dla danego wejścia odpowiadają docelowym wynikom. Celem jest zminimalizowanie tej różnicy podczas treningu. Zdefiniuj standardową stratę L2, znaną również jako błąd „średniokwadratowy”:

# This computes a single loss value for an entire batch
def loss(target_y, predicted_y):
  return tf.reduce_mean(tf.square(target_y - predicted_y))

Przed trenowaniem modelu możesz zwizualizować wartość straty, wykreślając prognozy modelu na czerwono, a dane szkoleniowe na niebiesko:

plt.plot(x, y, '.', label="Data")
plt.plot(x, f(x), label="Ground truth")
plt.plot(x, model(x), label="Predictions")
plt.legend()
plt.show()

print("Current loss: %1.6f" % loss(y, model(x)).numpy())

png

Current loss: 10.301712

Zdefiniuj pętlę treningową

Pętla treningowa polega na wielokrotnym wykonywaniu trzech zadań w kolejności:

  • Wysyłanie partii danych wejściowych przez model w celu wygenerowania danych wyjściowych
  • Obliczanie straty poprzez porównanie wyjść z wyjściem (lub etykietą)
  • Używanie taśmy gradientowej do znajdowania gradientów
  • Optymalizacja zmiennych za pomocą tych gradientów

W tym przykładzie model można trenować za pomocą funkcji gradientu .

W tf.keras.optimizers znajduje się wiele wariantów schematu zejścia gradientowego. Ale w duchu budowania od pierwszych zasad, tutaj samodzielnie zaimplementujesz podstawową matematykę za pomocą tf.GradientTape do automatycznego różnicowania i tf.assign_sub do dekrementacji wartości (która łączy tf.assign i tf.sub ):

# Given a callable model, inputs, outputs, and a learning rate...
def train(model, x, y, learning_rate):

  with tf.GradientTape() as t:
    # Trainable variables are automatically tracked by GradientTape
    current_loss = loss(y, model(x))

  # Use GradientTape to calculate the gradients with respect to W and b
  dw, db = t.gradient(current_loss, [model.w, model.b])

  # Subtract the gradient scaled by the learning rate
  model.w.assign_sub(learning_rate * dw)
  model.b.assign_sub(learning_rate * db)

Aby przyjrzeć się treningowi, możesz wysłać tę samą partię x i y przez pętlę treningową i zobaczyć, jak ewoluują W i b .

model = MyModel()

# Collect the history of W-values and b-values to plot later
weights = []
biases = []
epochs = range(10)

# Define a training loop
def report(model, loss):
  return f"W = {model.w.numpy():1.2f}, b = {model.b.numpy():1.2f}, loss={current_loss:2.5f}"


def training_loop(model, x, y):

  for epoch in epochs:
    # Update the model with the single giant batch
    train(model, x, y, learning_rate=0.1)

    # Track this before I update
    weights.append(model.w.numpy())
    biases.append(model.b.numpy())
    current_loss = loss(y, model(x))

    print(f"Epoch {epoch:2d}:")
    print("    ", report(model, current_loss))

Zrób szkolenie

current_loss = loss(y, model(x))

print(f"Starting:")
print("    ", report(model, current_loss))

training_loop(model, x, y)
Starting:
     W = 5.00, b = 0.00, loss=10.30171
Epoch  0:
     W = 4.46, b = 0.40, loss=10.30171
Epoch  1:
     W = 4.06, b = 0.72, loss=10.30171
Epoch  2:
     W = 3.77, b = 0.97, loss=10.30171
Epoch  3:
     W = 3.56, b = 1.18, loss=10.30171
Epoch  4:
     W = 3.40, b = 1.34, loss=10.30171
Epoch  5:
     W = 3.29, b = 1.47, loss=10.30171
Epoch  6:
     W = 3.21, b = 1.58, loss=10.30171
Epoch  7:
     W = 3.15, b = 1.66, loss=10.30171
Epoch  8:
     W = 3.10, b = 1.73, loss=10.30171
Epoch  9:
     W = 3.07, b = 1.78, loss=10.30171

Wykreśl ewolucję wag w czasie:

plt.plot(epochs, weights, label='Weights', color=colors[0])
plt.plot(epochs, [TRUE_W] * len(epochs), '--',
         label = "True weight", color=colors[0])

plt.plot(epochs, biases, label='bias', color=colors[1])
plt.plot(epochs, [TRUE_B] * len(epochs), "--",
         label="True bias", color=colors[1])

plt.legend()
plt.show()

png

Wizualizuj, jak działa wytrenowany model

plt.plot(x, y, '.', label="Data")
plt.plot(x, f(x), label="Ground truth")
plt.plot(x, model(x), label="Predictions")
plt.legend()
plt.show()

print("Current loss: %1.6f" % loss(model(x), y).numpy())

png

Current loss: 0.897898

To samo rozwiązanie, ale z Keras

Warto skontrastować powyższy kod z jego odpowiednikiem w Keras.

Definiowanie modelu wygląda dokładnie tak samo, jeśli podklasa tf.keras.Model . Pamiętaj, że modele Keras dziedziczą ostatecznie z modułu.

class MyModelKeras(tf.keras.Model):
  def __init__(self, **kwargs):
    super().__init__(**kwargs)
    # Initialize the weights to `5.0` and the bias to `0.0`
    # In practice, these should be randomly initialized
    self.w = tf.Variable(5.0)
    self.b = tf.Variable(0.0)

  def call(self, x):
    return self.w * x + self.b

keras_model = MyModelKeras()

# Reuse the training loop with a Keras model
training_loop(keras_model, x, y)

# You can also save a checkpoint using Keras's built-in support
keras_model.save_weights("my_checkpoint")
Epoch  0:
     W = 4.46, b = 0.40, loss=10.30171
Epoch  1:
     W = 4.06, b = 0.72, loss=10.30171
Epoch  2:
     W = 3.77, b = 0.97, loss=10.30171
Epoch  3:
     W = 3.56, b = 1.18, loss=10.30171
Epoch  4:
     W = 3.40, b = 1.34, loss=10.30171
Epoch  5:
     W = 3.29, b = 1.47, loss=10.30171
Epoch  6:
     W = 3.21, b = 1.58, loss=10.30171
Epoch  7:
     W = 3.15, b = 1.66, loss=10.30171
Epoch  8:
     W = 3.10, b = 1.73, loss=10.30171
Epoch  9:
     W = 3.07, b = 1.78, loss=10.30171

Zamiast pisać nowe pętle szkoleniowe za każdym razem, gdy tworzysz model, możesz użyć wbudowanych funkcji Keras jako skrótu. Może to być przydatne, gdy nie chcesz pisać ani debugować pętli szkoleniowych Pythona.

Jeśli to zrobisz, będziesz musiał użyć model.compile() do ustawienia parametrów i model.fit() do trenowania. Użycie implementacji Keras utraty L2 i spadku gradientu może być mniej kodu, ponownie jako skrótu. Straty Keras i optymalizatory mogą być również używane poza tymi funkcjami wygody, a poprzedni przykład mógł ich użyć.

keras_model = MyModelKeras()

# compile sets the training parameters
keras_model.compile(
    # By default, fit() uses tf.function().  You can
    # turn that off for debugging, but it is on now.
    run_eagerly=False,

    # Using a built-in optimizer, configuring as an object
    optimizer=tf.keras.optimizers.SGD(learning_rate=0.1),

    # Keras comes with built-in MSE error
    # However, you could use the loss function
    # defined above
    loss=tf.keras.losses.mean_squared_error,
)

Keras fit oczekuje danych wsadowych lub pełnego zestawu danych jako tablicy NumPy. Tablice NumPy są dzielone na partie i domyślnie mają rozmiar 32.

W takim przypadku, aby dopasować zachowanie pętli odręcznej, należy przekazać x jako pojedynczą partię o rozmiarze 1000.

print(x.shape[0])
keras_model.fit(x, y, epochs=10, batch_size=1000)
201
Epoch 1/10
1/1 [==============================] - 0s 242ms/step - loss: 10.3017
Epoch 2/10
1/1 [==============================] - 0s 3ms/step - loss: 6.3148
Epoch 3/10
1/1 [==============================] - 0s 3ms/step - loss: 4.0341
Epoch 4/10
1/1 [==============================] - 0s 3ms/step - loss: 2.7191
Epoch 5/10
1/1 [==============================] - 0s 3ms/step - loss: 1.9548
Epoch 6/10
1/1 [==============================] - 0s 2ms/step - loss: 1.5068
Epoch 7/10
1/1 [==============================] - 0s 3ms/step - loss: 1.2422
Epoch 8/10
1/1 [==============================] - 0s 2ms/step - loss: 1.0845
Epoch 9/10
1/1 [==============================] - 0s 2ms/step - loss: 0.9899
Epoch 10/10
1/1 [==============================] - 0s 3ms/step - loss: 0.9327
<keras.callbacks.History at 0x7f02ad940050>

Zauważ, że Keras wypisuje stratę po treningu, a nie przed, więc pierwsza strata wydaje się mniejsza, ale poza tym pokazuje to zasadniczo tę samą wydajność treningową.

Następne kroki

W tym przewodniku zobaczyłeś, jak używać podstawowych klas tensorów, zmiennych, modułów i taśmy gradientowej do budowania i trenowania modelu, a także jak te pomysły mapują się na Keras.

Jest to jednak niezwykle prosty problem. Aby uzyskać bardziej praktyczne wprowadzenie, zobacz Przewodnik dotyczący szkolenia niestandardowego .

Więcej informacji na temat korzystania z wbudowanych pętli treningowych Keras można znaleźć w tym przewodniku . Więcej informacji o pętlach treningowych i Keras znajdziesz w tym przewodniku . Aby napisać niestandardowe rozproszone pętle szkoleniowe, zapoznaj się z tym przewodnikiem .