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

TensorFlow:训练后全连接层的标签预测方法及训练异常排查

问题分析与解决方案

我来帮你解决这两个核心问题:训练前后预测结果无变化的bug,以及无需保存模型直接预测新数据的方法。

一、训练前后预测结果不变的原因及修复

你的代码里存在几个关键问题导致了这个异常现象:

1. 变量名笔误

你定义了预测节点predictions = nn(features, hidden_units),但后续调用sess.run(training_predictions)时,training_predictions从未被定义过——这明显是笔误,你实际想调用的是predictions。但即使修正了这个,还有其他深层问题。

2. 预测仅针对单个batch,而非全数据集

你的my_input_fn返回的是批量迭代器,每次sess.run(predictions)只会返回当前batch的预测结果,而不是整个训练集的结果。训练前后你跑的可能是同一个batch(因为迭代器在初始化后第一次取的batch,和训练后取的batch可能重复),导致看起来结果没有变化。

3. 损失函数选择错误

你的任务是回归预测(连续浓度值),但用了分类任务的损失函数sigmoid_cross_entropy_with_logits,这会导致模型训练方向完全错误,甚至参数几乎不更新。回归任务应该用均方误差(MSE)这类适合连续值预测的损失函数。

修复步骤

  • 统一变量名,修正笔误;
  • 编写专门的全量预测输入函数(不shuffle、不重复,一次性加载整个数据集);
  • 替换损失函数为tf.losses.mean_squared_error;
  • 训练后重新获取整个训练集的预测结果,清晰对比训练前后的变化。

二、无需保存模型直接预测新数据的方法

在同一个tf.Session中,训练完成后模型的所有参数已经保存在会话的变量里了,完全不需要保存再加载。你只需要:

  1. 把新数据转换成TensorFlow可处理的张量(直接用DataFrame的.values转成numpy数组即可);
  2. 复用你定义好的nn函数,传入新数据的张量得到预测节点;
  3. 在当前会话中run这个预测节点,就能得到新数据的预测结果。

修正后的完整代码

import pandas as pd
import numpy as np
import tensorflow as tf

# 假设你的conc_out和trans函数已实现
def conc_out(features, trans):
    # 这里替换为你实际的ODE计算逻辑,示例用随机值模拟
    return pd.DataFrame(data=np.random.random_sample([len(features), 2]), columns=['Ca', 'Cb'])
trans = {}  # 示例trans参数

# 生成训练/验证数据
training_features = pd.DataFrame(data=np.random.random_sample([500,3]), columns=['ca','t','T'])
training_labels = conc_out(training_features, trans)
validation_features = pd.DataFrame(data=np.random.random_sample([30,3]), columns=['ca','t','T'])
validation_labels = conc_out(validation_features, trans)  # 修正原代码中用training_features的错误

def my_input_fn(features, targets, batch_size=1, num_epochs=None, shuffle=True):
    # 转换为numpy数组,避免DataFrame的兼容性问题
    ds = tf.data.Dataset.from_tensor_slices((features.values, targets.values))
    if shuffle:
        ds = ds.shuffle(buffer_size=10000)
    ds = ds.batch(batch_size).repeat(num_epochs)
    features, labels = ds.make_one_shot_iterator().get_next()
    return features, labels

# 新增:用于全量数据预测的输入函数(不打乱、只跑一次)
def predict_input_fn(features):
    ds = tf.data.Dataset.from_tensor_slices(features.values).batch(len(features))
    return ds.make_one_shot_iterator().get_next()

def nn(input_features, hidden_layers=[10]):
    net = tf.layers.dense(input_features, hidden_layers[0], activation=tf.nn.sigmoid)
    if len(hidden_layers) > 1:
        for i in range(len(hidden_layers)-1):
            net = tf.layers.dense(net, hidden_layers[i+1], activation=tf.nn.sigmoid)
    logits = tf.layers.dense(net, 2, activation=None)
    return logits

def train_nn_regression_model(
    learning_rate, epochs, batch_size, hidden_units,
    training_examples, training_targets,
    validation_examples, validation_targets):
    # 重置计算图,避免重复定义节点报错
    tf.reset_default_graph()
    
    # 训练用的输入和预测节点
    train_features, train_labels = my_input_fn(training_examples, training_targets, batch_size=batch_size)
    train_predictions = nn(train_features, hidden_units)
    
    # 回归任务用MSE损失函数
    loss = tf.losses.mean_squared_error(labels=train_labels, predictions=train_predictions)
    train_op = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
    
    # 全量训练集的预测节点(用于对比训练前后)
    full_train_input = predict_input_fn(training_examples)
    full_train_predictions = nn(full_train_input, hidden_units)
    
    # 验证集预测节点
    full_val_input = predict_input_fn(validation_examples)
    full_val_predictions = nn(full_val_input, hidden_units)
    
    # 新数据预测示例:用验证集作为新数据演示
    new_data = validation_features
    new_data_input = predict_input_fn(new_data)
    new_data_predictions = nn(new_data_input, hidden_units)
    
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        
        # 训练前的全量训练集预测
        training_predictions_before = pd.DataFrame(data=sess.run(full_train_predictions), columns=['TP_Ca', 'TP_Cb'])
        print("训练前的训练集预测(前10行):")
        print(training_predictions_before.head(10))
        
        # 训练循环
        for epoch in range(epochs):
            epoch_loss = 0
            total_batches = int(training_examples.shape[0] / batch_size)
            for _ in range(total_batches):
                _, loss_value = sess.run([train_op, loss])
                epoch_loss += loss_value
            avg_epoch_loss = epoch_loss / total_batches
            print(f'Epoch : {epoch+1}/{epochs} , 平均Batch损失 = {avg_epoch_loss:.4f}')
        
        # 训练后的全量训练集预测
        training_predictions_after = pd.DataFrame(data=sess.run(full_train_predictions), columns=['TP_Ca', 'TP_Cb'])
        print("\n训练后的训练集预测(前10行):")
        print(training_predictions_after.head(10))
        
        # 验证集预测结果
        val_predictions = pd.DataFrame(data=sess.run(full_val_predictions), columns=['VP_Ca', 'VP_Cb'])
        print("\n验证集预测(前10行):")
        print(val_predictions.head(10))
        
        # 无需保存模型,直接在当前会话预测新数据
        new_predictions = pd.DataFrame(data=sess.run(new_data_predictions), columns=['NP_Ca', 'NP_Cb'])
        print("\n新数据预测(前10行):")
        print(new_predictions.head(10))

# 启动训练
train_nn_regression_model(
    learning_rate=0.002, epochs=10, batch_size=20, hidden_units=[100],
    training_examples=training_features, training_targets=training_labels,
    validation_examples=validation_features, validation_targets=validation_labels)

关键改进点说明

  1. 修正了validation_labels的数据源错误(原代码误用了训练集特征生成标签);
  2. 新增predict_input_fn,确保能一次性获取整个数据集的预测结果;
  3. 替换损失函数为MSE,适配回归预测任务;
  4. 在同一个会话中直接构造新数据的预测节点,实现即时预测,无需保存加载模型;
  5. 训练前后都输出全量训练集的预测结果,能清晰看到训练带来的模型性能变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:03:56