通过稀疏张量反向传播渐变?

时间:2017-02-03 20:34:19

标签: python tensorflow sparse-matrix backpropagation

我有一个正常的前馈网络,它产生一个向量v。然后将v的元素用作稀疏矩阵M的非零项(假设坐标是预定义的)。然后将稀疏矩阵乘以密集向量,并在得到的标量上定义损失。我想反向传播损失w.r.t.网络的权重,需要通过稀疏矩阵。

对于稀疏矩阵来说,这似乎是一个非常合理的用例,但似乎不支持这样的功能。实际上,即使调用tf.gradients(M,[v])也会产生错误:

  

AttributeError:' SparseTensor'对象没有属性' value_index'

我做错了什么,或者我认为这个功能还没有(但是?)存在?如果是后者,那么这个特定用例的解决方法是不能重写所有定义了渐变的稀疏张量操作?

2 个答案:

答案 0 :(得分:1)

稍微改变这一点确实有效,直接采用values SparseTensor的渐变:

import tensorflow as tf
sparse_values = tf.identity(tf.Variable(tf.constant([1., 2., 3.])))
sparse_indices = tf.constant([[0, 0], [1, 1], [2, 2]], dtype=tf.int64)
sparse_matrix = tf.SparseTensor(sparse_indices, sparse_values, [3, 3])
multiplied = tf.sparse_tensor_dense_matmul(sparse_matrix, tf.eye(3))
loss = tf.reduce_sum(multiplied)
gradients = tf.gradients(loss, [sparse_values])
with tf.Session() as session:
    tf.global_variables_initializer().run()
    print(session.run(gradients))

打印(在TensorFlow 0.12.1上):

[array([ 1.,  1.,  1.], dtype=float32)]

为什么tf.identity op对于定义渐变是必要的我还没弄清楚(可能与ref dtypes有关)。

答案 1 :(得分:0)

我在黑暗中钓鱼,使用代码和文档,而不是经验。

Tensor班级创建者是:

def __init__(self, op, value_index, dtype):
    #  value_index: An `int`. Index of the operation's endpoint that produces this tensor.

value_index用于生成Tensor名称。

SparseTensor一个

def __init__(self, indices, values, dense_shape):

其中没有任何地方定义文件tensorflow/tensorflow/python/framework/sparse_tensor.pyvalue_index引用。

它的论点是张量,可能每个都有自己的value_index

此外,SparseTensor似乎是IndexedSlices的替代品,tf.gradients也包含张量。

A `Tensor` or list of tensors 的输入都是

gradients

_IndexedSlicesToTensor定义文件有一个SparseTensor方法,但IndexedSlices没有任何等效方法。因此,在SparseTensors的情况下似乎有某种自动转换为密集(如果结果太大则会发出警告),但l = ['Opinion, Journal, Editorial', 'Opinion, Magazine, Evidence-based', 'Evidence-based'] # Get list of unique classes classes = list(set([j for i in l for j in i.split(', ')])) => ['Journal', 'Opinion', 'Editorial', 'Evidence-based', 'Magazine'] # Get indices in the matrix indices = np.array([[k, classes.index(j)] for k, i in enumerate(l) for j in i.split(', ')]) => array([[0, 1], [0, 0], [0, 2], [1, 1], [1, 4], [1, 3], [2, 3]]) # Generate output output = np.zeros((len(l), len(classes)), dtype=int) output[indices[:, 0], indices[:, 1]]=1 => array([[ 1, 1, 1, 0, 0], [ 0, 1, 0, 1, 1], [ 0, 0, 0, 1, 0]]) 则不然。我不知道这是一个不完全发展的情况,还是不相容的情况,使其无法实现。