Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/es-419/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.

Introducción a los tensores

import tensorflow as tf import numpy as np

Los tensores son matrices multidimensionales con un tipo uniforme (llamado dtype). Puede ver todos los dtypes admitidos en tf.dtypes.DType.

Si está familiarizado con NumPy{:.external}, los tensores son (más o menos) como np.arrays.

Todos los tensores son inmutables, como los números y las cadenas de Python: nunca se puede actualizar el contenido de un tensor, sólo crear uno nuevo.

Conceptos básicos

En primer lugar, cree algunos tensores básicos.

Se trata de un "escalar" o tensor de "rango 0". Un escalar contiene un valor único y ningún "eje".

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

Un "vector" o tensor de "rango 1" es como una lista de valores. Un vector tiene un eje:

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

Una "matriz" o tensor de "rango 2" tiene dos ejes:

# 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)
Un escalar, con forma: [] Un vector, con forma: [3] Una matriz, con forma: [3, 2]
Un escalar, el número 4
La línea con 3 secciones, cada una de las cuales contiene un número. Una cuadrícula de 3x2, con cada celda que contiene un número.

Los tensores pueden tener más ejes; aquí se muestra un tensor con tres ejes:

# 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)

Hay muchas formas de visualizar un tensor con más de dos ejes.

Un tensor de 3 ejes, con forma: [3, 2, 5]

Puede convertir un tensor en un arreglo NumPy utilizando np.array o el método tensor.numpy:

np.array(rank_2_tensor)
rank_2_tensor.numpy()

Los tensores a menudo contienen valores decimales e integrales, pero tienen muchos otros tipos, incluyendo:

  • números complejos

  • cadenas

La clase base tf.Tensor requiere que los tensores sean "rectangulares"--es decir, a lo largo de cada eje, cada elemento tiene el mismo tamaño. Sin embargo, hay tipos especializados de tensores que pueden manejar diferentes formas:

Puede realizar operaciones matemáticas básicas con tensores, como la suma, la multiplicación por elementos y la multiplicación de matrices.

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

Los tensores se utilizan en todo tipo de operaciones (u "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))

Nota: Típicamente, en cualquier lugar donde una función TensorFlow espere un Tensor como entrada, la función también aceptará cualquier cosa que pueda ser convertida a un Tensor usando tf.convert_to_tensor. Vea a continuación un ejemplo.

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

Sobre las formas

Los tensores tienen formas. Algo de vocabulario:

  • Forma: La longitud (número de elementos) de cada uno de los ejes de un tensor.

  • Rango: Número de ejes del tensor. Un escalar tiene rango 0, un vector tiene rango 1, una matriz es de rango 2.

  • Eje o Dimensión: Una dimensión particular de un tensor.

  • Tamaño: El número total de elementos del tensor, el producto de los elementos del vector de forma.

Nota: Aunque se haga referencia a un "tensor de dos dimensiones", un tensor de rango 2 normalmente no describe un espacio 2D.

Los objetos tensores y tf.TensorShape tienen propiedades convenientes para acceder a ellos:

rank_4_tensor = tf.zeros([3, 2, 4, 5])
Un tensor de rango 4, con forma: [3,2,4,5]
Una forma de tensor es como un vector. Un tensor de 4 ejes
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())

Pero tenga en cuenta que los atributos Tensor.ndim y Tensor.shape no devuelven objetos Tensor. Si necesita un Tensor utilice la función tf.rank o tf.shape. Esta diferencia es sutil, pero puede ser importante a la hora de construir grafos (más adelante).

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

Aunque a menudo se hace referencia a los ejes por sus índices, siempre hay que tener en cuenta el significado de cada uno. Con frecuencia, los ejes se ordenan de global a local: El eje del lote primero, seguido de las dimensiones espaciales, y las características de cada localización en último lugar. De este modo, los vectores de características son regiones contiguas de la memoria.

Orden típico de los ejes
 Tenga en cuenta lo que es cada eje. Un tensor de 4 ejes podría ser: Lote, Ancho, Alto, Características

Indexación

Indexación de un solo eje

TensorFlow sigue las reglas estándar de indexación de Python, similares a indexar una lista o una cadena en Python{:.external}, y las reglas básicas de indexación de NumPy.

  • los índices comienzan en 0

  • los índices negativos cuentan en sentido inverso desde el final

  • los dos puntos, :, se utilizan para los segmentos: start:stop:step

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

La indexación con un escalar elimina el eje:

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

La indexación con un segmento : mantiene el eje:

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())

Indexación multieje

Los tensores de rango superior se indexan pasando varios índices.

Las mismas reglas que en el caso de un solo eje se aplican a cada eje de forma independiente.

print(rank_2_tensor.numpy())

Pasando un entero por cada índice, el resultado es un escalar.

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

Puede indexar mediante cualquier combinación de enteros y segmentos:

# 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")

Este es un ejemplo con un tensor de 3 ejes:

print(rank_3_tensor[:, :, 4])
Selección de la última característica en todas las ubicaciones de cada ejemplo del lote
Un tensor 3x2x5 con todos los valores en el índice-4 del último eje seleccionado. Los valores seleccionados empaquetados en un tensor de 2 ejes.

Lea la guía de segmentación de tensores para aprender cómo puede aplicar la indexación para manipular elementos individuales en sus tensores.

Manipulación de las formas

Modificar la forma de un tensor es de gran utilidad.

# 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())

Puede volver a dar forma a un tensor en una nueva forma. La operación tf.reshape es rápida y barata, ya que no es necesario duplicar los datos subyacentes.

# 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)

Los datos mantienen su disposición en la memoria y se crea un nuevo tensor, con la forma solicitada, apuntando a los mismos datos. TensorFlow utiliza la clasificación de memoria "row-major" de estilo C, en la que el incremento del índice situado en el extremo derecho corresponde a un único paso en la memoria.

print(rank_3_tensor)

Si comprime un tensor, podrá ver en qué orden está almacenado en la memoria.

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

Normalmente, el único uso razonable de tf.reshape es combinar o dividir ejes adyacentes (o agregar/eliminar 1).

Para este tensor 3x2x5, es razonable cambiar la forma a (3x2)x5 o 3x(2x5), ya que los segmentos no se mezclan:

print(tf.reshape(rank_3_tensor, [3*2, 5]), "\n") print(tf.reshape(rank_3_tensor, [3, -1]))
Algunas buenas rediseños.
Un tensor 3x2x5 Los mismos datos redimensionados a (3x2)x5 Los mismos datos redimensionados a 3x(2x5)

La remodelación "funcionará" para cualquier forma nueva con el mismo número total de elementos, pero no hará nada útil si no se respeta el orden de los ejes.

Intercambiar ejes en tf.reshape no funciona; para eso se necesita tf.transpose.

# 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}")
Algunos malos rediseños.
No se pueden reordenar los ejes, para eso utilice tf.transpose Cualquier cosa que mezcle los segmentos de datos probablemente esté mal. La nueva forma debe ajustarse exactamente.

Puede encontrarse con formas no especificadas completamente. O bien la forma contiene un None (se desconoce la longitud de un eje) o toda la forma es None (se desconoce el rango del tensor).

Excepto para tf.RaggedTensor, tales formas sólo se producirán en el contexto de las API simbólicas de construcción de grafos de TensorFlow:

Más información sobre DTypes

Para inspeccionar el tipo de datos de un tensor utilice la propiedad Tensor.dtype.

Cuando se crea un tf.Tensor a partir de un objeto Python se puede especificar opcionalmente el tipo de datos.

Si no lo hace, TensorFlow elige un tipo de datos que pueda representar sus datos. TensorFlow convierte números enteros de Python a tf.int32 y números decimales de Python a tf.float32. Por otra parte TensorFlow utiliza las mismas reglas que NumPy para convertir a matrices.

Puede pasar de un tipo a otro.

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)

Transmisión

La difusión es un concepto tomado de la función equivalent de NumPy{:.external}. En resumen, en determinadas condiciones, los tensores más pequeños se "estiran" automáticamente para ajustarse a tensores más grandes cuando se ejecutan operaciones combinadas sobre ellos.

El caso más sencillo y común es cuando se intenta multiplicar o sumar un tensor a un escalar. En ese caso, el escalar se emite para que tenga la misma forma que el otro 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)

Del mismo modo, los ejes con longitud 1 pueden estirarse para que coincidan con los demás argumentos. Ambos argumentos pueden estirarse en el mismo cálculo.

En este caso, una matriz de 3x1 se multiplica elemento a elemento por una matriz de 1x4 para obtener una matriz de 3x4. Observe cómo el 1 inicial es opcional: La forma de y es [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))
Una adición transmitida: un [3, 1] por un [1, 4] da un [3,4]
Sumando una matriz 3x1 a una matriz 4x1 se obtiene una matriz 3x4

Esta es la misma operación sin transmisión:

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

La mayoría de las veces, la difusión es eficiente tanto en tiempo como en espacio, ya que la operación de difusión nunca materializa los tensores expandidos en la memoria.

Puede ver el aspecto de la difusión utilizando tf.broadcast_to.

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

A diferencia de una operación matemática, por ejemplo, broadcast_to no hace nada especial para ahorrar memoria. Aquí, está materializando el tensor.

Puede ser aún más complicado. Esta sección{:.external} del libro de Jake VanderPlas Python Data Science Handbook muestra más trucos de transmisión (de nuevo en NumPy).

tf.convert_to_tensor

La mayoría de las operaciones, como tf.matmul y tf.reshape toman argumentos de la clase tf.Tensor. Sin embargo, notará que en el caso anterior, se aceptan objetos de Python con forma de tensores.

La mayoría de las operaciones, pero no todas, llaman a convert_to_tensor en argumentos que no son tensores. Hay un registro de conversiones, y la mayoría de las clases de objetos como ndarray de NumPy, TensorShape, listas de Python, y tf.Variable se convertirán automáticamente.

Consulte tf.register_tensor_conversion_function para obtener más detalles, y si tiene su propio tipo que le gustaría convertirlo automáticamente a un tensor.

Tensores irregulares

Un tensor con números variables de elementos a lo largo de algún eje se llama "ragged". Utilice tf.ragged.RaggedTensor para obtener datos irregulares.

Por ejemplo, esto no puede representarse como un tensor regular:

Un `tf.RaggedTensor`, con forma: [4, None]
En un tensor irregular de 2 ejes, cada fila puede tener una longitud 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}")

En cambio, crea un tf.RaggedTensor utilizando tf.ragged.constant:

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

La forma de un tf.RaggedTensor contendrá algunos ejes con longitudes desconocidas:

print(ragged_tensor.shape)

Tensores de cadenas

tf.string es un dtype, es decir, se pueden representar datos como cadenas (matrices de bytes de longitud variable) en tensores.

Las cadenas son atómicas y no pueden indexarse como las cadenas de Python. La longitud de la cadena no es uno de los ejes del tensor. Consulte tf.strings para ver las funciones que permiten manipularlas.

Este es un tensor de cadena escalar:

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

Y un vector de cadenas:

Un vector de cadenas, con forma: [3,]
La longitud de la cadena no es uno de los ejes del 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)

En la impresión anterior, el prefijo b indica que el dtype tf.string no es una cadena unicode, sino una cadena de bytes. Consulte el Tutorial Unicode para obtener más información sobre cómo trabajar con texto unicode en TensorFlow.

Si introduce caracteres unicode, se codifican en utf-8.

tf.constant("🥳👍")

Algunas funciones básicas con cadenas se pueden encontrar en tf.strings, incluyendo 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))
Tres cadenas divididas, con forma: [3, None]
La división de múltiples cadenas devuelve un tf.RaggedTensor

Y tf.string.to_number:

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

Aunque no se puede utilizar tf.cast para convertir un tensor de cadenas en números, se puede convertir en bytes, y después en 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)

El dtype tf.string se utiliza para todos los datos en bytes en TensorFlow. El módulo tf.io contiene funciones para convertir datos a y desde bytes, incluyendo la decodificación de imágenes y el parseo de csv.

Tensores dispersos

En algunas ocasiones, sus datos son dispersos, como un espacio de incorporación muy amplio. TensorFlow es compatible con tf.sparse.SparseTensor y las operaciones relacionadas para almacenar datos dispersos de manera eficiente.

Un `tf.SparseTensor`, con forma: [3, 4]
Una cuadrícula de 3x4, con valores en sólo dos de las celdas.
# 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))