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

线性FFNN预测求和任务快速达100%准确率的原因分析

分析FFNN快速达到100%训练准确率的原因及验证方法

一、模型快速收敛的核心原因

  • 任务复杂度极低:两个整数求和是纯线性任务,哪怕是没有隐藏层的单一线性层都能完美拟合。你的模型配备了两层隐藏层,拟合能力远超任务需求,自然能快速收敛。
  • 数据集完全覆盖所有可能样本:np.random.randint(-10,10)生成的是-10到9的整数,所有可能的输入组合仅20×20=400种。2000个训练样本已经重复覆盖所有组合多次,模型很容易直接“记住”所有样本的映射关系,甚至不需要学习通用求和逻辑。
  • 准确率判定条件宽松:你用|预测值-真实值| < 1作为正确标准,而真实标签是整数,只要预测值落在真实值的相邻整数区间内(比如真实值为3,预测2.1或3.9都算对),这种宽松的判定加速了准确率达标。

二、验证模型是否真正学会求和逻辑

要区分模型是“死记硬背”还是“学会规则”,可以做以下测试:

  • 测试非整数输入:比如输入[2.5, 3.7],如果模型预测接近6.2,说明它学到了通用的加法逻辑,而非仅仅记住整数组合。
  • 简化模型对比:去掉隐藏层,只用nn.Linear(2,1)训练,如果依然能达到100%准确率,证明任务本身是线性的,模型确实学到了线性求和关系。
  • 查看输出层参数:如果模型学会求和,输出层的权重应该接近[1, 1],偏置接近0。可以打印net.output.weight和net.output.bias验证。

三、代码中的潜在问题

  • 测试准确率存储错误:原代码中testacc被反复赋值为标量,最终返回的testAcc仅保留最后一轮的测试准确率,应该改为testacc.append(test_acc.item())来记录每一轮结果。
  • 数据类型转换冗余:可以在创建TensorDataset时直接转换为float类型,避免训练循环中重复转换。
  • SGD学习率偏低:任务简单,把学习率从0.001调高到0.01或0.1,能进一步加快收敛速度。

改进后的代码示例

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader,TensorDataset
from sklearn.model_selection import train_test_split
import numpy as np

# 创建数据集
data = []
labels = []
datasetAmount = 2000

for i in range(datasetAmount):
    x = np.random.randint(-10, 10)
    y = np.random.randint(-10,10)
    data.append([x, y])
    labels.append(x + y)

data_np = np.array(data)
labels_np = np.array(labels).reshape(-1,1)

# 划分数据集并直接转换为float类型
train_data, test_data, train_labels, test_labels = train_test_split(data_np, labels_np, train_size=0.9)
train_data = TensorDataset(torch.tensor(train_data).float(), torch.tensor(train_labels).float())
test_data = TensorDataset(torch.tensor(test_data).float(), torch.tensor(test_labels).float())

batchsize = 20
train_loader = DataLoader(train_data, batch_size=batchsize, shuffle=True, drop_last=True)
test_loader = DataLoader(test_data, batch_size=len(test_data))

# 模型定义
def createModel():
    class myModel(nn.Module):
        def __init__(self):
            super().__init__()
            self.input = nn.Linear(2,8)
            self.fc1 = nn.Linear(8,8)
            self.output = nn.Linear(8,1)

        def forward(self,x):
            x = F.relu(self.input(x))
            x = F.relu(self.fc1(x))
            return self.output(x)

    net = myModel()
    lossfun = nn.MSELoss()
    optimizer = torch.optim.SGD(net.parameters(), lr=0.01)  # 调高学习率
    return net, lossfun, optimizer

def trainModel():
    numepochs = 100
    net, lossfun, optimizer = createModel()
    losses = torch.zeros(numepochs)
    trainacc = []
    testacc = []

    for epochi in range(numepochs):
        batchLoss = []
        # 训练循环
        for X, y in train_loader:
            yHat = net(X)
            loss = lossfun(yHat, y)
            batchLoss.append(loss.item())
            
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        
        losses[epochi] = np.mean(batchLoss)
        
        # 计算训练准确率
        with torch.no_grad():
            train_preds = []
            train_targets = []
            for X, y in train_loader:
                train_preds.append(net(X))
                train_targets.append(y)
            train_preds = torch.cat(train_preds)
            train_targets = torch.cat(train_targets)
            train_acc = 100 * torch.mean((torch.abs(train_preds - train_targets) < 1).float())
            trainacc.append(train_acc.item())
        
        # 计算测试准确率(修复为列表存储)
        with torch.no_grad():
            X, y = next(iter(test_loader))
            yHat = net(X)
            test_acc = 100 * torch.mean((torch.abs(yHat - y) < 1).float())
            testacc.append(test_acc.item())
    
    return trainacc, testacc, losses, net

# 训练并验证
trainAcc, testAcc, losses, net = trainModel()

# 验证模型是否学到求和逻辑:打印输出层参数
print("输出层权重:", net.output.weight.detach().numpy())
print("输出层偏置:", net.output.bias.detach().numpy())

# 测试非整数输入
test_input = torch.tensor([[2.5, 3.7], [-5.2, 8.9], [9.9, -9.9]]).float()
with torch.no_grad():
    print("非整数输入预测结果:", net(test_input).detach().numpy())
    print("真实求和结果:", [[6.2], [3.7], [0.0]])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:06:15