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

基于PyTorch拟合圆:实现坐标平方和输出的网络拟合困境

问题分析与解决方案

你的网络无法拟合x²+y²的核心原因是线性网络无法表达非线性关系,再加上初始化、训练参数的不合理设置,导致损失居高不下。以下是具体问题和修正方案:

核心问题点

  • 缺少非线性激活函数:当前网络是纯线性结构(两个Linear层串联),只能拟合线性映射,而x²+y²是二次非线性函数,必须引入非线性激活才能让网络学到非线性特征。
  • 偏差初始化错误且未生效:你定义了init_bias函数但从未调用,而且用Xavier初始化偏差是不合理的——偏差通常初始为0或极小常数,Xavier是针对权重的初始化方法。
  • 训练轮数不足:仅10轮训练不足以让网络收敛到合适的参数。
  • 学习率偏低:0.001的学习率对于这个简单任务来说收敛速度太慢。

修正后的代码

import torch 
import torch.nn as nn
from torch.utils.data import TensorDataset, DataLoader

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

# 明确指定数据类型为float32,避免潜在类型问题
features = torch.tensor([
    [8.3572,-11.3008,1],[6.2795,-12.5886,1],[4.0056,-13.4958,1],
    [1.6219,-13.9933,1],[-0.8157,-14.0706,1],[-3.2280,-13.7250,1],
    [-5.5392,-12.9598,1],[-7.6952,-11.8073,1],[-9.6076,-10.3035,1],
    [-11.2532,-8.4668,1],[-12.5568,-6.3425,1],[-13.4558,-4.0691,1],
    [-13.9484,-1.7293,1],[-14.0218,0.7224,1],[-13.6791,3.1211,1],
    [-12.9064,5.4561,1],[-11.7489,7.6081,1],[-10.2251,9.5447,1],
    [5.4804,12.8044,1],[7.6332,11.6543,1],[9.5543,10.1454,1],
    [11.1890,8.3117,1],[12.4705,6.2460,1],[13.3815,3.9556,1],
    [13.8733,1.5884,1],[13.9509,-0.8663,1],[13.6014,-3.2793,1],
    [12.8572,-5.5526,1],[11.7042,-7.7191,1],[10.1761,-9.6745,1],
    [-8.4301,11.1605,1],[-6.3228,12.4433,1],[-4.0701,13.3401,1],
    [-1.6816,13.8352,1],[0.7599,13.9117,1],[3.1672,13.5653,1]
], dtype=torch.float32).to(device)

# 简化标签计算,直接用张量运算
labels = (features[:,0]**2 + features[:,1]**2).to(device)

num_input ,num_hidden,num_output = 3,64,1
net = nn.Sequential(
    nn.Linear(num_input,num_hidden),
    nn.ReLU(),  # 添加非线性激活层,这是关键!
    nn.Linear(num_hidden,num_output)
).to(device)

# 修正初始化:权重用Xavier,偏差初始为0
def init_weights(m):
    if type(m) == nn.Linear:
        nn.init.xavier_normal_(m.weight)
        nn.init.constant_(m.bias, 0.0)  # 偏差初始为0

net.apply(init_weights)

loss = nn.MSELoss()

# 调整训练参数:增加轮数、调大学习率
num_epochs = 500
batch_size = 6
lr=0.005
trainer = torch.optim.RAdam(net.parameters(),lr=lr)

dataset = TensorDataset(features,labels)
data_loader = DataLoader(dataset,batch_size=batch_size,shuffle=True)

# 训练时打印每轮的平均损失,而不是最后一个batch的损失
for epoch in range(num_epochs):
    total_loss = 0.0
    for X,y in data_loader:
        y_hat = net(X)
        l = loss(y_hat,y.reshape(y_hat.shape))
        trainer.zero_grad()
        l.backward()
        trainer.step()
        total_loss += l.item()
    # 每20轮打印一次损失,避免输出过多
    if (epoch+1) % 20 == 0:
        with torch.no_grad():
            print(f"Epoch {epoch+1}, Average Loss: {total_loss/len(data_loader):.4f}")

额外优化建议

  • 输入归一化:可以将x、y除以它们的最大值(比如14),让输入范围落在[-1,1]之间,能进一步加快收敛速度,示例代码:
    features[:,0] /= 14.0
    features[:,1] /= 14.0
    
  • 调整隐藏层大小:这个任务很简单,隐藏层不用64这么大,16或32足够,能减少计算量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:15:59