Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/guide/tensor.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Introdução aos tensores

import tensorflow as tf import numpy as np

Tensores são vetores multidimensionais com um tipo uniforme (chamado dtype). Você pode ver todos os dtypes suportados em tf.dtypes.DType.

Se você estiver familiarizado com NumPy{:.external}, os tensores são (mais ou menos) como os np.arrays.

Todos os tensores são imutáveis ​​como números e strings do Python: você nunca pode atualizar o conteúdo de um tensor, apenas criar um novo.

Fundamentos

Primeiro, crie alguns tensores básicos.

Eis um "escalar", ou tensor de "posto 0". Um escalar contém um único valor e nenhum "eixo" (axis).

# This will be an int32 tensor by default; see "dtypes" below. rank_0_tensor = tf.constant(4) print(rank_0_tensor)

Um "vetor", ou tensor de "posto 1", é como uma lista de valores. Um vetor tem um eixo:

# Let's make this a float tensor. rank_1_tensor = tf.constant([2.0, 3.0, 4.0]) print(rank_1_tensor)

Uma "matriz", ou tensor de "posto 2" tem dois eixos:

# If you want to be specific, you can set the dtype (see below) at creation time rank_2_tensor = tf.constant([[1, 2], [3, 4], [5, 6]], dtype=tf.float16) print(rank_2_tensor)
Um escalar: formato: [] Um vetor, formato: [3] Uma matriz, formato: [3, 2]
Um escalar - o número 4
A linha com 3 seções 3, cada qual contendo um número. Uma grade 3x2, com cada célula contendo um número.

Tensores podem ter mais eixos (também chamados de dimensões). Eis aqui um tensor com três eixos:

# There can be an arbitrary number of # axes (sometimes called "dimensions") rank_3_tensor = tf.constant([ [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]], [[10, 11, 12, 13, 14], [15, 16, 17, 18, 19]], [[20, 21, 22, 23, 24], [25, 26, 27, 28, 29]],]) print(rank_3_tensor)

Há diversas maneiras de visualizar um tensor com mais de dois eixos.

Um tensor de 3 eixos, formato: [3, 2, 5]

Você pode converter um tensor para um array NumPy usando np.array ou o método tensor.numpy:

np.array(rank_2_tensor)
rank_2_tensor.numpy()

Os tensores geralmente contêm floats e ints, mas podem também conter muitos outros tipos, incluindo:

  • números complexos

  • strings

A classe base tf.Tensor requer que os tensores sejam "retangulares", ou seja, que ao longo de cada eixo, cada elemento tenha o mesmo tamanho. No entanto, existem tipos especializados de tensores que podem lidar com diferentes formatos:

Você pode realizar matemática básica com tensores, inclusive adição, multiplicação elemento a elemento e multiplicação matricial.

a = tf.constant([[1, 2], [3, 4]]) b = tf.constant([[1, 1], [1, 1]]) # Could have also said `tf.ones([2,2], dtype=tf.int32)` print(tf.add(a, b), "\n") print(tf.multiply(a, b), "\n") print(tf.matmul(a, b), "\n")
print(a + b, "\n") # element-wise addition print(a * b, "\n") # element-wise multiplication print(a @ b, "\n") # matrix multiplication

Tensores são usados ​​em todos os tipos de operações (ou "ops").

c = tf.constant([[4.0, 5.0], [10.0, 1.0]]) # Find the largest value print(tf.reduce_max(c)) # Find the index of the largest value print(tf.math.argmax(c)) # Compute the softmax print(tf.nn.softmax(c))

Observação: normalmente, em qualquer lugar onde uma função do TensorFlow aceite um Tensor como entrada, essa função também aceitará qualquer coisa que possa ser convertida num Tensor usando tf.convert_to_tensor. Veja abaixo um exemplo.

tf.convert_to_tensor([1,2,3])
tf.reduce_max([1,2,3])
tf.reduce_max(np.array([1,2,3]))

Sobre formatos

Os tensores têm formatos. Eis um breve glossário:

  • Formato: O comprimento (número de elementos) de cada um dos eixos de um tensor.

  • Posto: Número de eixos tensores. Um escalar tem posto 0, um vetor tem posto 1, uma matriz tem posto 2.

  • Eixo ou Dimensão: Uma dimensão específica de um tensor.

  • Tamanho: O número total de itens no tensor, o produto dos elementos do vetor de formato.

Observação: Embora você possa ver alguém se referir a um "tensor de duas dimensões", um tensor de posto 2 geralmente não descreve um espaço 2D.

Os objetos tensores e tf.TensorShape têm propriedades convenientes para acessá-los:

rank_4_tensor = tf.zeros([3, 2, 4, 5])
Um tensor de posto 4, formato: [3, 2, 4, 5]
O formato de um tensor é como um vetor. Um tensor de 4 eixos
print("Type of every element:", rank_4_tensor.dtype) print("Number of axes:", rank_4_tensor.ndim) print("Shape of tensor:", rank_4_tensor.shape) print("Elements along axis 0 of tensor:", rank_4_tensor.shape[0]) print("Elements along the last axis of tensor:", rank_4_tensor.shape[-1]) print("Total number of elements (3*2*4*5): ", tf.size(rank_4_tensor).numpy())

Mas observe que os atributos Tensor.ndim e Tensor.shape não retornam objetos Tensor. Se você precisar de um Tensor use a função tf.rank ou tf.shape. Essa diferença é sutil, mas pode ser importante ao construir grafos (posteriormente).

tf.rank(rank_4_tensor)
tf.shape(rank_4_tensor)

Embora frequentemente nos referimos ao eixos pelos seus índices, você deve sempre acompanhar o significado de cada um. Freqüentemente, os eixos são ordenados de global para local: primeiro o eixo do lote, seguido pelas dimensões espaciais e por último as características de cada local. Dessa forma, os vetores de características serão regiões contíguas da memória.

Ordem típica dos eixos
Acompanhe o que é cada eixo. Um tensor de 4 eixos talvez seja: Lote, Largura, Altura, Características

Indexação

Indexação de eixo único

O TensorFlow segue as regras de indexação padrão do Python, que são semelhantes à indexação de uma lista ou string em Python{:.external}, e as regras básicas para indexação do NumPy.

  • índices começam em 0

  • índices negativos contam de trás para frente a partir do final

  • dois pontos (:) são usados ​​para separar fatias: start:stop:step

rank_1_tensor = tf.constant([0, 1, 1, 2, 3, 5, 8, 13, 21, 34]) print(rank_1_tensor.numpy())

A indexação com um escalar remove o eixo:

print("First:", rank_1_tensor[0].numpy()) print("Second:", rank_1_tensor[1].numpy()) print("Last:", rank_1_tensor[-1].numpy())

A indexação com uma fatia : mantém o eixo:

print("Everything:", rank_1_tensor[:].numpy()) print("Before 4:", rank_1_tensor[:4].numpy()) print("From 4 to the end:", rank_1_tensor[4:].numpy()) print("From 2, before 7:", rank_1_tensor[2:7].numpy()) print("Every other item:", rank_1_tensor[::2].numpy()) print("Reversed:", rank_1_tensor[::-1].numpy())

Indexação multieixo

Tensores de posto mais alto são indexados passando múltiplos índices.

As mesmas regras do caso de eixo único aplicam-se a cada eixo independentemente.

print(rank_2_tensor.numpy())

Passando um número inteiro para cada índice, o resultado será um escalar.

# Pull out a single value from a 2-rank tensor print(rank_2_tensor[1, 1].numpy())

Você pode indexar usando qualquer combinação de números inteiros e fatias:

# Get row and column tensors print("Second row:", rank_2_tensor[1, :].numpy()) print("Second column:", rank_2_tensor[:, 1].numpy()) print("Last row:", rank_2_tensor[-1, :].numpy()) print("First item in last column:", rank_2_tensor[0, -1].numpy()) print("Skip the first row:") print(rank_2_tensor[1:, :].numpy(), "\n")

Eis um exemplo com um tensor de 3 eixos:

print(rank_3_tensor[:, :, 4])
Selecionando a última característica em todos os locais em cada exemplo do lote
Um tensor 3x2x5 com todos os valores no índice 4 do último eixo selecionado. Os valores selecionados empacotados num tensor de 2 eixos.

Leia o guia de divisão de tensores para saber como aplicar a indexação para manipular elementos individuais em seus tensores.

Manipulação de formatos

A alteração do formato de um tensor é de grande utilidade.

# Shape returns a `TensorShape` object that shows the size along each axis x = tf.constant([[1], [2], [3]]) print(x.shape)
# You can convert this object into a Python list, too print(x.shape.as_list())

Você pode mudar o formato de um tensor para que ele tenha um novo formato. A operação tf.reshape faz isso de forma rápida e barata porque os dados subjacentes não precisam ser duplicados.

# You can reshape a tensor to a new shape. # Note that you're passing in a list reshaped = tf.reshape(x, [1, 3])
print(x.shape) print(reshaped.shape)

Os dados mantêm seu layout na memória e um novo tensor é criado, com o formato solicitado, apontando para os mesmos dados. O TensorFlow usa ordenação de memória "linha principal" (row-major) no estilo C, onde o incremento do índice mais à direita corresponde a uma única etapa na memória.

print(rank_3_tensor)

Se você achatar um tensor, poderá ver em que ordem ele está disposto na memória.

# A `-1` passed in the `shape` argument says "Whatever fits". print(tf.reshape(rank_3_tensor, [-1]))

Normalmente, o único uso razoável de tf.reshape é combinar ou dividir eixos adjacentes (ou adicionar/remover valores 1).

Para este tensor 3x2x5, alterar o formato para (3x2)x5 ou 3x(2x5) são coisas razoáveis ​​a serem feitas, já que as fatias não se misturam:

print(tf.reshape(rank_3_tensor, [3*2, 5]), "\n") print(tf.reshape(rank_3_tensor, [3, -1]))
Algumas boas alterações de formato.
Um tensor 3x2x5 Os mesmos dados com formato alterado para (3x2)x5 Os mesmos dados com formato alterado para 3x(2x5)

A alteração de formato "funcionará" para qualquer novo formato com o mesmo número total de elementos, mas não fará nada de útil se você não respeitar a ordem dos eixos.

Trocar eixos em tf.reshape não funciona; você precisa de tf.transpose para isso.

# Bad examples: don't do this # You can't reorder axes with reshape. print(tf.reshape(rank_3_tensor, [2, 3, 5]), "\n") # This is a mess print(tf.reshape(rank_3_tensor, [5, 6]), "\n") # This doesn't work at all try: tf.reshape(rank_3_tensor, [7, -1]) except Exception as e: print(f"{type(e).__name__}: {e}")
Algumas alterações de formato ruins.
Você não pode reordenar eixos, use tf.transpose para isso Qualquer coisa que misture as fatias de dados provavelmente está errada. O novo formato deve caber de forma exata.

Você poderá se deparar com formatos não totalmente especificados. Ou o formato contém um None (o comprimento do eixo é desconhecido) ou todo o formato é None (o posto do tensor é desconhecido).

Com exceção de tf.RaggedTensor, esses formatos ocorrerão apenas no contexto das APIs simbólicas de construção de grafos do TensorFlow:

Mais sobre DTypes

Para inspecionar o tipo de dados de um tf.Tensor use a propriedade Tensor.dtype.

Ao criar um tf.Tensor a partir de um objeto Python, você pode opcionalmente especificar o tipo de dados.

Se você não fizer isso, o TensorFlow escolherá um tipo de dados que possa representar seus dados. O TensorFlow converte números inteiros do Python em tf.int32 e números de ponto flutuante do Python em tf.float32. Caso contrário, o TensorFlow usará as mesmas regras que o NumPy usa ao converter em arrays.

Você pode fazer um cast de um tipo para outro.

the_f64_tensor = tf.constant([2.2, 3.3, 4.4], dtype=tf.float64) the_f16_tensor = tf.cast(the_f64_tensor, dtype=tf.float16) # Now, cast to an uint8 and lose the decimal precision the_u8_tensor = tf.cast(the_f16_tensor, dtype=tf.uint8) print(the_u8_tensor)

Broadcasting

Broadcasting é um conceito emprestado do recurso equivalente em NumPy{:.external}. Em suma, sob certas condições, tensores menores são "esticados" automaticamente para caber em tensores maiores ao executar operações combinadas neles.

O caso mais simples e comum é quando você tenta multiplicar ou adicionar um tensor a um escalar. Nesse caso, é feito o broadcast do escalar para que ele tenha o mesmo formato do outro argumento.

x = tf.constant([1, 2, 3]) y = tf.constant(2) z = tf.constant([2, 2, 2]) # All of these are the same computation print(tf.multiply(x, 2)) print(x * y) print(x * z)

Da mesma forma, eixos com comprimento 1 podem ser esticados para corresponder aos outros argumentos. Ambos os argumentos podem ser esticados na mesma computação.

Neste caso, uma matriz 3x1 é multiplicada elemento a elemento por uma matriz 1x4 para produzir uma matriz 3x4. Observe como o 1 inicial é opcional: O formato de y é [4].

# These are the same computations x = tf.reshape(x,[3,1]) y = tf.range(1, 5) print(x, "\n") print(y, "\n") print(tf.multiply(x, y))
Broadcast de uma adição: a [3, 1] vezes a [1, 4] produz [3,4]
Somar uma matriz 3x1 a uma matriz 4x1 resulta em uma matriz 3x4

Aqui está a mesma operação sem broadcasting:

x_stretch = tf.constant([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]]) y_stretch = tf.constant([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]) print(x_stretch * y_stretch) # Again, operator overloading

Na maioria das vezes, o broadcasting é eficiente em termos de tempo e espaço, pois a operação de broadcasting nunca materializa os tensores expandidos na memória.

Você pode ver como vai ficar o broadcast usando tf.broadcast_to.

print(tf.broadcast_to(tf.constant([1, 2, 3]), [3, 3]))

Ao contrário de uma operação matemática, por exemplo, broadcast_to não faz nada de especial para economizar memória. Aqui, você está materializando o tensor.

Pode ficar ainda mais complicado. Esta seção{:.external} do livro Python Data Science Handbook de Jake VanderPlas mostra mais truques de broadcasting (novamente usando NumPy).

tf.convert_to_tensor

A maioria das ops, como tf.matmul e tf.reshape aceitam argumentos da classe tf.Tensor. No entanto, você notará que no caso acima, objetos Python em forma de tensores são aceitos.

A maioria, mas não todas as operações chamam convert_to_tensor em argumentos não tensores. Há um registro de conversões, e a maioria das classes de objetos, como ndarray, TensorShape, listas Python e tf.Variable do NumPy, serão convertidas automaticamente.

Veja tf.register_tensor_conversion_function para mais detalhes e, se você tiver seu próprio tipo que gostaria de converter automaticamente em um tensor.

Tensores irregulares

Um tensor com número variável de elementos ao longo de algum eixo é chamado de "irregular". Use tf.ragged.RaggedTensor para dados irregulares.

Por exemplo, isto não pode ser representado como um tensor regular:

Um `tf.RaggedTensor`, formato: [4, None]
Um tensor irregular de 2 eixos, cada linha pode ter um comprimento diferente.
ragged_list = [ [0, 1, 2, 3], [4, 5], [6, 7, 8], [9]]
try: tensor = tf.constant(ragged_list) except Exception as e: print(f"{type(e).__name__}: {e}")

Em vez disso, crie um tf.RaggedTensor usando tf.ragged.constant:

ragged_tensor = tf.ragged.constant(ragged_list) print(ragged_tensor)

O formato de um tf.RaggedTensor conterá alguns eixos com comprimentos desconhecidos:

print(ragged_tensor.shape)

Tensores de string

tf.string é um dtype, o que significa que você pode representar dados como strings (arrays de bytes de comprimento variável) em tensores.

Strings são atômicas e não podem ser indexadas da mesma forma que as strings do Python. O comprimento da string não é um dos eixos do tensor. Veja tf.strings para conhecer funções para manipulá-las.

Aqui está um tensor de strings escalar:

# Tensors can be strings, too here is a scalar string. scalar_string_tensor = tf.constant("Gray wolf") print(scalar_string_tensor)

E um vetor de strings:

Um vetor de strings, formato: [3,]
O comprimento da string não é um dos eixos do tensor.
# If you have three string tensors of different lengths, this is OK. tensor_of_strings = tf.constant(["Gray wolf", "Quick brown fox", "Lazy dog"]) # Note that the shape is (3,). The string length is not included. print(tensor_of_strings)

Na listagem acima, o prefixo b indica que o dtype tf.string não é uma string unicode, mas uma string de bytes. Consulte o Tutorial Unicode para saber mais sobre como trabalhar com texto Unicode no TensorFlow.

Se você passar caracteres Unicode, eles serão codificados em utf-8.

tf.constant("🥳👍")

Algumas funções básicas com strings podem ser encontradas em tf.strings, incluindo tf.strings.split.

# You can use split to split a string into a set of tensors print(tf.strings.split(scalar_string_tensor, sep=" "))
# ...but it turns into a `RaggedTensor` if you split up a tensor of strings, # as each string might be split into a different number of parts. print(tf.strings.split(tensor_of_strings))
Split de três strings, formato: [3, None]
A divisão de várias strings retorna um tf.RaggedTensor

E tf.strings.to_number:

text = tf.constant("1 10 100") print(tf.strings.to_number(tf.strings.split(text, " ")))

Embora você não possa usar tf.cast para transformar um tensor de string em números, você pode convertê-lo em bytes e depois em números.

byte_strings = tf.strings.bytes_split(tf.constant("Duck")) byte_ints = tf.io.decode_raw(tf.constant("Duck"), tf.uint8) print("Byte strings:", byte_strings) print("Bytes:", byte_ints)
# Or split it up as unicode and then decode it unicode_bytes = tf.constant("アヒル 🦆") unicode_char_bytes = tf.strings.unicode_split(unicode_bytes, "UTF-8") unicode_values = tf.strings.unicode_decode(unicode_bytes, "UTF-8") print("\nUnicode bytes:", unicode_bytes) print("\nUnicode chars:", unicode_char_bytes) print("\nUnicode values:", unicode_values)

O dtype tf.string é usado para todos os dados de bytes brutos no TensorFlow. O módulo tf.io contém funções para converter dados de e para bytes, inclusive decodificação de imagens e processamento de CSV.

Tensores esparsos

Às vezes, seus dados são esparsos, como um espaço de embedding muito largo. O TensorFlow oferece suporte a tf.sparse.SparseTensor e operações relacionadas para armazenar dados esparsos com eficiência.

Um `tf.SparseTensor`, formato: [3, 4]
Uma grade 3x4, com valores em apenas duas das células.
# Sparse tensors store values by index in a memory-efficient manner sparse_tensor = tf.sparse.SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]) print(sparse_tensor, "\n") # You can convert sparse tensors to dense print(tf.sparse.to_dense(sparse_tensor))