Tensorflow报错:TypeError: Fetch argument None has invalid type class ‘NoneType’

Tensorflow报错:TypeError: Fetch argument None has invalid type class ‘NoneType’在使用tensorflow中经常会出现这个错误,但是原因往往各不相同。第一种情况:在tensorflow的计算图中,我们可以利用函数def来封装一些tf操作,但是我们需要使用return语句去规避一些错误,看如下分析:看如下程序:importtensorflowastfa=tf.Variable(5.0)defadd():a_change=t…

在使用tensorflow中经常会出现这个错误,但是原因往往各不相同。

第一种情况:

在tensorflow的计算图中,我们可以利用函数def来封装一些tf操作,但是我们需要使用return语句去规避一些错误,看如下分析:

看如下程序:

import tensorflow as tf
 
a = tf.Variable(5.0)
 
 
def add():
    a_change = tf.assign(a, 10.0)
 
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

运行之后,显示如下错误:
Traceback (most recent call last):
File “E:/PythonProject/cnn_cifar10.py”, line 12, in
print(sess.run(add()))
File “E:\Python\lib\site-packages\tensorflow\python\client\session.py”, line 889, in run
run_metadata_ptr)
File “E:\Python\lib\site-packages\tensorflow\python\client\session.py”, line 1105, in _run
self._graph, fetches, feed_dict_tensor, feed_handles=feed_handles)
File “E:\Python\lib\site-packages\tensorflow\python\client\session.py”, line 414, in init
self._fetch_mapper = _FetchMapper.for_fetch(fetches)
File “E:\Python\lib\site-packages\tensorflow\python\client\session.py”, line 231, in for_fetch
(fetch, type(fetch)))
TypeError: Fetch argument None has invalid type <class ‘NoneType’>

此时表明add()没有fetch到参数,因此我们需要对函数里的操作添加return操作:

import tensorflow as tf
 
a = tf.Variable(5.0)
 
 
def add():
    a_change = tf.assign(a, 10.0)
    return a_change
 
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

输出:

10.0
10.0

如果函数中封装了多个操作,就要分情况了

如下程序:

import tensorflow as tf
 
a = tf.Variable(5.0)
 
 
def add():
    a_change = tf.assign(a, 10.0)
    a_plus_1 = tf.assign_add(a, 1.0)
    return a_change
 
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

输出:

10.0
10.0

此时def中有2个操作,但是只return了a_change,所以会获取到参数,不会出现之前的错误,但是由于没有return a_plus_1操作,所以只运行了a_change操作,所以需要同时return 这2个操作,return的顺序无所谓,修改如下:

import tensorflow as tf
 
def add():
    a_change = tf.assign(a, 10.0)
    a_plus_1 = tf.assign_add(a, 1.0)
    return a_plus_1, a_change
 
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

输出:

(10.0, 11.0)

11.0

当然,也不一定def封装的操作全部return,如果上一个操作返回的值被现操作使用,则只return现操作即可:

a = tf.Variable(5.0)
 
import tensorflow as tf
 
a = tf.Variable(5.0)
 
 
def add():
    a_change = tf.assign(a, 10.0)
    y = a_change + 1
    return y
 
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

输出:

11.0

10.0

关于用def函数进行封装的操作是否在tf计算图上的说明:

import tensorflow as tf
 
a = tf.Variable(5.0)
 
 
def add():
    a_change = tf.assign(a, 10.0)
    return a_change



sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

上述的tf操作被封装在add()函数中,没有被放在计算图中,若要放在计算图中,则需要调用函数:

import tensorflow as tf
 
a = tf.Variable(5.0)
 
 
def add():
    a_change = tf.assign(a, 10.0)
    return a_change
 
 
add()
 
sess = tf.Session()
sess.run(tf.global_variables_initializer())
print(sess.run(add()))
print(sess.run(a))

Tensorflow gradients好像不支持 int型的Tensor 的gradients 把w1的设置成float类型的例如tf.float32 gards就能算了,而且tensorflow梯度值一般都是float32类型的。




第二种情况:

第二种情况跟第一种情况是一类情况。。
https://blog.csdn.net/blythe0107/article/details/72818047
Tensorflow报错:

TypeError: Fetch argument None has invalid type <class 'NoneType'>

报错完整内容:

 File "D:/Workspace/SpyderWorkspace/Models/RBM_mnist.py", line 211, in main
    sess.run(rbm.train_ops(k, step, i),feed_dict={X: X_batch})
 
  File "D:\Program Files\Anaconda3\lib\site-packages\tensorflow\python\client\session.py", line 767, in run
    run_metadata_ptr)
 
  File "D:\Program Files\Anaconda3\lib\site-packages\tensorflow\python\client\session.py", line 952, in _run
    fetch_handler = _FetchHandler(self._graph, fetches, feed_dict_string)
 
  File "D:\Program Files\Anaconda3\lib\site-packages\tensorflow\python\client\session.py", line 408, in __init__
    self._fetch_mapper = _FetchMapper.for_fetch(fetches)
 
  File "D:\Program Files\Anaconda3\lib\site-packages\tensorflow\python\client\session.py", line 227, in for_fetch
    (fetch, type(fetch)))
 
TypeError: Fetch argument None has invalid type <class 'NoneType'>

发现是从sess.run()那行报错。
构建图的代码中,RBM是一个类,train_ops是该类下的函数。rbm是类RBM的一个对象,调用train_ops函数。

train_ops函数定义如下:

def train_ops(self, k, step, batch_count):
        ...(省略)
            with tf.name_scope("update_params"):
                tf.assign(self.W, self.W + self.learning_rate * delta_W,name="update_W")
                tf.assign(self.bv, self.bv + self.learning_rate*delta_bv,name="update_bv")
                tf.assign(self.bh, self.bh + self.learning_rate*delta_bh,name="update_bh")

函数的主要功能是更新参数,于是定义了更新参数操作。而报错的原因在于定义的train_ops函数没有返回值。
正确的代码如下:

def train_ops(self, k, step, batch_count):
        ...(省略)
            with tf.name_scope("update_params"):
                new_W = tf.assign(self.W, self.W + self.learning_rate * delta_W,name="update_W")
                new_bv = tf.assign(self.bv, self.bv + self.learning_rate*delta_bv,name="update_bv")
                new_bh = tf.assign(self.bh, self.bh + self.learning_rate*delta_bh,name="update_bh")
            return (new_W, new_bv, new_bh)

至此,报错解决。




第三种情况:

这种情况其实比较傻。。
https://blog.csdn.net/qq_41000891/article/details/84555225

写了一个TensorFlow卷积神经网络的训练程序。

基于mnist数据集进行训练和测试。

但是在程序运行的时候报出了下面的错误。

Traceback (most recent call last):
  File "nn_eg.py", line 104, in <module>
    train_loss, train_op = sess.run([loss, train_op], {input_x: batch[0], output_y: batch[1]})
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 929, in run
    run_metadata_ptr)
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1137, in _run
    self._graph, fetches, feed_dict_tensor, feed_handles=feed_handles)
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 471, in __init__
    self._fetch_mapper = _FetchMapper.for_fetch(fetches)
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 261, in for_fetch
    return _ListFetchMapper(fetch)
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 370, in __init__
    self._mappers = [_FetchMapper.for_fetch(fetch) for fetch in fetches]
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 370, in <listcomp>
    self._mappers = [_FetchMapper.for_fetch(fetch) for fetch in fetches]
  File "/home/zhonghangalex/venv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 258, in for_fetch
    type(fetch)))
TypeError: Fetch argument None has invalid type <class 'NoneType'>

这里我们看到错误指向的是代码的104行,我将这部分的代码贴出来:

 # 训练神经网络
for i in range(20000):
	batch = mnist.train.next_batch(50) #从Train(训练)数据集里取下一个50样本
	train_loss, train_op = sess.run([loss, train_op], {input_x: batch[0], output_y: batch[1]})
	if i % 100 == 0:
		test_accuracy = sess.run(accuracy, {input_x: test_x, output_y: test_y})
		print("Step=%d, Train loss=%.4f, [Test accuracy=%.2f]" % (i, train_loss, test_accuracy))

这是对神经网络训练的过程,指定训练20000步,有一个奇怪的现象就是,循环的第一步进行得很顺畅,可是从第二步开始就报了这个错误:
在这里插入图片描述
这就说明了应该是变量出现了问题。

查阅资料后发现是因为:

train_op变量重新分配给结果的第二个元素sess.run()(恰好是None)。因此,在第二次迭代中,train_op是None,这导致错误。 解决的方法很简单,就是把两个变量的第二个变量改为“_”:

# 训练神经网络
for i in range(20000):
	batch = mnist.train.next_batch(50) #从Train(训练)数据集里取下一个50样本
	train_loss, _ = sess.run([loss, train_op], {input_x: batch[0], output_y: batch[1]})
	if i % 100 == 0:
		test_accuracy = sess.run(accuracy, {input_x: test_x, output_y: test_y})
		print("Step=%d, Train loss=%.4f, [Test accuracy=%.2f]" % (i, train_loss, test_accuracy))

这样便成功开始了训练:
在这里插入图片描述
更多请参考;https://coding.imooc.com/learn/questiondetail/43916.html

说点题外话

注意新手要注意避免梯度检查,以及除零,以及softmax损失值中的nan,inf,以及e的指数次方等问题。
编码问题也很重要,源代码文件第一行添加:#coding:utf-8,这样就可以避免了,

runfile('E:/hnudianshuji/TensorFlow/class4/train_tfrecord.py', wdir='E:/hnudianshuji/TensorFlow/class4')



第四种情况:

我觉得这种情况可能比较重要。

https://blog.csdn.net/u012526003/article/details/61749863

代码网址:

https://github.com/littletomatodonkey/tensorflow_practice/

AlexNet

代码网址

https://github.com/littletomatodonkey/tensorflow_practice/blob/master/alexnet_benchmark.py

跑分结果图
在这里插入图片描述

VGGNet

代码网址

https://github.com/littletomatodonkey/tensorflow_practice/blob/master/vggnet_benchmark.py

跑分结果图
在这里插入图片描述

GoogleInceptionNet

ResNet

遇到的问题
类型无效或者为NoneType

TypeError: Fetch argument None has invalid type
  • gradient中的因变量必须与所有的自变量均有关系,才能进行梯度的求解,否则会报这个错误
  • 出现原因:之前搭建网络时,写错了一个变量,导致少了一层cnn,但是变量仍然被考虑进去了,最后的优化结果却与该变量无关,在求gradient(sess.run())时,出现了该问题
  • 参考的链接:http://blog.csdn.net/u012436149/article/details/53905797

或者可以看看stackoverflow上面提问:
https://stackoverflow.com/questions/49272228/tensorflow-typeerror-fetch-argument-none-has-invalid-type-class-nonetype-wh
在这里插入图片描述
主要意思也是说,无关变量,无法求导。

https://cloud.tencent.com/developer/ask/202312/answer/314611
如果图中它们之间没有显式连接,则返回梯度。 在您的代码中,似乎所有声明的变量都有连接,因此可能是从其他图形加载变量的情况。 您可以使用:

print([v.name for v in tf.all_variables()])

并且仅检查预期变量是此图的一部分。

print([v.name for v in tf.all_variables()])
并且仅检查预期变量是此图的一部分。




第五种情况:

这种情况其实是我真正遇到的问题,其实也算是第四种情况的升级版。。

起因:本来想看看

g = tf.get_default_graph()
with g.gradient_override_map({"Sign": "Identity"}):

对tf.sign函数的影响,发现这个确实有用。
可以看看下面两段代码:

import tensorflow as tf

w1 = tf.constant([2])
w2 = tf.constant([3])
temp = tf.multiply(w1, w2)

g = tf.get_default_graph()
#with g.gradient_override_map({"Sign": "Identity"}):
res = tf.sign(temp*2)
grads = tf.gradients(res,[w1,w2])
with tf.Session() as sess:
     tf.global_variables_initializer().run()
     re = sess.run(grads)
     print(re)

########################分割线,注释下面所有的代码,运行上面的代码,或者注释上面所有的代码,运行下面的代码,比较结果不同#####################################
import tensorflow as tf

w1 = tf.constant([2])
w2 = tf.constant([3])
temp = tf.multiply(w1, w2)

g = tf.get_default_graph()
with g.gradient_override_map({"Sign": "Identity"}):
     res = tf.sign(temp*2)
grads = tf.gradients(res,[w1,w2])
with tf.Session() as sess:
     tf.global_variables_initializer().run()
     re = sess.run(grads)
     print(re)

你甚至还可以自己注册标志并定义函数:

import tensorflow as tf
import tensorlayer as tl
import numpy as np



@tf.RegisterGradient("aQuantizeGrad")
def _sign_grad(tytyteyydoop,grad):

    return tf.clip_by_value(grad, -1, 10)


def sign(x):

    with tf.get_default_graph().gradient_override_map({"Sign": "aQuantizeGrad"}):

        return tf.sign(x, name='sign')

w1 = tf.Variable(4)
w2 = tf.Variable(3)
a = tf.multiply(w1,w2)
#g = tf.get_default_graph()
#with g.gradient_override_map({"Sign":"Sign_QuantizeGrad"}):
    #clip = tf.sign(a)
#clip = tf.maximum(w1, w2)
clip = sign(a)
m = tf.multiply(clip,3)    
m = tf.multiply(clip,-2)    
m = tf.multiply(clip,13)    
gradients = tf.gradients(m, xs=[w1,w2])
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    print(sess.run(m))
    print(sess.run(gradients))

题外话:
如果自己自定义(然后通过注册的方式),可以实现基本的自定义的梯度回传的,其次还可以同另外一个函数tf.pyfunc来实现自定义梯度回传。但这只是最基本,想自定义更加高级的操作,则需要去改底层代码,注册更多函数,甚至重新编译安装。

回到话题,于是我想看看这样的效果:

import tensorflow as tf

 
#w1 = tf.constant([-2.0,-1.0])

g = tf.get_default_graph()

    #res = tf.sign(w1)
#res=tf.where(tf.greater(w1,0.0),w1, tf.zeros_like(w1, tf.float32))

def _compute_threshold(x):
    """
    ref: https://github.com/XJTUWYD/TWN
    Computing the threshold.
    """
    x_sum = tf.reduce_sum(tf.abs(x), reduction_indices=None, keep_dims=False, name=None)
    threshold = tf.div(x_sum, tf.cast(tf.size(x), tf.float32), name=None)
    threshold = tf.multiply(0.7, threshold, name=None)
    return threshold

W = tf.constant([2.0,-1.0])

    
threshold = _compute_threshold(W)

g = tf.get_default_graph()
with g.gradient_override_map({"Greater": "Identity"}):
    with g.gradient_override_map({"Where": "Identity"}):
        alpha1_temp1 = tf.where(tf.greater(W, 1.0), W, tf.zeros_like(W, tf.float32))

alpha1_temp2 = tf.where(tf.less(W, -0.5), W, tf.zeros_like(W, tf.float32))
alpha_array = tf.add(alpha1_temp1, alpha1_temp2, name=None)
alpha_array_abs = tf.abs(alpha_array)
alpha_array_abs1 = tf.where(tf.greater(alpha_array_abs, 0), tf.ones_like(alpha_array_abs, tf.float32), tf.zeros_like(alpha_array_abs, tf.float32))
alpha_sum = tf.reduce_sum(alpha_array_abs)
n = tf.reduce_sum(alpha_array_abs1)
alpha = tf.div(3.0, n)



#W = tf.get_variable(name='W', shape=(10, 10), dtype=tf.float32)

            # W = tl.act.sign(W)    # dont update ...

grads = tf.gradients(alpha1_temp1 ,W)
 
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    re = sess.run(grads)
    print(re)
    print(sess.run(threshold))
    print(sess.run(alpha_array_abs))
    print(sess.run(alpha))

结果发现,这种情况,其实吧,你要是了解tf.where以及tf.greater就更好了。。这两个函数更像是关系运算,而关系运算对于这种静态图框架,可以说是一大软肋。。而这种关系运算如果想建立梯度关系的话,一般要么是设置none(不可导),要么直接设置梯度0,或者identity,也就是梯度1。
而我发现,后来想想,其实也应该这样,上面的g.gradient_override_map好像加了与不加,没什么关系。。其实也可能是这几个函数自身就设置了identity吧。

更重要的是,上面的函数,如果原变量与输出变量不建立运算关系的话,是无法计算梯度的,若强行直接计算会报上面一直提的错误信息。但是如果这个关系运算(或者称为与原变量无关的运算),参与了后面其他与原变量的运算(操作),那么之前那个也自然不会报错,直接跳过无关运算的求导(自动处理)。
比如你可以试试:

alpha1_temp1 = tf.where(tf.greater(W, 1.0), W, tf.zeros_like(W, tf.float32))
alpha1_temp1 = tf.where(tf.greater(W, 3.0), W, tf.zeros_like(W, tf.float32))
alpha1_temp1 = tf.where(tf.greater(W, 1.0), W, W)
alpha1_temp1 = tf.where(tf.greater(W, 3.0), W, W)

分别求tf.gradients(alpha1_temp1,W),看看效果。

alpha = tf.div(3.0, n),如果直接tf.gradients(alpha,W),或者tf.gradients(n,W),都是会直接报错的。
alpha = tf.div(W*W, n)或者alpha = tf.div(alpha_sum, n),就不会报错,可以顺利求导,而且我也认为这样是合理的。

切记切记,tensorflow是图,计算图,一种图模型,你始终是在构建一个计算模型(姑且可以认为它是静态计算图)。
要想参与计算,包括梯度计算,必须要有对应算子参与构建数据流图,最终形成一张计算图,这样才能启动tensorflow引擎。。




除此之外,再介绍一种特别相似的报错,如下:

TypeError: ‘NoneType’ object is not callable

这种报错暂时还不算严重的错误,通过重新运行代码可以避免。。

暂时还不知道原因,但是往往与上面的使用一样,也就是这些与特殊函数使用有关,所以这里也建议,最好不要随便使用这些函数作为梯度反传要经过的操作,否则可能得不到想要的结果,毕竟它们归根到底是条件表达式,tensorflow这些框架可能不是太支持,也不够稳定。要真正使用自定义的函数以及梯度反传,还是需要自己设计并注册函数的,当然这是另外一个话题了。。

print("100000000000000000000000000000000000000000")
import tensorflow as  tf

def _compute_threshold(x):
    """
    ref: https://github.com/XJTUWYD/TWN
    Computing the threshold.
    """
    x_sum = tf.reduce_sum(tf.abs(x), reduction_indices=None, keep_dims=False, name=None)
    threshold = tf.div(x_sum, tf.cast(tf.size(x), tf.float32), name=None)
    threshold = tf.multiply(0.7, threshold, name=None)
    return threshold


def _compute_alpha(x):
    """
    Computing the scale parameter.
    """
    threshold = _compute_threshold(x)
    alpha1_temp1 = tf.where(tf.greater(x, threshold), x, tf.zeros_like(x, tf.float32))
    alpha1_temp2 = tf.where(tf.less(x, -threshold), x, tf.zeros_like(x, tf.float32))
    alpha_array = tf.add(alpha1_temp1, alpha1_temp2, name=None)
    alpha_array_abs = tf.abs(alpha_array)
    alpha_array_abs1 = tf.where(tf.greater(alpha_array_abs, 0), tf.ones_like(alpha_array_abs, tf.float32), tf.zeros_like(alpha_array_abs, tf.float32))
    alpha_sum = tf.reduce_sum(alpha_array_abs)
    n = tf.reduce_sum(alpha_array_abs1)
    alpha = tf.div(alpha_sum, n)
    return alpha

def _ternary_operation(x):
    """
    Ternary operation use threshold computed with weights.
    """
    g = tf.get_default_graph()
    with g.gradient_override_map({"Sign": "Identity"}):
        threshold = _compute_threshold(x)
        x = tf.sign(tf.add(tf.sign(tf.add(x, threshold)), tf.sign(tf.add(x, -threshold))))
        return x


W = tf.get_variable(name='W', shape=(10, 10), dtype=tf.float32)
            # W = tl.act.sign(W)    # dont update ...
alpha = _compute_alpha(W)

W1 = _ternary_operation(W)
W2 = tf.multiply(alpha, W1)

grads1 = tf.gradients(W2 ,W)

grads2 = tf.gradients(alpha ,W)

grads3 = tf.gradients(W1 ,W)

grads4 = tf.gradients(W2 ,W1)

grads5 = tf.gradients(W2 ,alpha)
res=tf.multiply(alpha,grads3) + tf.multiply(tf.reduce_sum(W1),grads2)
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    re = sess.run(grads1)
    print(re)
    print(sess.run(grads2))
    print(sess.run(grads3))
    print(sess.run(alpha))
    print(sess.run(W1))

    print(sess.run(grads4))
    print(sess.run(grads5))
    
    print(sess.run(res))
    print(sess.run(res)==sess.run(grads1))

如果报错,可能显示如下,这是你需要重新运行。。
在这里插入图片描述
如果不报错,输出如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
你还可以看看这个,便于对上面理解:

import tensorflow as tf

a=tf.constant([1,2,3])

b=a
c=tf.reduce_sum(a)

d=tf.multiply(b,c)

sess.run(tf.gradients(d,a))
sess.run(tf.gradients(d,b))
sess.run(tf.gradients(d,c))


a=tf.constant([1,2,3])

b=tf.multiply(1,a)
c=tf.reduce_sum(a)

d=tf.multiply(b,c)

sess.run(tf.gradients(d,a))
sess.run(tf.gradients(d,b))
sess.run(tf.gradients(d,c))


a=tf.constant([1,2,3])

b=tf.multiply(2,a)
c=tf.reduce_sum(a)

d=tf.multiply(b,c)

sess.run(tf.gradients(d,a))
sess.run(tf.gradients(d,b))
sess.run(tf.gradients(d,c))



a=tf.constant([1,2,3])

b=tf.multiply(a,a)

d=tf.multiply(b,a)

sess.run(tf.gradients(b,a))
sess.run(tf.gradients(d,a))
sess.run(tf.gradients(d,b))


a=tf.constant([1,2,3])

b=tf.reduce_sum(a)

c=tf.multiply(a,b)

sess.run(tf.gradients(c,a))

讲真要全部弄懂上面的输出,还是需要功夫的,需要了解的几点就是,链式法则,全导数与偏导数,计算精度(四舍五入),矩阵,向量以及变量之间相互求导。

更多可以参考:
https://www.cnblogs.com/weiyinfu/p/10071955.html

今天的文章Tensorflow报错:TypeError: Fetch argument None has invalid type class ‘NoneType’分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/31966.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注