我尝试使用 SparseTensor 在完全连接的图层中表示重量变量。
但是,似乎TensorFlow 0.8不允许将SparseTensor用作tf.Variable。
有没有办法解决这个问题?
我已经尝试了
import tensorflow as tf
a = tf.constant(1)
b = tf.SparseTensor([[0,0]],[1],[1,1])
print a.__class__ # shows <class 'tensorflow.python.framework.ops.Tensor'>
print b.__class__ # shows <class 'tensorflow.python.framework.ops.SparseTensor'>
tf.Variable(a) # Variable is declared correctly
tf.Variable(b) # Fail
顺便说一句,我使用SparseTensor的最终目标是永久地屏蔽密集形式的一些连接。因此,在计算和应用渐变时,忽略了这些修剪过的连接。
在我目前的MLP实现中,SparseTensor及其稀疏形式的 matmul ops成功报告推理输出。但是,使用SparseTensor声明的权重不会作为训练步骤进行训练。
答案 0 :(得分:2)
TensorFlow目前不支持稀疏张量变量。但是,它确实支持密集变量的稀疏查找(tf.embedding_lookup
)和稀疏梯度更新(tf.sparse_add
)。我怀疑这两个就足够了你的用例。
答案 1 :(得分:2)
作为解决问题的方法,您可以为稀疏张量的值提供tf.Variable
(直到Tensorflow v0.8
)。在这种情况下,稀疏结构必须预先定义,但重量仍然可以训练。
weights = tf.Variable(<initial-value>)
sparse_var = tf.SparseTensor(<indices>, weights, <shape>) # v0.8
sparse_var = tf.SparseTensor(<indices>, tf.identity(weights), <shape>) # v0.9
答案 2 :(得分:1)
TensorFlow还不支持稀疏张量训练。您可以根据需要初始化稀疏张量,然后将其转换为密集张量并从中创建变量:
# You need to correctly initialize the sparse tensor with indices, values and a shape
b = tf.SparseTensor(indices, values, shape)
b_dense = tf.sparse_tensor_to_dense(b)
b_variable = tf.Variable(b_dense)
现在您已将稀疏张量初始化为变量。现在你需要处理渐变更新(换句话说,确保变量中的条目保持为0,因为在使用它时,在反向传播算法中计算出非消失梯度)。
为了做到这一点,TensorFlow优化器有一个名为 tf.train.Optimizer.compute_gradients(loss,[list_of_variables])的方法。这将计算图表中最小化损失函数所需的所有梯度,但尚未应用它们。此方法以(渐变,变量)的形式返回元组列表。您可以自由地修改这些渐变,但在您的情况下,将不需要的渐变屏蔽为0是有意义的(即通过创建另一个稀疏张量,默认值为0.0,值为1.0,其中存在网络中的权重)。 修改它们之后,调用优化程序方法 tf.train.Optimizer.apply_gradients(grads_and_vars)来实际应用渐变。示例代码如下所示:
# Create optimizer instance
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
# Get the gradients for your weights
grads_and_vars = optimizer.compute_gradients(loss, [b_variable])
# Modify the gradients at will
# In your case it would look similar to this
modified_grads_and_vars = [(tf.multiply(gv[0], mask_tensor), gv[1] for gv in grads_and_vars]
# Apply modified gradients to your model
optimizer.apply_gradients(modified_grads_and_vars)
这可确保您的条目在权重矩阵中保持为0,并且不会创建不需要的连接。您需要在以后处理所有其他变量的所有其他渐变。
答案 3 :(得分:0)
上面的代码可以像这样进行一些小修改。
def optimize(loss, mask_tensor):
optimizer = tf.train.AdamOptimizer(0.001)
grads_and_vars = optimizer.compute_gradients(loss)
modified_grads_and_vars = [
(tf.multiply(gv[0], mask_tensor[gv[1]]), gv[1]) for gv in grads_and_vars
]
return optimizer.apply_gradients(modified_grads_and_vars)