Path: blob/master/site/pt-br/guide/tf_numpy.ipynb
25115 views
Copyright 2020 The TensorFlow Authors.
API NumPy no TensorFlow
Visão geral
O TensorFlow implementa um subconjunto da API NumPy, disponível como tf.experimental.numpy
. Isso permite a execução de código NumPy, acelerado pelo TensorFlow, ao mesmo tempo que permite acesso a todas as APIs do TensorFlow.
Configuração
Ativando o comportamento NumPy
Para usar tnp
como NumPy, ative o comportamento NumPy para o TensorFlow:
Essa chamada permite a promoção de tipos no TensorFlow e também altera a inferência de tipos, ao converter literais em tensores, para seguir mais estritamente o padrão NumPy.
Observação: esta chamada mudará o comportamento de todo o TensorFlow, não apenas do módulo tf.experimental.numpy
.
TensorFlow NumPy ND array
Uma instância de tf.experimental.numpy.ndarray
, chamada ND Array, representa um array multidimensional denso de um determinado dtype
colocado em um determinado dispositivo. É um alias para tf.Tensor
. Dê uma olhada na classe de ND array para métodos úteis como ndarray.T
, ndarray.reshape
, ndarray.ravel
e outros.
Primeiro crie um objeto ND array e, em seguida, chame métodos diferentes.
Promoção de tipos
Existem 4 opções para promoção de tipos no TensorFlow.
Por padrão, o TensorFlow gera erros em vez de promover tipos para operações de tipo misto.
A execução de
tf.numpy.experimental_enable_numpy_behavior()
faz o TensorFlow passar a usar as regras de promoção de tipos do {code}NumPy{/code} (descritas abaixo).Após o TensorFlow 2.15, há duas novas opções (veja Promoção de tipos TF NumPy para mais detalhes):
tf.numpy.experimental_enable_numpy_behavior(dtype_conversion_mode="all")
usa regras de promoção de tipos do Jax.tf.numpy.experimental_enable_numpy_behavior(dtype_conversion_mode="safe")
usa regras de promoção de tipos do Jax, mas não permite determinadas promoções inseguras.
Promoção de tipos NumPy
As APIs TensorFlow NumPy têm semântica bem definida para converter literais em ND arrays, bem como para realizar promoção de tipos em entradas de ND arrays. Veja np.result_type
para mais detalhes.
As APIs TensorFlow deixam as entradas tf.Tensor
inalteradas e não realizam promoção de tipo nelas, enquanto as APIs TensorFlow NumPy promovem todas as entradas de acordo com as regras de promoção de tipos do NumPy. No próximo exemplo, você realizará uma promoção de tipos. Primeiro, execute a adição nas entradas do ND array de diferentes tipos e observe os tipos de saída. Nenhuma dessas promoções de tipo seria permitida pelas APIs do TensorFlow.
Por fim, converta literais em ND arrays usando ndarray.asarray
e observe o tipo resultante.
Ao converter literais em ND arrays, o NumPy prefere tipos largos como tnp.int64
e tnp.float64
. Por outro lado, tf.convert_to_tensor
prefere os tipos tf.int32
e tf.float32
para converter constantes em tf.Tensor
. As APIs TensorFlow NumPy aderem ao comportamento NumPy para números inteiros. Quanto aos floats, o argumento prefer_float32
de experimental_enable_numpy_behavior
permite controlar se você prefere tf.float32
em vez de tf.float64
(o padrão é False
). Por exemplo:
Broadcasting
Semelhante ao TensorFlow, o NumPy define uma semântica rica para "broadcasting" de valores. Você pode consultar o guia de broadcasting do NumPy para obter mais informações e compará-lo com a semântica de broadcasting do TensorFlow.
Indexação
O NumPy define regras de indexação muito sofisticadas. Consulte o Guia de indexação NumPy. Preste atenção ao uso de ND arrays como índices no exemplo abaixo.
Modelo de exemplo
A seguir, você verá como criar um modelo e executar inferências nele. Este modelo simples aplica uma camada relu seguida por uma projeção linear. As seções posteriores mostrarão como calcular gradientes para este modelo usando GradientTape
do TensorFlow.
TensorFlow NumPy e NumPy
O TensorFlow NumPy implementa um subconjunto da especificação completa do NumPy. Embora mais símbolos devam ser adicionados ao longo do tempo, existem alguns recursos sistemáticos que não serão suportados num futuro próximo. Isto inclui o suporte à API NumPy C, integração com Swig, ordem de armazenamento no Fortran, visualizações e stride_tricks
e alguns dtype
(como np.recarray
e np.object
). Para mais detalhes, consulte a Documentação da API TensorFlow NumPy.
Interoperabilidade com o NumPy
Os ND arrays do TensorFlow podem interoperar com funções NumPy. Esses objetos implementam a interface __array__
. NumPy usa esta interface para converter argumentos de função em valores np.ndarray
antes de processá-los.
Da mesma forma, as funções TensorFlow NumPy podem aceitar entradas de diferentes tipos, incluindo np.ndarray
. Essas entradas são convertidas em um ND array ao chamar ndarray.asarray
nelas.
A conversão de um ND array de e para np.ndarray
pode acionar cópias de dados. Consulte a seção sobre cópias buffer para mais detalhes.
Cópias buffer
A mistura do TensorFlow NumPy com o código NumPy pode acionar cópias de dados. Isto ocorre porque o TensorFlow NumPy tem requisitos mais rigorosos de alinhamento de memória do que os do NumPy.
Quando um np.ndarray
é passado para o TensorFlow NumPy, ele verifica os requisitos de alinhamento e aciona uma cópia, se necessário. Ao passar um buffer de CPU ND array para o NumPy, geralmente o buffer satisfará os requisitos de alinhamento e o NumPy não precisará criar uma cópia.
ND arrays podem se referir a buffers colocados em dispositivos diferentes da memória local da CPU. Nesses casos, chamar uma função NumPy acionará cópias na rede ou dispositivo conforme necessário.
Diante disso, a mistura com chamadas de API NumPy geralmente deve ser feita com cautela e o usuário deve estar atento aos overheads gerais relacionados à cópia de dados. Intercalar chamadas do TensorFlow NumPy com chamadas do TensorFlow geralmente é seguro e evita a cópia de dados. Veja a seção sobre Interoperabilidade com o TensorFlow para obter detalhes.
Precedência de operadores
O TensorFlow NumPy define uma __array_priority__
maior que o do NumPy. Isto significa que para operadores envolvendo ND arrays e np.ndarray
, o primeiro terá precedência, ou seja, a entrada np.ndarray
será convertida num ND array e a implementação TensorFlow NumPy do operador será chamada.
TF NumPy e TensorFlow
O TensorFlow NumPy é construído com base no TensorFlow e, portanto, interopera perfeitamente com o TensorFlow.
tf.Tensor
e ND array
O ND array é um alias para tf.Tensor
, então obviamente eles podem ser misturados sem produzir cópias de dados.
Interoperabilidade com o TensorFlow
Um ND array pode ser passado para APIs do TensorFlow, já que o ND array é apenas um alias para tf.Tensor
. Conforme mencionado anteriormente, tal interoperação não faz cópias de dados, nem mesmo para dados colocados em aceleradores ou dispositivos remotos.
Por outro lado, os objetos tf.Tensor
podem ser passados para APIs tf.experimental.numpy
, sem a realização de cópias de dados.
Gradientes e Jacobianos: tf.GradientTape
O GradientTape do TensorFlow pode ser usado para retropropagação por meio do código TensorFlow e TensorFlow NumPy.
Use o modelo criado na seção Modelo de exemplo e calcule gradientes e jacobianos.
Compilação de rastreamento: tf.function
tf.function
do TensorFlow funciona "compilando o rastreamento" do código e, em seguida, otimizando esses rastreamentos para um desempenho muito mais rápido. Veja a Introdução a grafos e funções.
tf.function
também pode ser usada para otimizar o código TensorFlow NumPy. Aqui está um exemplo simples para demonstrar as acelerações. Observe que o corpo do código tf.function
inclui chamadas para APIs TensorFlow NumPy.
Vetorização: tf.vectorized_map
O TensorFlow tem suporte integrado para vetorização de loops paralelos, o que permite acelerações de uma a duas ordens de magnitude. Essas acelerações são acessíveis via API tf.vectorized_map
e também se aplicam a código TensorFlow NumPy.
Às vezes é útil calcular o gradiente de cada saída num lote em relação ao elemento de lote de entrada correspondente. Tal cálculo pode ser feito de forma eficiente usando tf.vectorized_map
conforme mostrado abaixo.
Posicionamento de dispositivos
O TensorFlow NumPy pode realizar operações em CPUs, GPUs, TPUs e dispositivos remotos. Ele usa os mecanismos padrão do TensorFlow para o posicionamento de dispositivos. Abaixo, um exemplo simples mostra como listar todos os dispositivos e, em seguida, aplicar alguma computação num dispositivo específico.
O TensorFlow também possui APIs para replicar a computação entre dispositivos e realizar reduções coletivas que não serão abordadas aqui.
Listando dispositivos
tf.config.list_logical_devices
e tf.config.list_physical_devices
podem ser usados para encontrar quais dispositivos usar.
Posicionando operações: tf.device
As operações podem ser colocadas num dispositivo chamando-o num escopo de tf.device
.
Copiando ND arrays entre dispositivos: tnp.copy
Uma chamada para tnp.copy
, colocada num determinado escopo de dispositivo, copiará os dados para esse dispositivo, a menos que os dados já estejam nesse dispositivo.
Comparações de desempenho
O TensorFlow NumPy usa kernels TensorFlow altamente otimizados que podem ser despachados em CPUs, GPUs e TPUs. O TensorFlow também realiza muitas otimizações de compilador, como fusão de operações, que se traduzem em melhorias de desempenho e uso de memória. Veja Otimização de grafos do TensorFlow com o Grappler para saber mais.
No entanto, o TensorFlow tem overheads gerais mais altas para operações de despacho em comparação com o NumPy. Para workloads compostas por pequenas operações (menos de 10 microssegundos), esses overheads podem dominar o tempo de execução e o NumPy pode garantir melhor desempenho. Para outros casos, o TensorFlow geralmente deve entregar um melhor desempenho.
Execute o benchmark abaixo para comparar o desempenho do NumPy com o TensorFlow NumPy para diferentes tamanhos de entrada.