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中,训练完成后模型的所有参数已经保存在会话的变量里了,完全不需要保存再加载。你只需要:
- 把新数据转换成TensorFlow可处理的张量(直接用DataFrame的
.values转成numpy数组即可); - 复用你定义好的
nn函数,传入新数据的张量得到预测节点; - 在当前会话中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)
关键改进点说明
- 修正了
validation_labels的数据源错误(原代码误用了训练集特征生成标签); - 新增
predict_input_fn,确保能一次性获取整个数据集的预测结果; - 替换损失函数为MSE,适配回归预测任务;
- 在同一个会话中直接构造新数据的预测节点,实现即时预测,无需保存加载模型;
- 训练前后都输出全量训练集的预测结果,能清晰看到训练带来的模型性能变化。
内容的提问来源于stack exchange,提问作者Lim Kaizhuo
相关产品推荐
相关产品推荐

