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

使用PyTorch实现一元线性回归时出现NaN输出问题

PyTorch一元线性回归训练大数值数据出现NaN的解决方法

当训练数据包含较大整数(比如把训练样本从(20,40)换成(50,100))时,模型训练后预测输出变为NaN,而使用较小数值时预测正常。

实现代码

import torch
from torch.autograd import Variable
import numpy as np

class linearRegression(torch.nn.Module):            
    
    # instantiating Linear Regression class
    def __init__(self):
        super(linearRegression, self).__init__() 
        self.lr_pytorch = torch.nn.Linear(1,1)                 
    def forward(self,input_to_predict):                        
        predictions = self.lr_pytorch(input_to_predict)
        return predictions
            
    def fit(self,inputs,outputs,epochs = 10, learning_rate = 0.01):  
        
        inputs = Variable(torch.from_numpy(np.array(inputs,dtype=np.float32).reshape(-1,1)))        
        labels = Variable(torch.from_numpy(np.array(outputs,dtype=np.float32).reshape(-1,1))) 
        
        stochastic_gradient_descent = torch.optim.SGD(self.lr_pytorch.parameters(),learning_rate)  
        mse_loss_function = torch.nn.MSELoss()                                                     
        
        for epoch in range(epochs):                                                                 
            stochastic_gradient_descent.zero_grad()
            predictions = self.lr_pytorch(inputs)
            
            loss = mse_loss_function(predictions,labels)
            loss.backward()
            stochastic_gradient_descent.step()

测试案例对比

正常工作的训练数据

a = [1,2,3,4,5,6,7,8,9,10,20]
b = [2,4,6,8,10,12,14,16,18,20,40]
c = Variable(torch.from_numpy(np.array([150],dtype=np.float32)))

d = linearRegression()
d.fit(a,b,500)

prediction = d.forward(c) 

print(prediction)

输出:tensor([299.9434], grad_fn=<AddBackward0>)

出现NaN的训练数据

a = [1,2,3,4,5,6,7,8,9,10,50]
b = [2,4,6,8,10,12,14,16,18,20,100]
c = Variable(torch.from_numpy(np.array([150],dtype=np.float32)))

d = linearRegression()
d.fit(a,b,500)

prediction = d.forward(c) 

print(prediction)

输出:tensor([nan], grad_fn=<AddBackward0>)

解决方法

1. 对输入数据做归一化/标准化

大数值输入会导致MSE损失值过大,进而引发梯度爆炸,参数更新后直接变成NaN。将数据缩放到较小范围(比如均值为0、方差为1的标准分布),能从根源上避免梯度异常。

修改fit方法加入归一化逻辑,同时调整forward方法支持反归一化:

class linearRegression(torch.nn.Module):            
    def __init__(self):
        super(linearRegression, self).__init__() 
        self.lr_pytorch = torch.nn.Linear(1,1)                 
        # 初始化归一化参数
        self.input_mean = 0.0
        self.input_std = 1.0
        self.output_mean = 0.0
        self.output_std = 1.0
        
    def forward(self,input_to_predict):                        
        # 对输入做归一化
        input_normalized = (input_to_predict - self.input_mean) / self.input_std
        predictions_normalized = self.lr_pytorch(input_normalized)
        # 反归一化得到真实预测值
        predictions = predictions_normalized * self.output_std + self.output_mean
        return predictions
            
    def fit(self,inputs,outputs,epochs = 10, learning_rate = 0.01):  
        inputs_np = np.array(inputs,dtype=np.float32).reshape(-1,1)
        outputs_np = np.array(outputs,dtype=np.float32).reshape(-1,1)
        
        # 计算归一化参数
        self.input_mean = np.mean(inputs_np)
        self.input_std = np.std(inputs_np)
        self.output_mean = np.mean(outputs_np)
        self.output_std = np.std(outputs_np)
        
        # 归一化处理
        inputs_normalized = (inputs_np - self.input_mean) / self.input_std
        outputs_normalized = (outputs_np - self.output_mean) / self.output_std
        
        inputs = Variable(torch.from_numpy(inputs_normalized))        
        labels = Variable(torch.from_numpy(outputs_normalized)) 
        
        stochastic_gradient_descent = torch.optim.SGD(self.lr_pytorch.parameters(),learning_rate)  
        mse_loss_function = torch.nn.MSELoss()                                                     
        
        for epoch in range(epochs):                                                                 
            stochastic_gradient_descent.zero_grad()
            predictions = self.lr_pytorch(inputs)
            
            loss = mse_loss_function(predictions,labels)
            loss.backward()
            stochastic_gradient_descent.step()

2. 降低学习率

原学习率0.01在大数值场景下可能过高,导致参数更新幅度过大。可以尝试将学习率调低到0.001甚至更小:

d.fit(a,b,500, learning_rate=0.001)

3. 添加梯度裁剪

在反向传播后限制梯度的最大范数,防止梯度爆炸:
修改fit方法中的循环部分:

for epoch in range(epochs):                                                                 
    stochastic_gradient_descent.zero_grad()
    predictions = self.lr_pytorch(inputs)
    
    loss = mse_loss_function(predictions,labels)
    loss.backward()
    # 梯度裁剪,限制最大范数为1.0
    torch.nn.utils.clip_grad_norm_(self.lr_pytorch.parameters(), max_norm=1.0)
    stochastic_gradient_descent.step()

优先推荐数据归一化方案,它不仅解决NaN问题,还能提升模型训练的稳定性和收敛速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:17:54