2016-05-03 1 views
2

Я пытаюсь использовать SparseTensor, чтобы представить весовые переменные в полностью подключенном слое.
Однако, похоже, что TensorFlow 0.8 не позволяет использовать SparseTensor как tf.Variable.
Есть ли способ обойти это?Использование SparseTensor в качестве обучаемой переменной?

Я попытался

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 Операции успешно завершаются выводами вывода. Тем не менее, веса, объявленные с использованием SparseTensor, не проходят обучение, так как пройдут учебные шаги.

ответ

2

В настоящее время TensorFlow не поддерживает разреженные переменные тензора. Тем не менее, он поддерживает разреженные запросы (tf.embedding_lookup) и разреженные обновления градиента (tf.sparse_add) плотных переменных. Я подозреваю, что этих двух будет достаточно для вашего случая использования.

+0

Благодарим за быстрый ответ.Итак, чтобы обучить разреженный тензор или сохранить его в сериализованном виде, в текущей версии (0.8) нет прямого метода, верно? Теперь я просто пытаюсь сохранить разреженную матрицу как плотную форму каждого индекса, значений и формы. А затем загрузите его в SparseTensor (idx.eval(), value.eval(), shape.eval()). Есть ли лучшее обходное решение? –

1

Как обход вашей проблемы, вы можете предоставить 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 
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, так как для этого используется наименее градиент, рассчитанный в алгоритме backpropagation для использования при наименьшем использовании).

Для того чтобы сделать это, TensorFlow оптимизаторов есть метод, называемый tf.train.Optimizer.compute_gradients (потеря, [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 в вашей весовой матрицы и никаких нежелательных соединений не создается. Вы должны позаботиться обо всех других градиентах для всех других переменных позже.

+2

Запустил ли кто-нибудь в 1.1.0? – pcejrowski

+0

Любой прогресс в 1.2.0, потому что я не могу изменить какое-либо обновление ... – pcejrowski

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)