You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow中如何将计算损失应用到图中?报错无优化变量

嘿,我来帮你拆解下这个问题!你遇到的ValueError: No variables to optimize其实是几个小问题凑到一起导致的,咱们一步步理清楚:

核心问题分析

  1. 优化节点不在模型的图上下文里
    你的类专门创建了self.graph来管理所有模型节点,但在discriminator()方法里创建optimize时,没有把这个操作放到self.graph.as_default()的上下文环境中!TensorFlow默认会把新节点加到全局默认图里,而你的模型权重变量都在self.graph里,优化器自然找不到要更新的变量。

  2. 提前Run出模型输出,断开了梯度链
    你先调用self.sess.run(self.dis_output)把专家/新手的输出转成了numpy数组,再用tf.reduce_mean计算损失——这时候的损失张量和模型的权重变量完全没有关联,优化器根本找不到需要优化的对象!必须在计算图里直接完成损失定义,保留损失和变量之间的梯度连接。

  3. 变量名拼写错误
    __init__里你定义的是self.learning_rate_dist,但后面优化器用的是self.learning_rate_dis,这会直接导致属性不存在的错误,得先统一变量名。

修正后的完整代码

import tensorflow as tf
import numpy as np

class Discriminator:  # 类名首字母大写更符合Python规范
    def __init__(self, n_actions, learning_rate):
        self.n_actions = n_actions
        self.learning_rate = learning_rate  # 统一变量名,避免拼写错误
        self.graph = tf.Graph()
        
        # 所有图节点的创建都放在self.graph的上下文里
        with self.graph.as_default():
            # 定义专家和新手动作的输入占位符
            self.expert_input = tf.placeholder(tf.float32, [None, self.n_actions])
            self.novice_input = tf.placeholder(tf.float32, [None, self.n_actions])
            
            # 封装判别器网络,避免重复定义
            def build_discriminator(inputs):
                x = tf.layers.dense(inputs, 16, tf.nn.relu)
                x = tf.layers.dense(x, 16, tf.nn.relu)
                return tf.layers.dense(x, 1)
            
            # 计算专家和新手的判别输出
            expert_out = build_discriminator(self.expert_input)
            novice_out = build_discriminator(self.novice_input)
            
            # 用内置交叉熵函数计算损失,比手动log更稳定(避免log(0)的数值问题)
            expert_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
                logits=expert_out, labels=tf.ones_like(expert_out)
            ))
            novice_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
                logits=novice_out, labels=tf.zeros_like(novice_out)
            ))
            self.total_loss = expert_loss + novice_loss
            
            # 提前定义优化操作,和模型变量在同一个图里
            self.optimizer = tf.train.AdamOptimizer(self.learning_rate).minimize(self.total_loss)
            
            # 初始化所有变量
            init = tf.global_variables_initializer()
            self.sess = tf.Session(graph=self.graph)
            self.sess.run(init)
    
    def train_step(self, expert_actions, novice_actions):
        # 执行一次训练,返回当前损失值
        _, current_loss = self.sess.run(
            [self.optimizer, self.total_loss],
            feed_dict={
                self.expert_input: expert_actions.astype(np.float32),
                self.novice_input: novice_actions.astype(np.float32)
            }
        )
        return current_loss

if __name__ == '__main__':
    d = Discriminator(2, 0.001)
    # 注意输入要匹配placeholder的形状:[batch_size, n_actions],转成float32类型
    expert_actions = np.random.randint(2, size=(10, 2))
    novice_actions = np.random.randint(2, size=(10, 2))
    loss = d.train_step(expert_actions, novice_actions)
    print(f"第一次训练损失:{loss}")

关键修改点说明

  • 所有图相关操作(包括损失、优化器)都放到self.graph.as_default()上下文里,确保模型变量和优化操作在同一个图中。
  • 用TensorFlow内置的sigmoid_cross_entropy_with_logits计算损失,避免手动tf.log可能出现的数值不稳定问题。
  • 调整输入数据的形状,确保和占位符的[None, n_actions]匹配(原来的一维数组会导致形状不匹配错误)。
  • 把训练逻辑封装成train_step方法,代码结构更清晰。

内容的提问来源于stack exchange,提问作者shunyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:30:14