今天的代码一直遇见下列错误, 烦不胜烦。其实就是因为在进行优化求损失函数最小值的时候,找不到需要梯度下降的变量,提示的是要检查损失函数。
([str(v) for _, v in grads_and_vars], loss))
ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables [] and loss <function loss at 0x000001ABF60B2488>.
我的出错代码如下。
train_logits = inference(train_batch, BATCH_SIZE, N_CLASSES)
def loss():
return tf.nn.sparse_softmax_cross_entropy_with_logits(labels=train_label_batch,logits=train_logits ) )#infere
optimizer.minimize(loss=loss)
按我的理解,优化过程的第一步其实就是求梯度。这个过程就是根据输入的损失函数,提取其中的变量,进行梯度下降,使整个损失函数达到最小值。首先想的是怎么提取损失函数中的变量呢?
查看官网,我们可以看到optimizer.minimize
函数的变量列表,其实就是variables类型的元组或者列表。那理想中的梯度下降过程,其实就是利用标签和预测值求损失函数,再对从预测模型引入的variables变量进行梯度下降,以减小损失函数。
那其实,损失函数作为预测模型和优化模型的桥梁,肯定要做到传递变量的作用。我们使用下面这个关于初次使用tensorflow遇到的坑的代码,直观看一下错误处在了哪里,再对症下药。源代码肯定是可以运行成功的,但我们稍微做一些修改。其实就是把return tf.keras.losses.MSE(y_data, Weights*x_data+biases)
修改成w=Weights*x_data+biases def loss(): return tf.keras.losses.MSE(y_data, w)
不再直接传预测模型,而是传入一个变量,虽然这个变量就是原来的预测模型,我们想看根据一个变量,是否梯度下降的时候可以找到对应的变量。
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
# tf.disable_v2_behavior()
# create data
x_data = np.random.rand(100).astype(np.float32) # 一百个随机数列 定义数据类型
y_data = x_data*0.1+0.3 # W为0.3
print(y_data)
# create tensorflow structure start #
# AttributeError: module 'tensorflow' has no attribute 'random_uniform'
# V2版本里面random_uniform改为random.uniform
Weights = tf.Variable(tf.random.uniform((1,), -1.0, 1.0)) # 随机数列生产的参数 [1] W结构为一维 -1.0, 1.0 随机生产数列的范围
# TypeError: 'function' object is not subscriptable
# 一般是少了括号
print(Weights)
biases = tf.Variable(tf.zeros((1,))) # 定义初始值 0
print(biases)
# y = Weights*x_data+biases
# 定义预测值y
w=Weights*x_data+biases
def loss():
print(tf.keras.losses.MSE(y_data, w))
return tf.keras.losses.MSE(y_data, w) # alias 计算loss 预测值与真实值的差别
# AttributeError: module 'tensorflow_core._api.v2.train' has no attribute 'GradientDescentOptimizer'
# "tf.train.GradientDescentOptimizer" change "tf.compat.v1.train.GradientDescentOptimizer"
# `loss` passed to Optimizer.compute_gradients should be a function when eager execution is enabled.
# 神经网络知道误差以后 优化器(optimizer)减少误差 提升参数的准确度
# 其中的minimize可以拆为以下两个步骤:
# ① 梯度计算
# ② 将计算出来的梯度应用到变量的更新中
# 拆开的好处是,可以对计算的梯度进行限制,防止梯度消失和爆炸
# optimizer = tf.compat.v1.train.GradientDescentOptimizer(0.5)
# train = optimizer.minimize(loss)
optimizer = tf.keras.optimizers.SGD(learning_rate=0.5) # alias: tf.optimizers.SGD learning_rate=0.5
#init = tf.initializer_all_variables()
# create tensorflow structure end #
# create session
# sess = tf.Session()
# sess.run(init) # Very important
for step in range(201):
optimizer.minimize(loss,var_list=[Weights,biases])
if step % 20 == 0:
print("{} step, Weights = {}, biases = {}"
.format(step, Weights.read_value(), biases.read_value())) # read_value函数可用numpy替换
运行结果如下:
([v.name for _, v in grads_and_vars],))
ValueError: No gradients provided for any variable: ['Variable:0', 'Variable:0'].
发现发现了需要梯度下降的两个变量[‘Variable:0’, ‘Variable:0’],并不是我们希望的权重和偏置。那这两个值是在哪里产生的呢?
我们打印初始化的权重和偏置
Weights = tf.Variable(tf.random.uniform((1,), -1.0, 1.0))
# 一般是少了括号
print(Weights)
biases = tf.Variable(tf.zeros((1,))) # 定义初始值 0
print(biases)
结果如下,发现正是我们的初始权重和偏置啊。所以还是直接传模型吧,而不是传递一个已经计算好的数值
<tf.Variable 'Variable:0' shape=(1,) dtype=float32, numpy=array([-0.16910172], dtype=float32)>
<tf.Variable 'Variable:0' shape=(1,) dtype=float32, numpy=array([0.], dtype=float32)>
除了直接输入模型,还可以使用下述方法
def loss():
# print(tf.keras.losses.MSE(y_data, w))
w = Weights * x_data + biases
return tf.keras.losses.MSE(y_data, w) # alias 计算loss 预测值与真实值的差别
结果:
哎,就是一直试,慢慢找套路
20 step, Weights = [-0.06692801], biases = [0.39274]
40 step, Weights = [0.05562253], biases = [0.32465476]
60 step, Weights = [0.08820234], biases = [0.30655444]
80 step, Weights = [0.09686362], biases = [0.3017425]
100 step, Weights = [0.09916621], biases = [0.30046323]
120 step, Weights = [0.09977833], biases = [0.30012316]
140 step, Weights = [0.09994107], biases = [0.30003276]
160 step, Weights = [0.09998435], biases = [0.3000087]
180 step, Weights = [0.09999582], biases = [0.30000234]
200 step, Weights = [0.09999889], biases = [0.30000064]
我原来的代码也应该修改成return tf.nn.sparse_softmax_cross_entropy_with_logits(labels=train_label_batch,logits=inference(train_batch, BATCH_SIZE, N_CLASSES) )#inference(train_batch, BATCH_SIZE, N_CLASSES)