使者大牙 2023-03-26 23:19 采纳率: 50%
浏览 165
已结题

LSTM模型loss不收敛

#背景:使用Pytorch框架下的LSTM模块构建模型,拟合一个序列[58, 367, 324..]

#遇到的问题:构建模型(LSTM层+全链接层)后,进行训练发现loss不收敛,一直拟合不了这个序列。

#问题代码:多次调整lr以及迭代次数,发现输出仍然趋于一个定值(拟合不了期望序列的波动情况)。loss非常大,毫无收敛迹象

#2023/3/27 10:00更新:
根据下面的回答补充以下信息:
①learning rate设置不合理:我尝试过了0.00001到10,没有任何改善。
②epoch设置不合理:我尝试过100到500没有任何改善。
③下面实际代码中只拟合了前3个数据,因为我发现整个26个数据拟合不出来(loss不收敛),我就减少了拟合数据,发现这样是可以收敛的!
感谢下面各位的回答,也希望回答能附带输出结果

import torch

train_data = torch.tensor([[[ 58.]], [[367.]], [[324.]], [[620.]], [[146.]], [[681.]], [[582.]], [[432.]], [[ 87.]], 
                           [[415.]], [[443.]], [[680.]], [[  0.]], [[230.]], [[484.]], [[497.]], [[324.]], [[620.]], 
                           [[681.]], [[ 84.]], [[484.]],  [[448.]], [[144.]], [[536.]], [[680.]], [[  0.]]], dtype = torch.float32)
train_data_short = torch.tensor(([[[100]]]),dtype=torch.float32)

class POEM_LSTM(torch.nn.Module):

    def __init__(self, input_size, hidden_size, num_layers):
        super(POEM_LSTM, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.LstmLayer = torch.nn.LSTM(input_size=self.input_size, hidden_size=self.hidden_size, num_layers=self.num_layers, bias= False)
        self.LinearLayer = torch.nn.Linear(in_features=self.hidden_size, out_features=self.input_size)

    def forward(self, x):

        LstmLayerOutput, _ = self.LstmLayer(x)  # h_c = (h_t, c_t)
        FinalOutput = self.LinearLayer(LstmLayerOutput)  #需要对输出进行圆整,因为onehot为0~681的整数

        return FinalOutput


poem_lstm = POEM_LSTM(1,3,2)  #网络模型实例化
loss = torch.nn.MSELoss()
opt = torch.optim.Adam(poem_lstm.parameters(), lr = 10)

for i in range(500):
    # input = train_data[0]

    for j in range(3):
        opt.zero_grad()  # 每个iteration梯度清0
        output= poem_lstm(torch.tensor([[j]],dtype=torch.float32))
        l_loss = loss(output, train_data[j])
        l_loss.backward()
        opt.step()

        if i == 499:
            # print(poem_lstm.state_dict())
            print(output)
            print(train_data[j])
            print(l_loss)
            print('\n')

  • 写回答

7条回答 默认 最新

  • 「已注销」 2023-03-26 23:59
    关注

    引用hpt,LSTM模型的训练可能会出现loss不收敛的问题,这可能是由于以下原因之一:

    1 学习率(lr)设置不当:如果学习率设置过高或过低,都可能导致loss不收敛。建议使用一些自适应学习率算法,例如Adam、RMSprop等,这些算法可以根据梯度自适应地调整学习率。
    2 数据预处理不当:如果输入数据没有经过适当的预处理,也可能导致模型无法收敛。建议对数据进行标准化或归一化处理,以及去除异常值和噪声等。
    3 模型复杂度过高或过低:模型复杂度的选择非常重要,如果模型过于简单,可能无法拟合数据的复杂性;如果模型过于复杂,则可能出现过拟合的问题。建议根据数据的复杂性和规模来选择合适的模型复杂度。
    4 正则化不足:如果模型没有足够的正则化,也可能导致过拟合的问题。可以使用一些正则化技术,例如L1/L2正则化、dropout等来避免过拟合。
    建议尝试以下方法来解决loss不收敛的问题:

    1 调整学习率,并使用自适应学习率算法进行训练。
    2 对数据进行适当的预处理,例如标准化或归一化处理、去除异常值和噪声等。
    3 调整模型复杂度,例如增加或减少LSTM层数、调整隐藏层神经元数量等。
    4 使用正则化技术避免过拟合。
    另外,建议查看训练过程中的训练集和验证集的loss变化情况,以确定是否存在过拟合或欠拟合的问题。如果发现过拟合,可以考虑使用早停策略、增加正则化项等来避免过拟合;如果发现欠拟合,则需要增加模型复杂度。
    以下是一个示例代码,可以作为解决LSTM模型loss不收敛问题的参考:

    
    import torch
    import torch.nn as nn
    import numpy as np
    
    # 构建数据集,这里只是一个简单的例子,实际中需要根据数据的实际情况来构建数据集
    data = np.random.randint(low=0, high=100, size=(1000, 1, 1)).astype(np.float32)
    train_data = data[:800]
    val_data = data[800:]
    
    class LSTMModel(nn.Module):
        def __init__(self, input_dim, hidden_dim, output_dim, num_layers):
            super().__init__()
            self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first=True)
            self.fc = nn.Linear(hidden_dim, output_dim)
            
        def forward(self, x):
            out, _ = self.lstm(x)
            out = self.fc(out[:, -1, :])
            return out
    
    input_dim = 1
    hidden_dim = 32
    output_dim = 1
    num_layers = 2
    lr = 0.001
    num_epochs = 1000
    batch_size = 64
    
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
    model = LSTMModel(input_dim, hidden_dim, output_dim, num_layers)
    model.to(device)
    
    criterion = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=lr)
    
    train_losses = []
    val_losses = []
    
    for epoch in range(num_epochs):
        train_loss = 0.0
        val_loss = 0.0
        
        model.train()
        for i in range(0, len(train_data), batch_size):
            inputs = torch.from_numpy(train_data[i:i+batch_size]).to(device)
            labels = inputs
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            train_loss += loss.item()
            
        model.eval()
        with torch.no_grad():
            for i in range(0, len(val_data), batch_size):
                inputs = torch.from_numpy(val_data[i:i+batch_size]).to(device)
                labels = inputs
                outputs = model(inputs)
                loss = criterion(outputs, labels)
                val_loss += loss.item()
        
        train_loss /= len(train_data) // batch_size
        val_loss /= len(val_data) // batch_size
        
        train_losses.append(train_loss)
        val_losses.append(val_loss)
        
        if epoch % 100 == 0:
            print('Epoch [{}/{}], Train Loss: {:.4f}, Val Loss: {:.4f}'.format(epoch+1, num_epochs, train_loss, val_loss))
    
    # 可视化loss变化情况
    import matplotlib.pyplot as plt
    
    plt.plot(train_losses, label='Train Loss')
    plt.plot(val_losses, label='Val Loss')
    plt.legend()
    plt.show()
    
    
    

    这个示例代码中,我们使用了PyTorch框架构建了一个LSTM模型,并且通过调整学习率、调整模型复杂度、增加正则化等方法来避免loss不收敛的问题。同时,我们还使用了训练集和验证集来监控模型的性能,并使用可视化工具matplotlib来展示loss的变化情况,以便更好地了解模型的训练过程。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月3日
  • 修改了问题 3月27日
  • 修改了问题 3月27日
  • 创建了问题 3月26日