笔尖下的自由 2019-07-22 12:48 采纳率: 0%
浏览 1439
已结题

optim.compute_gradients计算梯度 ,为什么返回的第一列为None?

1.问题描述
模型通过keras.models.Sequential构建
loss => tf.losses.sparse_softmax_cross_entropy
通过 var_list=tf.trainable_variables() 获取可训练变量
计算梯度值:
loss_op = tf.losses.sparse_softmax_cross_entropy(y, y_pred)
grads_vars = optim.compute_gradients(loss_op, tf.trainable_variables())
grads_vars返回的第一元素为 None,导致面的程序异常。

 为什么grads_vars第一列返回的元素为None?

2.相关代码

import tensorflow as tf
import numpy as np
import time
import keras

# 加载数据集
x_dataset=np.random.rand(1000,28,28,1)
y_dataset=np.random.randint(0,10,size=(1000,))
act = tf.nn.leaky_relu

epoch = 200
batch_size = 5000
n_batch = len(x_dataset) // batch_size

# 把 batch 分成多少个 sub batch 来计算
subdivisions = 50
subdivisions_batch_size = int(np.ceil(batch_size / subdivisions))

# 是否使用 sub batch 方法,设置为 False 代表使用默认方法
is_on_subdivisions = True
def get_model(is_train=True, reuse=False):
    with tf.variable_scope('model', reuse=reuse):
        net = keras.models.Sequential()
        net.add(keras.layers.Conv2D(128,(3,3),input_shape=(28,28,1),strides=(2,2),padding='same',name='c1'))
        net.add(keras.layers.GlobalAveragePooling2D())
        net.add(keras.layers.Dense(10))
    return net


x = tf.placeholder(tf.float32, [None, 28, 28, 1])
y = tf.placeholder(tf.int32, [None,])

net = get_model()
y_pred=tf.cast(tf.argmax(net.outputs[0],axis=-1),dtype=tf.float32)
loss_op = tf.losses.sparse_softmax_cross_entropy(y, y_pred)
optim = tf.train.AdamOptimizer(0.01)
var_list=tf.trainable_variables()
grads_vars = optim.compute_gradients(loss_op, tf.trainable_variables())
#grads_vars返回的第一列为None,为什么?
for gv in grads_vars:
    print(gv)
# 删掉没梯度的参数, 倒序删除,减少麻烦
for i in range(len(grads_vars))[::-1]:
    if grads_vars[i][0] is None:
        del grads_vars[i]
#因为返回的第一列为None,所以所有变量都被删除了,导致后面的异常!        
print('len(grads_vars):',len(grads_vars))

# 生成梯度缓存:grads_vars第一列为None触发异常
grads_cache = [tf.Variable(np.zeros(t[0].shape.as_list(), np.float32), trainable=False) for t in grads_vars]

# 清空梯度缓存op,每一 batch 开始前调用
clear_grads_cache_op = tf.group([gc.assign(tf.zeros_like(gc)) for gc in grads_cache])

# 累积梯度op,累积每个 sub batch 的梯度
accumulate_grad_op = tf.group([gc.assign_add(gv[0]) for gc, gv in zip(grads_cache, grads_vars)])

# 求平均梯度,
mean_grad = [gc/tf.to_float(subdivisions) for gc in grads_cache]

# 组装梯度列表
new_grads_vars = [(g, gv[1]) for g, gv in zip(mean_grad, grads_vars)]

# 应用梯度op,累积完所有 sub batch 的梯度后,应用梯度
apply_grad_op = optim.apply_gradients(new_grads_vars)


# 原来的 optim ,跟上面做对照
ori_optim_op = tf.train.AdamOptimizer(0.01).minimize(loss_op, var_list=net.all_params)

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
config.allow_soft_placement = True
sess = tf.Session(config=config)
sess.run(tf.global_variables_initializer())


for e in range(epoch):
    loss_sum = 0
    for b in progressbar(range(n_batch)):
        x_batch = x_dataset[b * batch_size: (b + 1) * batch_size]
        y_batch = y_dataset[b * batch_size: (b + 1) * batch_size]

        if is_on_subdivisions:
            # 每一批开始前需要清空梯度缓存
            sess.run(clear_grads_cache_op)

            sub_loss_sum = 0
            for s in range(subdivisions):
                x_sub_batch = x_batch[s * subdivisions_batch_size: (s + 1) * subdivisions_batch_size]
                y_sub_batch = y_batch[s * subdivisions_batch_size: (s + 1) * subdivisions_batch_size]
                if len(x_sub_batch) == 0:
                    break
                feed_dict = {x: x_sub_batch, y: y_sub_batch}
                _, los = sess.run([accumulate_grad_op, loss_op], feed_dict)
                sub_loss_sum += los
            loss_sum += sub_loss_sum / subdivisions

            # 梯度累积完成,开始应用梯度
            sess.run(apply_grad_op)
            # 本批次结束
        else:
            feed_dict = {x: x_batch, y: y_batch}
            _, los = sess.run([ori_optim_op, loss_op], feed_dict)
            loss_sum += los
    time.sleep(0.2)
    print('loss', loss_sum / n_batch)

3.报错信息

grads_vars:
(None, <tf.Variable 'model/c1/kernel:0' shape=(3, 3, 1, 128) dtype=float32_ref>)
(None, <tf.Variable 'model/c1/bias:0' shape=(128,) dtype=float32_ref>)
(None, <tf.Variable 'model/dense_1/kernel:0' shape=(128, 10) dtype=float32_ref>)
(None, <tf.Variable 'model/dense_1/bias:0' shape=(10,) dtype=float32_ref>)
(None, <tf.Variable 'model_1/c1/kernel:0' shape=(3, 3, 1, 128) dtype=float32_ref>)
(None, <tf.Variable 'model_1/c1/bias:0' shape=(128,) dtype=float32_ref>)
(None, <tf.Variable 'model_1/dense_2/kernel:0' shape=(128, 10) dtype=float32_ref>)
(None, <tf.Variable 'model_1/dense_2/bias:0' shape=(10,) dtype=float32_ref>)
(None, <tf.Variable 'model_2/c1/kernel:0' shape=(3, 3, 1, 128) dtype=float32_ref>)
(None, <tf.Variable 'model_2/c1/bias:0' shape=(128,) dtype=float32_ref>)
(None, <tf.Variable 'model_2/dense_3/kernel:0' shape=(128, 10) dtype=float32_ref>)
(None, <tf.Variable 'model_2/dense_3/bias:0' shape=(10,) dtype=float32_ref>)
len(grads_vars): 0

4.尝试过的方法方式
5.相关截图

  • 写回答

1条回答 默认 最新

  • dabocaiqq 2019-07-22 13:50
    关注
    评论

报告相同问题?

悬赏问题

  • ¥15 不同尺寸货物如何寻找合适的包装箱型谱
  • ¥15 求解 yolo算法问题
  • ¥15 虚拟机打包apk出现错误
  • ¥30 最小化遗憾贪心算法上界
  • ¥15 用visual studi code完成html页面
  • ¥15 聚类分析或者python进行数据分析
  • ¥15 三菱伺服电机按启动按钮有使能但不动作
  • ¥15 js,页面2返回页面1时定位进入的设备
  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。