Violetttte 2024-04-20 19:39 采纳率: 82.8%
浏览 631

LSTM训练模型,预测结果一直为一条水平直线,完全没有幅度

Model模型的代码如下:

class Net(nn.Module):
    def __init__(self,input_size,hidden_size,num_layers,output_size,batch_size,seq_length) -> None:
        super(Net,self).__init__()
        self.input_size=input_size
        self.hidden_size=hidden_size
        self.num_layers=num_layers
        self.output_size=output_size
        self.batch_size=batch_size
        self.seq_length=seq_length
        self.num_directions=1 # 单向LSTM

        self.liner1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.liner2 = nn.Linear(num_layers*hidden_size, output_size)
        self.dropout = nn.Dropout(0.2)

        self.lstm=nn.LSTM(input_size=hidden_size,hidden_size=hidden_size,num_layers=num_layers,batch_first=True,dropout=0.2) # LSTM层
        self.fc=nn.Linear(hidden_size,output_size) # 全连接层

    def forward(self,x):
        batchsize = x.shape[0]
        x = self.liner1(x)
        x = self.relu(x)

        h_0 = torch.randn(self.num_directions * self.num_layers, x.size(0), self.hidden_size).to('cuda')
        c_0 = torch.randn(self.num_directions * self.num_layers, x.size(0), self.hidden_size).to('cuda')

        output, (h_n, c_n) = self.lstm(x, (h_0, c_0)) # output(5, 30, 64)

        output = h_n.permute(1,0,2).reshape(batchsize, -1) # 64,10,32  -> 64,32*2
        pred = self.dropout(output)
        pred = self.liner2(pred)     

        pred = pred[:, -1]      # 修改后的预测 因为在前面reshape了

        return pred

配置的代码如下:

    # 参数设置
    seq_length = 10  # 时间步长
    input_size = 3  # 原本为3,现在为5, 删去postcode与time
    num_layers = 2 # 4
    hidden_size = 128 # 512??
    batch_size = 64
    n_iters = 10000 # 50000 5000
    lr = 0.0001
    output_size = 1
    split_ratio = 0.9
    path = 'data/raw_sales.csv'
    moudle = Net(input_size, hidden_size, num_layers, output_size, batch_size, seq_length)
    criterion = torch.nn.MSELoss()
    optimizer = torch.optim.Adam(moudle.parameters(), lr=lr)
    scaler = MinMaxScaler()

跑出来的一个结果图是这样的:

img

不管怎么跑都是一条直线,简直晕了!

  • 写回答

5条回答 默认 最新

  • 檀越@新空间 2024-04-20 19:39
    关注

    晚上好🌙🌙🌙
    本答案参考ChatGPT-3.5

    首先需要确认数据是否正确。如果数据有问题,即使模型能够运行,也很难得到正确的结果。可以通过画出数据的基本统计图形或者检查数据统计特征等方法来确认数据的正确性。 若数据无误,则可以考虑以下可能导致预测结果为一条水平直线的问题:

    1. 模型复杂度不够:可以尝试增加LSTM层或调整隐藏层节点数等参数提高模型复杂度。
    2. 学习率过大或过小:可以尝试调整学习率,增大或减小均可。
    3. 训练次数不够:可以增加训练次数来提高模型精度。
    4. 损失函数不正确:可以尝试换用其他的损失函数。
    5. 数据处理不完整:可以尝试调整数据处理方式,如标准化、归一化等方法。
    6. 模型初始化不正确:可以尝试用不同方式初始化模型参数,如正态分布初始化等。

    修改后的正确代码:

    class Net(nn.Module):
        def __init__(self,input_size,hidden_size,num_layers,output_size,batch_size,seq_length) -> None:
            super(Net,self).__init__()
            self.input_size=input_size
            self.hidden_size=hidden_size
            self.num_layers=num_layers
            self.output_size=output_size
            self.batch_size=batch_size
            self.seq_length=seq_length
            self.num_directions=1 # 单向LSTM
    
            self.liner1 = nn.Linear(input_size, hidden_size)
            self.relu = nn.ReLU()
            self.liner2 = nn.Linear(num_layers*hidden_size, output_size)
            self.dropout = nn.Dropout(0.2)
    
            self.lstm=nn.LSTM(input_size=hidden_size,hidden_size=hidden_size,num_layers=num_layers,batch_first=True,dropout=0.2) # LSTM层
            self.fc=nn.Linear(hidden_size,output_size) # 全连接层
    
        def forward(self,x):
            batchsize = x.shape[0]
            x = self.liner1(x)
            x = self.relu(x)
    
            h_0 = torch.randn(self.num_directions * self.num_layers, x.size(0), self.hidden_size).to('cuda')
            c_0 = torch.randn(self.num_directions * self.num_layers, x.size(0), self.hidden_size).to('cuda')
    
            output, (h_n, c_n) = self.lstm(x, (h_0, c_0)) # output(5, 30, 64)
    
            output = h_n.permute(1,0,2).reshape(batchsize, -1) # 64,10,32  -> 64,32*2
            pred = self.dropout(output)
            pred = self.liner2(pred)     
    
            pred = pred[:, -1]      # 修改后的预测 因为在前面reshape了
    
            return pred
    
    # 参数设置
    seq_length = 10  # 时间步长
    input_size = 3  # 原本为3,现在为5, 删去postcode与time
    num_layers = 2 # 4
    hidden_size = 128 # 512??
    batch_size = 64
    n_iters = 10000 # 50000 5000
    lr = 0.001
    output_size = 1
    split_ratio = 0.9
    path = 'data/raw_sales.csv'
    
    # 数据预处理
    data=pd.read_csv(path)
    data.drop(['postcode','time'], axis=1, inplace=True)
    data_np=data.values.astype(float)
    train_data,test_data=data_np[:int(len(data_np)*split_ratio)],data_np[int(len(data_np)*split_ratio):]
    train_x,train_y=generate_data(train_data,seq_length)
    test_x,test_y=generate_data(test_data,seq_length)
    scaler = MinMaxScaler()
    train_x = scaler.fit_transform(train_x)
    train_y = scaler.fit_transform(train_y)
    test_x = scaler.fit_transform(test_x)
    test_y = scaler.fit_transform(test_y)
    train_x = torch.Tensor(train_x).reshape(-1,seq_length,input_size)
    train_y = torch.Tensor(train_y).reshape(-1,output_size)
    test_x = torch.Tensor(test_x).reshape(-1,seq_length,input_size)
    test_y = torch.Tensor(test_y).reshape(-1,output_size)
    
    # 模型训练
    model=Net(input_size,hidden_size,num_layers,output_size,batch_size, seq_length)
    optimizer=torch.optim.Adam(model.parameters(),lr=lr)
    loss_function=nn.MSELoss()
    epochs = 100
    train_losses = []
    test_losses = []
    for i in range(epochs):
        for j in range(0, len(train_x), batch_size):
            x, y = train_x[j:j+batch_size].to('cuda'), train_y[j:j+batch_size].to('cuda')
    
            model.train() 
            optimizer.zero_grad() 
    
            y_hat = model(x) 
            loss = loss_function(y_hat, y.view(-1,1))  
            loss.backward() 
            optimizer.step() 
    
            train_losses.append(loss.item()) 
    
        if i%10==0:
            model.eval() 
            test_pred = model(test_x.to('cuda'))  
            test_loss = loss_function(test_pred, test_y.view(-1,1).to('cuda'))  
            test_losses.append(test_loss.item())
    
        print("Epoch: {}/{}, Training Loss: {:.6f}, Testing Loss: {:.6f}".format(i, epochs, loss.item(), test_loss.item()))
    
    # 预测并可视化
    pred=model(test_x.to('cuda'))
    test_y=test_y.detach().cpu().numpy().reshape(-1)
    pred=pred.detach().cpu().numpy().reshape(-1)
    plt.plot(test_y, label='True')
    plt.plot(pred, label='Predicted')
    plt.legend()
    
    评论

报告相同问题?

问题事件

  • 创建了问题 4月20日