Conversión de tensor a un SparseTensor para ctc_loss

¿Hay alguna manera de convertir un tensor denso en un tensor disperso? Aparentemente, el Estimator.fit de Tensorflow no acepta SparseTensors como tags. Una razón por la que me gustaría pasar SparseTensors al Estimator.fit de Tensorflow es poder usar tensorflow ctc_loss. Aquí está el código:

import dataset_utils import tensorflow as tf import numpy as np from tensorflow.contrib import grid_rnn, learn, layers, framework def grid_rnn_fn(features, labels, mode): input_layer = tf.reshape(features["x"], [-1, 48, 1596]) indices = tf.where(tf.not_equal(labels, tf.constant(0, dtype=tf.int32))) values = tf.gather_nd(labels, indices) sparse_labels = tf.SparseTensor(indices, values, dense_shape=tf.shape(labels, out_type=tf.int64)) cell_fw = grid_rnn.Grid2LSTMCell(num_units=128) cell_bw = grid_rnn.Grid2LSTMCell(num_units=128) bidirectional_grid_rnn = tf.nn.bidirectional_dynamic_rnn(cell_fw, cell_bw, input_layer, dtype=tf.float32) outputs = tf.reshape(bidirectional_grid_rnn[0], [-1, 256]) W = tf.Variable(tf.truncated_normal([256, 80], stddev=0.1, dtype=tf.float32), name='W') b = tf.Variable(tf.constant(0., dtype=tf.float32, shape=[80], name='b')) logits = tf.matmul(outputs, W) + b logits = tf.reshape(logits, [tf.shape(input_layer)[0], -1, 80]) logits = tf.transpose(logits, (1, 0, 2)) loss = None train_op = None if mode != learn.ModeKeys.INFER: #Error occurs here loss = tf.nn.ctc_loss(inputs=logits, labels=sparse_labels, sequence_length=320) ... # returning ModelFnOps def main(_): image_paths, labels = dataset_utils.read_dataset_list('../test/dummy_labels_file.txt') data_dir = "../test/dummy_data/" images = dataset_utils.read_images(data_dir=data_dir, image_paths=image_paths, image_extension='png') print('Done reading images') images = dataset_utils.resize(images, (1596, 48)) images = dataset_utils.transpose(images) labels = dataset_utils.encode(labels) x_train, x_test, y_train, y_test = dataset_utils.split(features=images, test_size=0.5, labels=labels) train_input_fn = tf.estimator.inputs.numpy_input_fn( x={"x": np.array(x_train)}, y=np.array(y_train), num_epochs=1, shuffle=True, batch_size=1 ) classifier = learn.Estimator(model_fn=grid_rnn_fn, model_dir="/tmp/grid_rnn_ocr_model") classifier.fit(input_fn=train_input_fn) 

ACTUALIZACIÓN :

Resulta que esta solución desde aquí convierte el tensor denso en uno disperso:

 indices = tf.where(tf.not_equal(labels, tf.constant(0, dtype=tf.int32))) values = tf.gather_nd(labels, indices) sparse_labels = tf.SparseTensor(indices, values, dense_shape=tf.shape(labels, out_type=tf.int64)) 

Sin embargo, encuentro este error ahora provocado por ctc_loss:

 ValueError: Shape must be rank 1 but is rank 0 for 'CTCLoss' (op: 'CTCLoss') with input shapes: [?,?,80], [?,2], [?], []. 

Tengo este código que convierte tags densas en dispersas:

 def convert_to_sparse(labels, dtype=np.int32): indices = [] values = [] for n, seq in enumerate(labels): indices.extend(zip([n] * len(seq), range(len(seq)))) values.extend(seq) indices = np.asarray(indices, dtype=dtype) values = np.asarray(values, dtype=dtype) shape = np.asarray([len(labels), np.asarray(indices).max(0)[1] + 1], dtype=dtype) return indices, values, shape 

y_train en tags dispersas, y SparseTensor los valores dentro de un SparseTensor :

 sparse_y_train = convert_to_sparse(y_train) print(tf.SparseTensor( indices=sparse_y_train[0], values=sparse_y_train[1], dense_shape=sparse_y_train )) 

Y lo comparó con el SparseTensor creado dentro de grid_rnn_fn:

 indices = tf.where(tf.not_equal(labels, tf.constant(0, dtype=tf.int32))) values = tf.gather_nd(labels, indices) sparse_labels = tf.SparseTensor(indices, values, dense_shape=tf.shape(labels, out_type=tf.int64)) 

Esto es lo que tengo:

Para sparse_y_train :

 SparseTensor(indices=Tensor("SparseTensor/indices:0", shape=(33, 2), dtype=int64), values=Tensor("SparseTensor/values:0", shape=(33,), dtype=int32), dense_shape=Tensor("SparseTensor/dense_shape:0", shape=(2,), dtype=int64)) 

Para sparse_labels :

 SparseTensor(indices=Tensor("Where:0", shape=(?, 2), dtype=int64), values=Tensor("GatherNd:0", shape=(?,), dtype=int32), dense_shape=Tensor("Shape:0", shape=(2,), dtype=int64)) 

Lo que me lleva a pensar que parece que ctc_loss no puede manejar SparseTensors como tags con formas dinámicas.

Sí. Es posible convertir un tensor en un tensor disperso y volver:

Sea sparse un tensor escaso y dense sea ​​un tensor denso.

De escaso a denso:

  dense = tf.sparse_to_dense(sparse.indices, sparse.shape, sparse.values) 

De denso a escaso:

 zero = tf.constant(0, dtype=tf.float32) where = tf.not_equal(dense, zero) indices = tf.where(where) values = tf.gather_nd(dense, indices) sparse = tf.SparseTensor(indices, values, dense.shape)