Participe do Simpósio Women in ML em 7 de dezembro Inscreva-se agora

Noções básicas do TensorFlow

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Veja no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Este guia fornece uma visão geral rápida dos conceitos básicos do TensorFlow . Cada seção deste documento é uma visão geral de um tópico maior - você pode encontrar links para guias completos no final de cada seção.

O TensorFlow é uma plataforma de ponta a ponta para aprendizado de máquina. Ele suporta o seguinte:

  • Computação numérica baseada em matriz multidimensional (semelhante a NumPy .)
  • GPU e processamento distribuído
  • Diferenciação automática
  • Construção, treinamento e exportação de modelos
  • E mais

Tensores

O TensorFlow opera em matrizes ou tensores multidimensionais representados como objetos tf.Tensor . Aqui está um tensor bidimensional:

import tensorflow as tf

x = tf.constant([[1., 2., 3.],
                 [4., 5., 6.]])

print(x)
print(x.shape)
print(x.dtype)
tf.Tensor(
[[1. 2. 3.]
 [4. 5. 6.]], shape=(2, 3), dtype=float32)
(2, 3)
<dtype: 'float32'>

Os atributos mais importantes de um tf.Tensor são sua shape e dtype :

  • Tensor.shape : informa o tamanho do tensor ao longo de cada um de seus eixos.
  • Tensor.dtype : informa o tipo de todos os elementos no tensor.

O TensorFlow implementa operações matemáticas padrão em tensores, bem como muitas operações especializadas para aprendizado de máquina.

Por exemplo:

x + x
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ 2.,  4.,  6.],
       [ 8., 10., 12.]], dtype=float32)>
5 * x
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ 5., 10., 15.],
       [20., 25., 30.]], dtype=float32)>
x @ tf.transpose(x)
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[14., 32.],
       [32., 77.]], dtype=float32)>
tf.concat([x, x, x], axis=0)
<tf.Tensor: shape=(6, 3), dtype=float32, numpy=
array([[1., 2., 3.],
       [4., 5., 6.],
       [1., 2., 3.],
       [4., 5., 6.],
       [1., 2., 3.],
       [4., 5., 6.]], dtype=float32)>
tf.nn.softmax(x, axis=-1)
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[0.09003057, 0.24472848, 0.6652409 ],
       [0.09003057, 0.24472848, 0.6652409 ]], dtype=float32)>
tf.reduce_sum(x)
<tf.Tensor: shape=(), dtype=float32, numpy=21.0>

A execução de grandes cálculos na CPU pode ser lenta. Quando configurado corretamente, o TensorFlow pode usar hardware acelerador, como GPUs, para executar operações muito rapidamente.

if tf.config.list_physical_devices('GPU'):
  print("TensorFlow **IS** using the GPU")
else:
  print("TensorFlow **IS NOT** using the GPU")
TensorFlow **IS** using the GPU

Consulte o guia Tensor para obter detalhes.

Variáveis

Objetos tf.Tensor normais são imutáveis. Para armazenar pesos de modelo (ou outro estado mutável) no TensorFlow, use um tf.Variable .

var = tf.Variable([0.0, 0.0, 0.0])
var.assign([1, 2, 3])
<tf.Variable 'UnreadVariable' shape=(3,) dtype=float32, numpy=array([1., 2., 3.], dtype=float32)>
var.assign_add([1, 1, 1])
<tf.Variable 'UnreadVariable' shape=(3,) dtype=float32, numpy=array([2., 3., 4.], dtype=float32)>

Consulte o guia Variáveis para obter detalhes.

Diferenciação automática

A descida de gradiente e os algoritmos relacionados são a base do aprendizado de máquina moderno.

Para habilitar isso, o TensorFlow implementa a diferenciação automática (autodiff), que usa cálculo para calcular gradientes. Normalmente, você usará isso para calcular o gradiente do erro ou perda de um modelo em relação a seus pesos.

x = tf.Variable(1.0)

def f(x):
  y = x**2 + 2*x - 5
  return y
f(x)
<tf.Tensor: shape=(), dtype=float32, numpy=-2.0>

Em x = 1.0 , y = f(x) = (1**2 + 2*1 - 5) = -2 .

A derivada de y é y' = f'(x) = (2*x + 2) = 4 . O TensorFlow pode calcular isso automaticamente:

with tf.GradientTape() as tape:
  y = f(x)

g_x = tape.gradient(y, x)  # g(x) = dy/dx

g_x
<tf.Tensor: shape=(), dtype=float32, numpy=4.0>

Este exemplo simplificado leva apenas a derivada em relação a um único escalar ( x ), mas o TensorFlow pode calcular o gradiente em relação a qualquer número de tensores não escalares simultaneamente.

Consulte o guia Autodiff para obter detalhes.

Gráficos e tf.function

Embora você possa usar o TensorFlow interativamente como qualquer biblioteca Python, o TensorFlow também fornece ferramentas para:

  • Otimização de desempenho : para acelerar o treinamento e a inferência.
  • Exportar : para que você possa salvar seu modelo quando terminar o treinamento.

Eles exigem que você use tf.function para separar seu código Pure-TensorFlow do Python.

@tf.function
def my_func(x):
  print('Tracing.\n')
  return tf.reduce_sum(x)

A primeira vez que você executa o tf.function , embora ele seja executado em Python, ele captura um gráfico completo e otimizado representando os cálculos do TensorFlow feitos dentro da função.

x = tf.constant([1, 2, 3])
my_func(x)
Tracing.
<tf.Tensor: shape=(), dtype=int32, numpy=6>

Nas chamadas subsequentes, o TensorFlow executa apenas o gráfico otimizado, ignorando todas as etapas não relacionadas ao TensorFlow. Abaixo, observe que my_func não imprime rastreamento , pois print é uma função do Python, não uma função do TensorFlow.

x = tf.constant([10, 9, 8])
my_func(x)
<tf.Tensor: shape=(), dtype=int32, numpy=27>

Um gráfico pode não ser reutilizável para entradas com uma assinatura diferente ( shape e dtype ), portanto, um novo gráfico é gerado:

x = tf.constant([10.0, 9.1, 8.2], dtype=tf.float32)
my_func(x)
Tracing.
<tf.Tensor: shape=(), dtype=float32, numpy=27.3>

Esses gráficos capturados fornecem dois benefícios:

  • Em muitos casos, eles fornecem uma aceleração significativa na execução (embora não neste exemplo trivial).
  • Você pode exportar esses gráficos, usando tf.saved_model , para executar em outros sistemas como um servidor ou um dispositivo móvel , sem necessidade de instalação do Python.

Consulte Introdução aos gráficos para obter mais detalhes.

Módulos, camadas e modelos

tf.Module é uma classe para gerenciar seus objetos tf.Variable e os objetos tf.function que operam neles. A classe tf.Module é necessária para dar suporte a dois recursos significativos:

  1. Você pode salvar e restaurar os valores de suas variáveis ​​usando tf.train.Checkpoint . Isso é útil durante o treinamento, pois é rápido salvar e restaurar o estado de um modelo.
  2. Você pode importar e exportar os valores tf.Variable e os gráficos tf.function usando tf.saved_model . Isso permite que você execute seu modelo independentemente do programa Python que o criou.

Aqui está um exemplo completo de exportação de um objeto tf.Module simples:

class MyModule(tf.Module):
  def __init__(self, value):
    self.weight = tf.Variable(value)

  @tf.function
  def multiply(self, x):
    return x * self.weight
mod = MyModule(3)
mod.multiply(tf.constant([1, 2, 3]))
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([3, 6, 9], dtype=int32)>

Salve o Module :

save_path = './saved'
tf.saved_model.save(mod, save_path)
INFO:tensorflow:Assets written to: ./saved/assets
2022-01-19 02:29:48.135588: 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.

O SavedModel resultante é independente do código que o criou. Você pode carregar um SavedModel do Python, outras associações de linguagem ou TensorFlow Serving . Você também pode convertê-lo para ser executado com TensorFlow Lite ou TensorFlow JS .

reloaded = tf.saved_model.load(save_path)
reloaded.multiply(tf.constant([1, 2, 3]))
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([3, 6, 9], dtype=int32)>

As classes tf.keras.layers.Layer e tf.keras.Model construídas no tf.Module , fornecendo funcionalidades adicionais e métodos convenientes para construir, treinar e salvar modelos. Algumas delas são demonstradas na próxima seção.

Consulte Introdução aos módulos para obter detalhes.

Loops de treinamento

Agora junte tudo isso para construir um modelo básico e treiná-lo do zero.

Primeiro, crie alguns dados de exemplo. Isso gera uma nuvem de pontos que segue vagamente uma curva quadrática:

import matplotlib
from matplotlib import pyplot as plt

matplotlib.rcParams['figure.figsize'] = [9, 6]
x = tf.linspace(-2, 2, 201)
x = tf.cast(x, tf.float32)

def f(x):
  y = x**2 + 2*x - 5
  return y

y = f(x) + tf.random.normal(shape=[201])

plt.plot(x.numpy(), y.numpy(), '.', label='Data')
plt.plot(x, f(x),  label='Ground truth')
plt.legend();

png

Crie um modelo:

class Model(tf.keras.Model):
  def __init__(self, units):
    super().__init__()
    self.dense1 = tf.keras.layers.Dense(units=units,
                                        activation=tf.nn.relu,
                                        kernel_initializer=tf.random.normal,
                                        bias_initializer=tf.random.normal)
    self.dense2 = tf.keras.layers.Dense(1)

  def call(self, x, training=True):
    # For Keras layers/models, implement `call` instead of `__call__`.
    x = x[:, tf.newaxis]
    x = self.dense1(x)
    x = self.dense2(x)
    return tf.squeeze(x, axis=1)
model = Model(64)
plt.plot(x.numpy(), y.numpy(), '.', label='data')
plt.plot(x, f(x),  label='Ground truth')
plt.plot(x, model(x), label='Untrained predictions')
plt.title('Before training')
plt.legend();

png

Escreva um loop de treinamento básico:

variables = model.variables

optimizer = tf.optimizers.SGD(learning_rate=0.01)

for step in range(1000):
  with tf.GradientTape() as tape:
    prediction = model(x)
    error = (y-prediction)**2
    mean_error = tf.reduce_mean(error)
  gradient = tape.gradient(mean_error, variables)
  optimizer.apply_gradients(zip(gradient, variables))

  if step % 100 == 0:
    print(f'Mean squared error: {mean_error.numpy():0.3f}')
Mean squared error: 16.123
Mean squared error: 0.997
Mean squared error: 0.964
Mean squared error: 0.946
Mean squared error: 0.932
Mean squared error: 0.921
Mean squared error: 0.913
Mean squared error: 0.907
Mean squared error: 0.901
Mean squared error: 0.897
plt.plot(x.numpy(),y.numpy(), '.', label="data")
plt.plot(x, f(x),  label='Ground truth')
plt.plot(x, model(x), label='Trained predictions')
plt.title('After training')
plt.legend();

png

Isso está funcionando, mas lembre-se de que implementações de utilitários de treinamento comuns estão disponíveis no módulo tf.keras . Portanto, considere usá-los antes de escrever o seu próprio. Para começar, os métodos Model.compile e Model.fit implementam um loop de treinamento para você:

new_model = Model(64)
new_model.compile(
    loss=tf.keras.losses.MSE,
    optimizer=tf.optimizers.SGD(learning_rate=0.01))

history = new_model.fit(x, y,
                        epochs=100,
                        batch_size=32,
                        verbose=0)

model.save('./my_model')
INFO:tensorflow:Assets written to: ./my_model/assets
plt.plot(history.history['loss'])
plt.xlabel('Epoch')
plt.ylim([0, max(plt.ylim())])
plt.ylabel('Loss [Mean Squared Error]')
plt.title('Keras training progress');

png

Consulte Loops de treinamento básico e o guia Keras para obter mais detalhes.