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

PyTorch线性神经网络损失与输出恒定问题技术求助

神经网络训练损失与输出恒定问题求助

我正在构建一个用于计算旋转矩阵输入角度的神经网络,采用经典线性网络结构,最终将网络输出传入自定义旋转函数以返回空间点列表。但训练过程中损失值与网络输出始终保持恒定,无法进行有效训练,现寻求技术帮助解决该问题,问题解决后将提取网络所用的旋转角度。

实现代码

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable as V
import torch.optim as opt
import numpy as np
import matplotlib.pyplot as plt


cam_pos = np.array([500, 160, 1140, 1])    # with respect to vehicle coordinates
img_res = (1280, 1080)

aspect_ratio = img_res[0] / img_res[1]

# in px
cx = 636 / aspect_ratio
cy = 548 / aspect_ratio

fx = 241 / aspect_ratio
fy = 238 / aspect_ratio

u = 872 
v = 423
D = 1900  # mm

img_pt = np.array([u, v, 1, 1/D]).T

camera_matrix = np.array([[fx, 0, cx, 0],
                          [0, fy, cy, 0], 
                          [0, 0,  1,  0],
                          [0, 0,  0,  1]])

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.lin1 = nn.Linear(3,10)
        self.lin2 = nn.Linear(10,10)
        self.lin3 = nn.Linear(10,3)
        self.angle_list = []


    def forward(self, x):
        x = F.relu(self.lin1(x))
        x = F.relu(self.lin2(x))
        x = self.lin3(x)
        self.angle_list.append(list(x.detach().numpy()))

        return torch.tensor(self.cam_function(x), requires_grad=True)


    def rot_x(self, alpha): 
        return np.array([  [1,                 0,             0, 0],
                        [0,     np.cos(alpha), -np.sin(alpha), 0],
                        [0,     np.sin(alpha), np.cos(alpha), 0],
                        [0,                  0,            0, 1]
    ])


    def rot_y(self, beta): 
        return np.array([  [np.cos(beta),  0,   np.sin(beta), 0],
                        [0,             1,              0, 0],
                        [-np.sin(beta), 0,   np.cos(beta), 0],
                        [0,             0,              0, 1]
    ])


    def rot_z(self, gamma):
        return np.array([  [np.cos(gamma), -np.sin(gamma),   0, 0],
                            [np.sin(gamma), np.cos(gamma),    0, 0],
                            [0,          0,                   1, 0],
                            [0,          0,                   0, 1]
        ])


    def cam_function(self, net_output):
        net_output = net_output.detach().numpy()
        x = net_output[0]
        y = net_output[1]
        z = net_output[2]
        
        rot_m = np.dot(self.rot_z(z), np.dot(self.rot_y(y), self.rot_x(x)))

        extrinsic_matrix = np.array([  [rot_m[0][0], rot_m[0][1], rot_m[0][2], cam_pos[0]],
                                        [rot_m[1][0], rot_m[1][1], rot_m[1][2], cam_pos[1]],
                                        [rot_m[2][0], rot_m[2][1], rot_m[2][2], cam_pos[2]],
                                        [0,           0,           0,           1         ]])

        cam_output = img_pt * D * np.linalg.inv(camera_matrix) * extrinsic_matrix / 1000
        cam_output = [cam_output[0][0], cam_output[1][1], cam_output[2][2]]

        return cam_output

model = Network()
loss_function = nn.CrossEntropyLoss()
optimizer = opt.SGD(model.parameters(), lr=1e-3)
target = torch.tensor([1.636, 1.405, 0.262]).float()
dummy_data = torch.tensor([0, 0, 0]).float()

losses = []
for epoch in range(5000):
    model.train()
    prediction= model(dummy_data)
    loss = loss_function(prediction, target)
    
    losses.append(loss.item())

    optimizer.zero_grad()
    loss.backward()

    optimizer.step()

训练异常输出

7.3858967314779305
tensor([7.9938, 3.9272, 1.8514], dtype=torch.float64, requires_grad=True)
7.3858967314779305
tensor([7.9938, 3.9272, 1.8514], dtype=torch.float64, requires_grad=True)
7.3858967314779305
tensor([7.9938, 3.9272, 1.8514], dtype=torch.float64, requires_grad=True)

问题分析与解决方案

核心问题原因

  1. 梯度断裂:cam_function中调用net_output.detach().numpy()直接切断了网络输出到后续计算的梯度传播链,导致模型参数无法通过反向传播更新;手动创建返回张量时未关联原计算图,梯度无法传递回网络层。
  2. 损失函数误用:CrossEntropyLoss是分类任务专用损失,当前任务是回归(预测连续空间坐标),应使用MSE或L1损失。
  3. 计算图破坏:使用NumPy数组进行矩阵运算,而非PyTorch张量,既破坏计算图,还可能引发类型不匹配问题。
  4. 矩阵运算错误:使用逐元素乘法*替代矩阵乘法,导致空间坐标计算逻辑错误。

修正后的代码

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as opt
import numpy as np
import matplotlib.pyplot as plt


cam_pos = torch.tensor([500, 160, 1140, 1], dtype=torch.float32)    # with respect to vehicle coordinates
img_res = (1280, 1080)

aspect_ratio = img_res[0] / img_res[1]

# in px
cx = 636 / aspect_ratio
cy = 548 / aspect_ratio

fx = 241 / aspect_ratio
fy = 238 / aspect_ratio

u = 872 
v = 423
D = 1900  # mm

img_pt = torch.tensor([u, v, 1, 1/D], dtype=torch.float32).unsqueeze(1)  # 转为列向量

camera_matrix = torch.tensor([[fx, 0, cx, 0],
                              [0, fy, cy, 0], 
                              [0, 0,  1,  0],
                              [0, 0,  0,  1]], dtype=torch.float32)

class Network(nn.Module):
    def __init__(self):
        super(Network, self).__init__()
        self.lin1 = nn.Linear(3,10)
        self.lin2 = nn.Linear(10,10)
        self.lin3 = nn.Linear(10,3)
        self.angle_list = []


    def forward(self, x):
        x = F.relu(self.lin1(x))
        x = F.relu(self.lin2(x))
        angles = self.lin3(x)
        self.angle_list.append(angles.detach().cpu().numpy().tolist())

        return self.cam_function(angles)


    def rot_x(self, alpha): 
        return torch.tensor([  [1,                 0,             0, 0],
                        [0,     torch.cos(alpha), -torch.sin(alpha), 0],
                        [0,     torch.sin(alpha), torch.cos(alpha), 0],
                        [0,                  0,            0, 1]
    ], dtype=torch.float32)


    def rot_y(self, beta): 
        return torch.tensor([  [torch.cos(beta),  0,   torch.sin(beta), 0],
                        [0,             1,              0, 0],
                        [-torch.sin(beta), 0,   torch.cos(beta), 0],
                        [0,             0,              0, 1]
    ], dtype=torch.float32)


    def rot_z(self, gamma):
        return torch.tensor([  [torch.cos(gamma), -torch.sin(gamma),   0, 0],
                            [torch.sin(gamma), torch.cos(gamma),    0, 0],
                            [0,          0,                   1, 0],
                            [0,          0,                   0, 1]
        ], dtype=torch.float32)


    def cam_function(self, angles):
        alpha, beta, gamma = angles[0], angles[1], angles[2]
        
        rot_m = self.rot_z(gamma) @ self.rot_y(beta) @ self.rot_x(alpha)

        extrinsic_matrix = torch.zeros((4,4), dtype=torch.float32)
        extrinsic_matrix[:3, :3] = rot_m[:3, :3]
        extrinsic_matrix[:3, 3] = cam_pos[:3]
        extrinsic_matrix[3, 3] = 1

        # 修正矩阵运算逻辑
        inv_camera = torch.inverse(camera_matrix)
        cam_output = D * inv_camera @ extrinsic_matrix @ img_pt
        cam_output = cam_output[:3, 0] / 1000  # 转为米单位,取前三个坐标

        return cam_output

model = Network()
loss_function = nn.MSELoss()  # 替换为回归损失
optimizer = opt.SGD(model.parameters(), lr=1e-3)
target = torch.tensor([1.636, 1.405, 0.262], dtype=torch.float32)
dummy_data = torch.tensor([0, 0, 0], dtype=torch.float32)

losses = []
for epoch in range(5000):
    model.train()
    optimizer.zero_grad()
    prediction = model(dummy_data)
    loss = loss_function(prediction, target)
    
    losses.append(loss.item())

    loss.backward()
    optimizer.step()

# 提取最终旋转角度
final_angles = model.angle_list[-1]
print("最终旋转角度:", final_angles)

额外优化建议

  • 调整学习率(如lr=1e-2)或改用Adam优化器,提升收敛速度
  • 对角度输出添加范围约束(如tanh激活函数限制在[-π, π]),避免三角函数计算不稳定
  • 增加训练样本多样性,避免单一样本训练导致的过拟合或收敛困难

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:30:44