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

TensorFlow逻辑回归模型训练精度无法稳定提升问题咨询

解决逻辑回归模型训练精度无法提升的问题

我仔细分析了你的代码和问题描述,发现几个核心问题导致模型无法有效学习——哪怕是简单的AND函数任务,都出现了权重趋近于0、输出趋近50%的情况。下面是具体的问题拆解和修复方案:

1. 输入与模型输出的形状不匹配

你的self.y占位符注释标注为1 x num_sents,但实际传入的batch_y是一维数组(比如batch_size=3时形状为(3,)),而模型输出的self.scores形状是(batch_size, 1)(因为num_outputs=1)。这种形状不匹配会导致损失计算时的广播错误,虽然TensorFlow不会直接报错,但损失值的计算逻辑已经偏离预期,模型自然无法学到有效参数。

修复方法:

  • 修改self.y的定义,明确适配批量输入的形状:
    self.y = tf.placeholder(tf.float64, shape=[None, 1], name="placeholdery")
    
  • 在get_batch函数中,将返回的y_b转换为二维数组:
    return (x_b, y_b.reshape(-1, 1))
    

2. 手动计算交叉熵的数值稳定性问题

你手动用tf.clip_by_value避免log(0)的问题,但TensorFlow内置的tf.nn.sigmoid_cross_entropy_with_logits函数已经做了更完善的数值稳定处理,还会自动完成sigmoid转换和交叉熵计算,避免手动实现的潜在误差。

修复方法:
替换你的损失计算代码为:

self.scores = tf.add(self.wx, self.b)
# 用内置函数计算交叉熵,自动处理数值稳定
self.loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=self.scores, labels=self.y))
# 若需要正则化,取消注释下方代码(tf.nn.l2_loss已包含0.5因子)
# self.loss += self.reg_const * tf.nn.l2_loss(self.w)

这样可以删掉手动计算probs和clip_by_value的代码,简化逻辑同时提升稳定性。

3. 学习率设置不合理

Adam优化器的默认学习率是0.001,你设置的self.eta=0.01偏大,容易导致训练过程中权重震荡甚至发散,最终模型“放弃学习”,权重逐渐趋近于0。

修复方法:
将学习率调整为更合理的数值:

self.eta = 0.001

如果还是不稳定,可以尝试更小的值(比如0.0001)。

4. 训练时未打乱数据顺序

你的训练循环没有在每个epoch前打乱数据,模型会记住样本的固定顺序,导致训练不稳定——在小数据集上这个问题会格外明显。

修复方法:
在每个epoch开始前,对训练数据的索引进行洗牌,再按洗牌后的索引取batch:

def train(self, x, y, loss_graph_file):
    session = self.session
    num_samples = y.shape[0]
    loss_vect = []
    for epoch in range(self.epochs):
        avg_loss = 0
        # 洗牌样本索引
        indices = np.random.permutation(num_samples)
        num_batches = (num_samples + self.batch_size - 1) // self.batch_size
        for i in range(num_batches):
            # 按洗牌后的索引取batch
            batch_indices = indices[i*self.batch_size : min((i+1)*self.batch_size, num_samples)]
            batch_x, batch_y = get_batch_by_indices(batch_indices, [x, y], dsize=x[2])
            _, loss, w = session.run([self.optimizer, self.loss, self.w], {self.x: batch_x, self.y: batch_y})
            avg_loss += loss/num_batches
        loss_vect.append(avg_loss)
        # 原有的打印、绘图代码不变

对应的get_batch_by_indices函数实现:

def get_batch_by_indices(indices, tensors, dsize):
    xs, ys = tensors
    y_b = ys[indices].reshape(-1, 1)
    inds, vals, _ = xs
    # 筛选属于当前batch的稀疏索引
    mask = np.isin(inds[:,0], indices)
    nInds = inds[mask].copy()
    # 将原样本索引转换为batch内的相对索引
    idx_map = {old_idx: new_idx for new_idx, old_idx in enumerate(indices)}
    nInds[:,0] = [idx_map[idx] for idx in nInds[:,0]]
    nVals = vals[mask]
    nDsize = (len(indices), dsize[1])
    x_b = tf.SparseTensorValue(nInds, nVals, nDsize)
    return (x_b, y_b)

5. 训练时丢弃了部分样本

原来的num_batches = y.shape[0] // self.batch_size会丢弃最后一个不足batch_size的样本,在小数据集上这会导致模型无法学到全部数据。修改为向上取整的计算方式,确保所有样本都被用到:

num_batches = (y.shape[0] + self.batch_size - 1) // self.batch_size

验证AND函数任务

用修改后的代码测试AND函数时,模型应该能学到有效的参数。比如输入为[[0,0],[0,1],[1,0],[1,1]],标签为[0,0,0,1],训练后权重会呈现正值,偏置为负,最终能达到100%的精度。

按照以上步骤修改后,你的模型应该能稳定提升训练精度,在小数据集上达到100%,在大数据集上也能收敛到合理的精度范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:44:30