Здравствуйте,
В настоящее время я пытаюсь вычислить градиенты в Tensorflow 1.13.1 и использую класс GradientTape
, как описано в официальной документации ,но я получаю TypeError: Fetch argument None has invalid type <class 'NoneType'>
.
Ниже я приведу два простых случая, когда я получаю эту ошибку, используя только готовую функцию Tensorflow, первый из которых - более простой минимальный рабочий пример, ивторой, который мне действительно нужно решить / обойти.Для полноты я использую Python 3.6.8 .
Упрощенный
import tensorflow as tf
tf.reset_default_graph()
x = tf.constant([1., 2., 3.])
with tf.GradientTape(persistent=True) as gg:
gg.watch(x)
f1 = tf.map_fn(lambda a: a**2, x)
f2 = x*x
# Computes gradients
d_fx1 = gg.gradient(f1, x) #Line that causes the error
d_fx2 = gg.gradient(f2, x) #No error
del gg #delete persistent GradientTape
with tf.Session() as sess:
d1, d2 = sess.run((d_fx1, d_fx2))
print(d1, d2)
В этом коде f1
и f2
вычисляются по-разному, но дать тот же массив.Однако при попытке вычислить связанные с ними градиенты, первая строка дает следующую ошибку, тогда как вторая строка работает без нареканий.Я сообщаю ниже трассировки стека ошибки
TypeError Traceback (most recent call last)
<ipython-input-1-9c59a2cf2d9b> in <module>()
15
16 with tf.Session() as sess:
---> 17 d1, d2 = sess.run((d_fx1, d_fx2))
18 print(d1, d2)
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in run(self, fetches, feed_dict, options, run_metadata)
927 try:
928 result = self._run(None, fetches, feed_dict, options_ptr,
--> 929 run_metadata_ptr)
930 if run_metadata:
931 proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in _run(self, handle, fetches, feed_dict, options, run_metadata)
1135 # Create a fetch handler to take care of the structure of fetches.
1136 fetch_handler = _FetchHandler(
-> 1137 self._graph, fetches, feed_dict_tensor, feed_handles=feed_handles)
1138
1139 # Run request and get response.
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in __init__(self, graph, fetches, feeds, feed_handles)
469 """
470 with graph.as_default():
--> 471 self._fetch_mapper = _FetchMapper.for_fetch(fetches)
472 self._fetches = []
473 self._targets = []
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in for_fetch(fetch)
259 elif isinstance(fetch, (list, tuple)):
260 # NOTE(touts): This is also the code path for namedtuples.
--> 261 return _ListFetchMapper(fetch)
262 elif isinstance(fetch, collections.Mapping):
263 return _DictFetchMapper(fetch)
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in __init__(self, fetches)
368 """
369 self._fetch_type = type(fetches)
--> 370 self._mappers = [_FetchMapper.for_fetch(fetch) for fetch in fetches]
371 self._unique_fetches, self._value_indices = _uniquify_fetches(self._mappers)
372
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in <listcomp>(.0)
368 """
369 self._fetch_type = type(fetches)
--> 370 self._mappers = [_FetchMapper.for_fetch(fetch) for fetch in fetches]
371 self._unique_fetches, self._value_indices = _uniquify_fetches(self._mappers)
372
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in for_fetch(fetch)
256 if fetch is None:
257 raise TypeError('Fetch argument %r has invalid type %r' % (fetch,
--> 258 type(fetch)))
259 elif isinstance(fetch, (list, tuple)):
260 # NOTE(touts): This is also the code path for namedtuples.
TypeError: Fetch argument None has invalid type <class 'NoneType'>
Обратите внимание, что я также пытался вычислять только один градиент за раз, то есть с persistent=False
, и получил те же результаты.
Фактическая потребность
Ниже я приведу также минимальный рабочий пример для воспроизведения той же ошибки, что и я, но пытаюсь решить проблему, над которой я на самом деле работаю.
В этом коде я 'используя RNN
для вычисления выхода с некоторыми входами, и мне нужно вычислить jacobian
этого выхода с входами.
import tensorflow as tf
from tensorflow.keras.layers import RNN, GRUCell
# Define size of variable. TODO: adapt to data
inp_dim = 2
num_units = 50
batch_size = 100
timesteps = 10
# Reset the graph, so as to avoid errors
tf.reset_default_graph()
# Building the model
inputs = tf.ones(shape=(timesteps, batch_size, inp_dim))
# Follow gradient computations
with tf.GradientTape() as g:
g.watch(inputs)
cells = [GRUCell(num_units), GRUCell(num_units)]
rnn = RNN(cells, time_major=True, return_sequences=True)
f = rnn(inputs)
d_fx = g.batch_jacobian(f, inputs)
# Run graph
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
grads = sess.run(d_fx)
grads.shape
Что касается трассировки стека, я получаю ту же ошибку, но с меньшим количеством строк (в этой трассировке стека меньше на for_fetch
, <listcomp>
и __init
).Для полноты я все еще включаю его ниже
TypeError Traceback (most recent call last)
<ipython-input-5-bb2ce4eebe87> in <module>()
25 with tf.Session() as sess:
26 sess.run(tf.global_variables_initializer())
---> 27 grads = sess.run(d_fx)
28 grads.shape
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in run(self, fetches, feed_dict, options, run_metadata)
927 try:
928 result = self._run(None, fetches, feed_dict, options_ptr,
--> 929 run_metadata_ptr)
930 if run_metadata:
931 proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in _run(self, handle, fetches, feed_dict, options, run_metadata)
1135 # Create a fetch handler to take care of the structure of fetches.
1136 fetch_handler = _FetchHandler(
-> 1137 self._graph, fetches, feed_dict_tensor, feed_handles=feed_handles)
1138
1139 # Run request and get response.
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in __init__(self, graph, fetches, feeds, feed_handles)
469 """
470 with graph.as_default():
--> 471 self._fetch_mapper = _FetchMapper.for_fetch(fetches)
472 self._fetches = []
473 self._targets = []
C:\HOMEWARE\Miniconda3-Windows-x86_64\envs\rdwsenv\lib\site-packages\tensorflow\python\client\session.py in for_fetch(fetch)
256 if fetch is None:
257 raise TypeError('Fetch argument %r has invalid type %r' % (fetch,
--> 258 type(fetch)))
259 elif isinstance(fetch, (list, tuple)):
260 # NOTE(touts): This is also the code path for namedtuples.
TypeError: Fetch argument None has invalid type <class 'NoneType'>
Я чувствую, что есть ошибка с какой-то функцией Tensorflow, которая выдает мне ошибку, однако я не уверен.В конце концов, меня интересует получение tensor
, содержащее jacobian вывода моей сети относительно входов.Как я могу добиться этого, используя другие инструменты или исправляя мой код?
EDIT : Хорошо, поэтому я принял во внимание комментарии danyfang и попытался разобраться в проблеме, поднятой на Github.он процитировал tf.gradients
, возвращающее None
вместо 0
из-за некоторого дизайна реализации в низкоуровневом Tensorflow.
Поэтому я попытался создать простой случай, в котором я уверен, что градиент отличается от0
, вычислением tf.matmul(tf.transpose(x), x)
.Я публикую ниже MWE.
import tensorflow as tf
tf.reset_default_graph()
x = tf.constant([[1., 2., 3.]])
with tf.GradientTape(persistent=True) as gg:
gg.watch(x)
y = tf.matmul(x, tf.transpose(x))
f1 = tf.map_fn(lambda a: a, y)
# Computes gradients
d_fx1 = gg.gradient(f1, x)
d_yx = gg.gradient(y, x)
del gg #delete persistent GradientTape
with tf.Session() as sess:
#d1 = sess.run(d_fx1) # Same error None type
d2 = sess.run(d_yx) #Works flawlessly. returns array([[2., 4., 6.]], dtype=float32)
d2
Это показывает (по крайней мере, на мой взгляд), что ошибка возникает не из-за поведения, о котором сообщает эта проблема , а из-зареализация более низкого уровня.