Home Ciencia y Tecnología Tensores dispersos tensorflow explicados con ejemplos

Tensores dispersos tensorflow explicados con ejemplos

30
0

Descripción common del contenido

  • Tensores escasos en tensorflow
  • Creación de un tf.sparse.sparsetensor
  • Manipulación de tensores dispersos
  • Usando tf.sparse.sparsetensor con otras API TensorFlow
  • tf.keras
  • tf.information
  • tf.prepare.instance
  • tf.función
  • Más lecturas y recursos

Cuando se trabaja con tensores que contienen muchos valores cero, es importante almacenarlos de manera que sea eficiente en el espacio y el tiempo. Los tensores dispersos permiten un almacenamiento y procesamiento eficientes de tensores que contienen muchos valores cero. Los tensores dispersos se usan ampliamente en esquemas de codificación como TF-IDF como parte del preprocesamiento de datos en aplicaciones de PNL y para el procesamiento de imágenes de preprocesamiento con muchos píxeles oscuros en aplicaciones de visión por computadora.

Tensores escasos en tensorflow

TensorFlow representa tensores escasos a través del tf.sparse.SparseTensor objeto. Actualmente, los tensores dispersos en TensorFlow están codificados utilizando el formato de la lista de coordenadas (COO). Este formato de codificación está optimizado para matrices de hiper-sparse, como incrustaciones.

La codificación de COO para tensores dispersos se compone de:

  • values: Un tensor 1D con forma [N] que contiene todos los valores distantes de cero.
  • indices: Un tensor 2D con forma [N, rank]que contiene los índices de los valores distintivos.
  • dense_shape: Un tensor 1D con forma [rank]especificando la forma del tensor.

A cero cero valor en el contexto de un tf.sparse.SparseTensor es un valor que no está codificado explícitamente. Es posible incluir explícitamente valores cero en el values de una matriz escasa de COO, pero estos “ceros explícitos” generalmente no se incluyen cuando se refieren a valores distintivos en un tensor escaso.

Nota: tf.sparse.SparseTensor No requiere que los índices/valores estén en un orden en explicit, pero varios OPS suponen que están en el orden de mayúsculas. Usar tf.sparse.reorder Para crear una copia del tensor disperso que se clasifica en el orden canónico de la fila.

Creando un tf.sparse.SparseTensor

Construir tensores dispersos especificando directamente su values, indicesy dense_shape.

import tensorflow as tf
2024-10-25 01:24:09.202320: E exterior/local_xla/xla/stream_executor/cuda/cuda_fft.cc:477] Unable to register cuFFT manufacturing facility: Making an attempt to register manufacturing facility for plugin cuFFT when one has already been registered
WARNING: All log messages earlier than absl::InitializeLog() is known as are written to STDERR
E0000 00:00:1729819449.223893   16549 cuda_dnn.cc:8310] Unable to register cuDNN manufacturing facility: Making an attempt to register manufacturing facility for plugin cuDNN when one has already been registered
E0000 00:00:1729819449.230517   16549 cuda_blas.cc:1418] Unable to register cuBLAS manufacturing facility: Making an attempt to register manufacturing facility for plugin cuBLAS when one has already been registered
st1 = tf.sparse.SparseTensor(indices=[[0, 3], [2, 4]],
                      values=[10, 20],
                      dense_shape=[3, 10])
W0000 00:00:1729819451.911465   16549 gpu_device.cc:2344] Can not dlopen some GPU libraries. Please be certain the lacking libraries talked about above are put in correctly if you want to make use of GPU. Comply with the information at  for the best way to obtain and setup the required libraries in your platform.
Skipping registering GPU units...

Cuando usas el print() Función para imprimir un tensor escaso, muestra el contenido de los tres tensores de componentes:

print(st1)
SparseTensor(indices=tf.Tensor(
[[0 3]
 [2 4]], form=(2, 2), dtype=int64), values=tf.Tensor([10 20], form=(2,), dtype=int32), dense_shape=tf.Tensor([ 3 10], form=(2,), dtype=int64))

Es más fácil entender el contenido de un tensor escaso si el distinto de cero values están alineados con su correspondiente indices. Defina una función auxiliar de tensores dispersos bastante impresos de modo que cada valor distinto de cero se muestre en su propia línea.

def pprint_sparse_tensor(st):
  s = ""
print(pprint_sparse_tensor(st1))

You can also construct sparse tensors from dense tensors by using tf.sparse.from_dense, and convert them back to dense tensors by using tf.sparse.to_dense.

st2 = tf.sparse.from_dense([[1, 0, 0, 8], [0, 0, 0, 0], [0, 0, 3, 0]]) print (pPrint_sparse_tensor (ST2))

st3 = tf.sparse.to_dense(st2)
print(st3)
tf.Tensor(
[[1 0 0 8]
 [0 0 0 0]
 [0 0 3 0]]forma = (3, 4), dtype = int32)

Manipulación de tensores dispersos

Use las utilidades en el tf.sparse Paquete para manipular tensores dispersos. Ops como tf.math.add que puede usar para la manipulación aritmética de tensores densos no funcionan con tensores dispersos.

Agregue tensores dispersos de la misma forma usando tf.sparse.add.

st_a = tf.sparse.SparseTensor(indices=[[0, 2], [3, 4]],
                       values=[31, 2], 
                       dense_shape=[4, 10])

st_b = tf.sparse.SparseTensor(indices=[[0, 2], [3, 0]],
                       values=[56, 38],
                       dense_shape=[4, 10])

st_sum = tf.sparse.add(st_a, st_b)

print(pprint_sparse_tensor(st_sum))

Usar tf.sparse.sparse_dense_matmul para multiplicar tensores dispersos con matrices densas.

st_c = tf.sparse.SparseTensor(indices=([0, 1], [1, 0], [1, 1]),
                       values=[13, 15, 17],
                       dense_shape=(2,2))

mb = tf.fixed([[4], [6]])
product = tf.sparse.sparse_dense_matmul(st_c, mb)

print(product)
tf.Tensor(
[[ 78]
 [162]], form=(2, 1), dtype=int32)

Poner tensores escasos usando usando tf.sparse.concat y desarmarlos usando usando tf.sparse.slice.

sparse_pattern_A = tf.sparse.SparseTensor(indices = [[2,4], [3,3], [3,4], [4,3], [4,4], [5,4]],
                         values = [1,1,1,1,1,1],
                         dense_shape = [8,5])
sparse_pattern_B = tf.sparse.SparseTensor(indices = [[0,2], [1,1], [1,3], [2,0], [2,4], [2,5], [3,5], 
                                              [4,5], [5,0], [5,4], [5,5], [6,1], [6,3], [7,2]],
                         values = [1,1,1,1,1,1,1,1,1,1,1,1,1,1],
                         dense_shape = [8,6])
sparse_pattern_C = tf.sparse.SparseTensor(indices = [[3,0], [4,0]],
                         values = [1,1],
                         dense_shape = [8,6])

sparse_patterns_list = [sparse_pattern_A, sparse_pattern_B, sparse_pattern_C]
sparse_pattern = tf.sparse.concat(axis=1, sp_inputs=sparse_patterns_list)
print(tf.sparse.to_dense(sparse_pattern))
tf.Tensor(
[[0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0]
 [0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0]
 [0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0]
 [0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0]
 [0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0]
 [0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]], form=(8, 17), dtype=int32)
sparse_slice_A = tf.sparse.slice(sparse_pattern_A, begin = [0,0], dimension = [8,5])
sparse_slice_B = tf.sparse.slice(sparse_pattern_B, begin = [0,5], dimension = [8,6])
sparse_slice_C = tf.sparse.slice(sparse_pattern_C, begin = [0,10], dimension = [8,6])
print(tf.sparse.to_dense(sparse_slice_A))
print(tf.sparse.to_dense(sparse_slice_B))
print(tf.sparse.to_dense(sparse_slice_C))
tf.Tensor(
[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 1]
 [0 0 0 1 1]
 [0 0 0 1 1]
 [0 0 0 0 1]
 [0 0 0 0 0]
 [0 0 0 0 0]], form=(8, 5), dtype=int32)
tf.Tensor(
[[0]
 [0]
 [1]
 [1]
 [1]
 [1]
 [0]
 [0]], form=(8, 1), dtype=int32)
tf.Tensor([], form=(8, 0), dtype=int32)

Si está utilizando TensorFlow 2.4 o superior, use tf.sparse.map_values para operaciones de elementos en valores distintos de cero en tensores dispersos.

st2_plus_5 = tf.sparse.map_values(tf.add, st2, 5)
print(tf.sparse.to_dense(st2_plus_5))
tf.Tensor(
[[ 6  0  0 13]
 [ 0  0  0  0]
 [ 0  0  8  0]], form=(3, 4), dtype=int32)

Tenga en cuenta que solo se modificaron los valores distintivos: los valores cero se mantienen cero.

De manera equivalente, puede seguir el patrón de diseño a continuación para versiones anteriores de TensorFlow:

st2_plus_5 = tf.sparse.SparseTensor(
    st2.indices,
    st2.values + 5,
    st2.dense_shape)
print(tf.sparse.to_dense(st2_plus_5))
tf.Tensor(
[[ 6  0  0 13]
 [ 0  0  0  0]
 [ 0  0  8  0]], form=(3, 4), dtype=int32)

Usando tf.sparse.SparseTensor con otras API tensorflow

Los tensores dispersos funcionan transparentemente con estas API de flujo tensor:

  • tf.keras
  • tf.information
  • tf.Prepare.Instance protobuf
  • tf.operate
  • tf.while_loop
  • tf.cond
  • tf.id
  • tf.forged
  • tf.print
  • tf.saved_model
  • tf.io.serialize_sparse
  • tf.io.serialize_many_sparse
  • tf.io.deserialize_many_sparse
  • tf.math.abs
  • tf.math.unfavorable
  • tf.math.signal
  • tf.math.sq.
  • tf.math.sqrt
  • tf.math.erf
  • tf.math.tanh
  • tf.math.bessel_i0e
  • tf.math.bessel_i1e

Los ejemplos se muestran a continuación para algunas de las API anteriores.

tf.keras

Un subconjunto de la tf.keras La API admite tensores escasos sin costosas operaciones de fundición o conversión. La API de Keras le permite pasar tensores dispersos como entradas a un modelo Keras. Colocar sparse=True Al llamar tf.keras.Enter o tf.keras.layers.InputLayer. Puede pasar tensores dispersos entre las capas de Keras, y también hacer que los modelos Keras los devuelvan como salidas. Si usa tensores dispersos en tf.keras.layers.Dense Capas En su modelo, generarán tensores densos.

El siguiente ejemplo le muestra cómo pasar un tensor escaso como entrada a un modelo Keras si usa solo capas que admiten entradas dispersas.

x = tf.keras.Enter(form=(4,), sparse=True)
y = tf.keras.layers.Dense(4)(x)
mannequin = tf.keras.Mannequin(x, y)

sparse_data = tf.sparse.SparseTensor(
    indices = [(0,0),(0,1),(0,2),
               (4,3),(5,0),(5,1)],
    values = [1,1,1,1,1,1],
    dense_shape = (6,4)
)

mannequin(sparse_data)

mannequin.predict(sparse_data)
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step
array([[ 1.8707037e-02,  7.7025330e-01,  2.2425324e-01, -1.9139588e+00],
       [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
       [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
       [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
       [-6.2435389e-02, -4.5783034e-01,  1.2970567e-03, -1.8046319e-01],
       [-8.0019468e-01,  9.0452707e-01,  2.1884918e-02, -1.3622781e+00]],
      dtype=float32)

tf.information

El tf.information API le permite construir tuberías de entrada complejas a partir de piezas simples y reutilizables. Su estructura de datos del núcleo es tf.information.Datasetque representa una secuencia de elementos en los que cada elemento consta de uno o más componentes.

Construyendo conjuntos de datos con tensores escasos

Construir conjuntos de datos a partir de tensores dispersos utilizando los mismos métodos que se utilizan para construirlos a partir de tf.Tensors o matrices numpy, como tf.information.Dataset.from_tensor_slices. Este OP preserva la escasez (o naturaleza escasa) de los datos.

dataset = tf.information.Dataset.from_tensor_slices(sparse_data)
for aspect in dataset: 
  print(pprint_sparse_tensor(aspect))






Conjuntos de datos por lotes y desacelerar con tensores escasos

Puede lotes (combinar elementos consecutivos en un solo elemento) y dejar de desgarrar conjuntos de datos con tensores dispersos utilizando el Dataset.batch y Dataset.unbatch métodos respectivamente.

batched_dataset = dataset.batch(2)
for aspect in batched_dataset:
  print (pprint_sparse_tensor(aspect))



unbatched_dataset = batched_dataset.unbatch()
for element in unbatched_dataset:
  print (pprint_sparse_tensor(element))






También puedes usar tf.information.experimental.dense_to_sparse_batch a los elementos del conjunto de datos por lotes de formas variables en tensores dispersos.

Transformar conjuntos de datos con tensores escasos

Transformar y crear tensores escasos en conjuntos de datos utilizando Dataset.map.

transform_dataset = dataset.map(lambda x: x*2)
for i in transform_dataset:
  print(pprint_sparse_tensor(i))






tf.prepare.instance

tf.prepare.Instance es una codificación de protoBUF estándar para datos de flujo de tensor. Al usar tensores dispersos con tf.prepare.Instancepuede:

  • Leer datos de longitud variable en un tf.sparse.SparseTensor usando tf.io.VarLenFeature. Sin embargo, debe considerar usar tf.io.RaggedFeature en cambio.
  • Leer datos escasos arbitrarios en un tf.sparse.SparseTensor usando tf.io.SparseFeatureque utiliza tres teclas de características separadas para almacenar el indices, valuesy dense_shape.

tf.operate

El tf.operate El decorador precompuesta gráficos de tensorflow para funciones de Python, que pueden mejorar sustancialmente el rendimiento de su código de flujo tensor. Los tensores escasos funcionan transparentemente con ambos tf.operate y funciones concretas.

@tf.operate
def f(x,y):
  return tf.sparse.sparse_dense_matmul(x,y)

a = tf.sparse.SparseTensor(indices=[[0, 3], [2, 4]],
                    values=[15, 25],
                    dense_shape=[3, 10])

b = tf.sparse.to_dense(tf.sparse.transpose(a))

c = f(a,b)

print(c)
tf.Tensor(
[[225   0   0]
 [  0   0   0]
 [  0   0 625]], form=(3, 3), dtype=int32)

Distinguir los valores faltantes de los valores cero

La mayoría de las operaciones en tf.sparse.SparseTensorS trata los valores faltantes y los valores cero explícitos de manera idéntica. Esto es por diseño – un tf.sparse.SparseTensor se supone que actúa como un tensor denso.

Sin embargo, hay algunos casos en los que puede ser útil distinguir los valores cero de los valores faltantes. En explicit, esto permite una forma de codificar datos faltantes/desconocidos en sus datos de entrenamiento. Por ejemplo, considere un caso de uso en el que tenga un tensor de puntajes (que puede tener algún valor de punto flotante de -inf a +inf), con algunos puntajes faltantes. Puede codificar este tensor utilizando un tensor disperso donde los ceros explícitos son puntajes cero conocidos, pero los valores cero implícitos en realidad representan datos faltantes y no cero.

Nota: Este generalmente no es el uso previsto de tf.sparse.SparseTensors; Y es posible que también desee considerar otras técnicas para codificar esto, como por ejemplo, usar un tensor de máscara separado que identifica las ubicaciones de los valores conocidos/desconocidos. Sin embargo, ejercer precaución mientras usa este enfoque, ya que la mayoría de las operaciones escasas tratarán de manera idéntica valores cero explícitos e implícitos.

Tenga en cuenta que a algunas operaciones les gusta tf.sparse.reduce_max No trate los valores faltantes como si fueran cero. Por ejemplo, cuando ejecuta el bloque de código a continuación, la salida esperada es 0. Sin embargo, debido a esta excepción, la salida es -3.

print(tf.sparse.reduce_max(tf.sparse.from_dense([-5, 0, -3])))
tf.Tensor(-3, form=(), dtype=int32)

En contraste, cuando aplicas tf.math.reduce_max Para un tensor denso, la salida es 0 como se esperaba.

print(tf.math.reduce_max([-5, 0, -3]))
tf.Tensor(0, form=(), dtype=int32)

Más lecturas y recursos

  • Consulte la Guía del tensor para aprender sobre tensores.
  • Lea la guía de tensor irregular para aprender a trabajar con tensores irregulares, un tipo de tensor que le permite trabajar con datos no uniformes.
  • Echa un vistazo a este modelo de detección de objetos en el Modelo de TensorFlow Backyard que usa tensores dispersos en un tf.Instance decodificador de datos.

Publicado originalmente en el Flujo tensor Sitio net, este artículo aparece aquí en un nuevo titular y tiene licencia bajo CC por 4.0. Muestras de código compartidas bajo la licencia Apache 2.0.

fuente

LEAVE A REPLY

Please enter your comment!
Please enter your name here