[英]Apply tensorflow gradients to specific inputs
I am trying to create a Jacobian matrix for certain output vairables with respect to specific input features in a keras model. 我正在尝试针对keras模型中的特定输入特征为某些输出变量创建雅可比矩阵。 For instance If I have a model with 100 input features and 10 output variables and I want to create a Jacobian of outputs 2, 3, and 4 with respect to outputs 50-70, I can create the jacobian like this: 例如,如果我有一个包含100个输入要素和10个输出变量的模型,并且我想针对输出50-70创建输出2、3和4的雅可比行列式,则可以这样创建jacobian:
from keras.models import Model
from keras.layers import Dense, Input
import tensorflow as tf
import keras.backend as K
import numpy as np
input_ = Input(shape=(100,))
output_ = Dense(10)(input_)
model = Model(input_,output_)
x_indices = np.arange(50,70)
y_indices = [2,3,4]
y_list = tf.unstack(model.output[0])
x = np.random.random((1,100))
jacobian_matrix = []
for i in y_indices:
J = tf.gradients(y_list[i], model.input)
jacobian_func = K.function([model.input, K.learning_phase()], J)
jac = jacobian_func([x, False])[0][0,x_indices]
jacobian_matrix.append(jac)
jacobian_matrix = np.array(jacobian_matrix)
but with a much more complex model, this is extremely slow. 但是使用更复杂的模型,速度非常慢。 I only want to create the Jacobian functions above with respect to the inputs of interest. 我只想针对感兴趣的输入创建上面的Jacobian函数。 I tried something like this: 我尝试过这样的事情:
from keras.models import Model
from keras.layers import Dense, Input
import tensorflow as tf
import keras.backend as K
import numpy as np
input_ = Input(shape=(100,))
output_ = Dense(10)(input_)
model = Model(input_,output_)
x_indices = np.arange(50,60)
y_indices = [2,3,4]
y_list = tf.unstack(model.output[0])
x_list = tf.unstack(model.input[0])
x = np.random.random((1,100))
jacobian_matrix = []
for i in y_indices:
jacobian_row = []
for j in x_indices:
J = tf.gradients(y_list[i], x_list[j])
jacobian_func = K.function([model.input, K.learning_phase()], J)
jac = jacobian_func([x, False])[0][0,:]
jacobian_row.append(jac)
jacobian_matrix.append(jacobian_row)
jacobian_matrix = np.array(jacobian_matrix)
and got the Error: 并得到错误:
TypeErrorTraceback (most recent call last)
<ipython-input-33-d0d524ad0e40> in <module>()
23 for j in x_indices:
24 J = tf.gradients(y_list[i], x_list[j])
---> 25 jacobian_func = K.function([model.input, K.learning_phase()], J)
26 jac = jacobian_func([x, False])[0][0,:]
27 jacobian_row.append(jac)
/opt/conda/lib/python2.7/site-packages/keras/backend/tensorflow_backend.pyc in function(inputs, outputs, updates, **kwargs)
2500 msg = 'Invalid argument "%s" passed to K.function with TensorFlow backend' % key
2501 raise ValueError(msg)
-> 2502 return Function(inputs, outputs, updates=updates, **kwargs)
2503
2504
/opt/conda/lib/python2.7/site-packages/keras/backend/tensorflow_backend.pyc in __init__(self, inputs, outputs, updates, name, **session_kwargs)
2443 self.inputs = list(inputs)
2444 self.outputs = list(outputs)
-> 2445 with tf.control_dependencies(self.outputs):
2446 updates_ops = []
2447 for update in updates:
/opt/conda/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in control_dependencies(control_inputs)
4302 """
4303 if context.in_graph_mode():
-> 4304 return get_default_graph().control_dependencies(control_inputs)
4305 else:
4306 return _NullContextmanager()
/opt/conda/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in control_dependencies(self, control_inputs)
4015 if isinstance(c, IndexedSlices):
4016 c = c.op
-> 4017 c = self.as_graph_element(c)
4018 if isinstance(c, Tensor):
4019 c = c.op
/opt/conda/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in as_graph_element(self, obj, allow_tensor, allow_operation)
3033
3034 with self._lock:
-> 3035 return self._as_graph_element_locked(obj, allow_tensor, allow_operation)
3036
3037 def _as_graph_element_locked(self, obj, allow_tensor, allow_operation):
/opt/conda/lib/python2.7/site-packages/tensorflow/python/framework/ops.pyc in _as_graph_element_locked(self, obj, allow_tensor, allow_operation)
3122 # We give up!
3123 raise TypeError("Can not convert a %s into a %s." % (type(obj).__name__,
-> 3124 types_str))
3125
3126 def get_operations(self):
TypeError: Can not convert a NoneType into a Tensor or Operation.
Any ideas? 有任何想法吗? Thanks. 谢谢。
The issue is with the line J = tf.gradients(y_list[i], x_list[j])
. 问题在于行J = tf.gradients(y_list[i], x_list[j])
。 x_list[j]
was derived from model.input[0]
, but there's no directed path from x_list[j]
to model.output[0]
. x_list[j]
是从model.input[0]
派生的,但是没有从x_list[j]
到model.output[0]
定向路径。 You need to either unstack the model input, restack then run the model, or create the derivative with respect to the entire input and just select the j
th row from there. 您需要拆开模型输入,重新堆叠然后运行模型,或者相对于整个输入创建导数,然后从此处选择第j
行。
First way: 第一种方式:
inputs = tf.keras.Inputs((100,))
uninteresting, interesting, more_uninteresting = tf.split(inputs, [50, 10, 40], axis=1)
inputs = tf.concat([uninteresting, interesting, more_uninteresting], axis=1)
model = Model(inputs)
...
J, = tf.gradients(y_list[i], interesting)
Second way: 第二种方式:
J, = tf.gradients(y_list[i], model.input[0])
J = J[:, 50:60]
Having said that, this is still going to be slow for a large number of y
indices, so I'd strongly encourage you to be absolutely sure you need the Jacobian itself (and not, for example, the result of a Jacobian-vector product). 话虽如此,但对于许多y
索引来说,这仍然会很慢,因此,我强烈建议您绝对确定自己需要Jacobian函数(而不是例如Jacobian向量积的结果) )。
In case anyone is wanting a full solution regarding @DomJacks answer: 如果有人想要有关@DomJacks的完整解决方案,请回答:
from keras.models import Model
from keras.layers import Dense, Input, Concatenate
import tensorflow as tf
import keras.backend as K
import numpy as np
num_features = 100
input_ = Input(shape=(num_features,))
output_ = Dense(10)(input_)
model = Model(input_,output_)
# input range of interest
x_range = [50,70]
# output indices of interest
y_indices = [2,3,4]
# If model is saved, you can load using:
#model = keras.models.load_model(filepath)
# then grab the input:
input_ = model.input
# Split inputs
uninteresting, interesting, more_uninteresting = tf.split(input_, [x_range[0],
x_range[1]-x_range[0],
num_features-x_range[1]],
axis=1)
# Create new process
inputs = Concatenate()([uninteresting, interesting, more_uninteresting])
y = model(inputs)
y_list = tf.unstack(y[0])
x = np.random.random((1,num_features))
# Create Jacobian matrix
jacobian_matrix = []
for i in y_indices:
J = tf.gradients(y_list[i], interesting)
jacobian_func = K.function([input_, K.learning_phase()], J)
jac = jacobian_func([x, False])[0][0]
jacobian_matrix.append(jac)
jacobian_matrix = np.array(jacobian_matrix)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.