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

为何我的LSTM模型无法判断序列中1的数量奇偶性?

问题分析与修正方案

你的任务是序列奇偶校验(判断序列中1的个数奇偶性),本质是让模型学习累积计数的奇偶特征,当前训练准确率低主要源于网络结构设计、训练参数设置的不合理,具体修正点如下:

1. 错误使用LSTM输出特征

你的任务只需要LSTM最后一个时间步的隐藏状态——因为奇偶性是整个序列的累积结果,最后一个状态已经包含了前面所有元素的信息。但你当前把所有时间步的隐藏状态(形状(1,5,10))展平后输入全连接层,这会引入大量冗余信息,干扰模型学习核心逻辑。

修正方式:

修改forward方法,仅提取最后一个时间步的输出,并对应调整全连接层输入维度:

class LSTMNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.hidden_size = 10
        self.lstm = nn.LSTM(input_size=1, hidden_size=self.hidden_size, num_layers=1, batch_first=True)
        # 去掉Flatten,输入维度改为hidden_size
        self.net = nn.Sequential(
            nn.ReLU(),
            nn.Linear(self.hidden_size, 1),
            nn.Sigmoid()
        )

    def forward(self, x):
        x, _ = self.lstm(x)
        # 取最后一个时间步的hidden state
        x = self.net(x[:, -1, :])
        return x

2. 训练参数设置不合理

  • 学习率与优化器选择:SGD用0.001的学习率对于这个简单任务来说太小,梯度更新极慢。建议换成自适应学习率的Adam优化器,或把SGD学习率调到0.01以上:
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    
  • Batch Size过小:batch_size=1会导致梯度更新极度不稳定,噪声极大,模型难以学到稳定特征。建议把batch size调到32或64:
    training_loader = DataLoader(trainingSet, batch_size=32, shuffle=True)
    validation_loader = DataLoader(testSet, batch_size=32, shuffle=False)
    
  • 训练轮数不足:10轮训练对于LSTM来说太少,至少训练50-100轮,观察准确率收敛趋势。

3. 标签形状的严谨性修正

在LSTMDataset的__getitem__中,label.reshape((1))得到的是(1,)形状的张量,而模型输出是(1,1),虽然BCELoss会自动广播,但统一形状能避免潜在问题:

def __getitem__(self, idx):
    sample, label = self.x[idx], self.y[idx]
    return sample.reshape((-1, 1)), label.reshape((1, 1))

4. 可选:简化网络结构

这个任务非常简单,不需要两层LSTM,单层LSTM(num_layers=1)就足够完成任务,减少模型复杂度反而更容易收敛。

修正后训练核心代码示例
if __name__ == "__main__":
    # 数据生成部分保持不变
    numSamples = 1000
    sampleLength = 5
    samples = np.ndarray( shape=( numSamples, sampleLength ), dtype=np.float32 )
    labels = np.ndarray( shape=( numSamples ), dtype=np.float32 )
    for s in range( numSamples ):
        sample = np.random.choice( [ 0, 1 ], size=sampleLength )
        samples[ s ] = sample
        even = np.count_nonzero( sample == 1 ) % 2 == 0
        labels[ s ] = int( even )
    
    X_train, X_test, y_train, y_test = train_test_split( samples, labels, test_size=0.25, random_state=42 )
    trainingSet = LSTMDataset( X_train, y_train )
    testSet = LSTMDataset( X_test, y_test )

    # 调整batch size
    training_loader = DataLoader(trainingSet, batch_size=32, shuffle=True)
    validation_loader = DataLoader(testSet, batch_size=32, shuffle=False)
    
    model = LSTMNet()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    loss_fn = torch.nn.BCELoss()

    # 增加训练轮数
    for epoch in range(50):
        yPredicted = []
        yTruth = []
        model.train()
        for i, data in enumerate(training_loader):
            inputs, labels = data
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = loss_fn(outputs, labels)
            loss.backward()
            optimizer.step()
            
            # 批量处理标签与预测结果
            yTruth.extend(labels.cpu().numpy().flatten().astype(int))
            yPredicted.extend(torch.round(outputs).cpu().numpy().flatten().astype(int))
        
        accuracy = accuracy_score(yTruth, yPredicted)
        print(f"Epoch {epoch+1}, Accuracy: {accuracy:.2f}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:57:11