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

EEG扫描检测CNN精度提升过慢,请求问题排查与优化建议

EEG检测CNN模型精度提升缓慢问题排查

我用下述CNN模型进行EEG扫描信息检测,但模型精度提升极为缓慢,怀疑模型层设计或训练流程存在疏漏。已尝试为各层添加BatchNorm1d与Dropout层,当前每次训练采用20000份扫描数据(可扩展至51000份),训练100轮后精度仅达13%。相关模型与训练代码如下:

class Net(Module):
    def __init__(self):
        super(Net, self).__init__()
        self.cnn_layers = Sequential(
            Conv1d(1,14, kernel_size=5, padding=1),
            BatchNorm1d(14),
            LeakyReLU(0.1),
            MaxPool1d(kernel_size=5, stride=1),

        )
        self.cnn_layer2 = Sequential(
            Conv1d(14, 10,kernel_size=5, padding=1),
            BatchNorm1d(10),
            LeakyReLU(0.1),
            MaxPool1d(kernel_size=5, stride=1),
            Dropout(0.2),
        )
        self.cnn_layer3 = Sequential(
            Conv1d(10, 10, kernel_size=5, padding=1),
            BatchNorm1d(10),
            LeakyReLU(0.1),
            MaxPool1d(kernel_size=5, stride=1),
            Dropout(0.2),
        )
        self.linear_layer1 = Sequential(
            Linear(in_features=35660,out_features=3500),
            BatchNorm1d(3500),
            LeakyReLU(0.1),
            Dropout(0.2)

        )
        self.linear_layer2 = Sequential(
            Linear(in_features=3500,out_features=2500),
            BatchNorm1d(2500),
            LeakyReLU(0.1),
            Dropout(0.2)
        )
        self.linear_layer3 = Sequential(
            Linear(in_features=2500, out_features=250),
            BatchNorm1d(250),
            LeakyReLU(0.1),
            Dropout(0.2)
        )
        self.linear_layer4 = Sequential(
            Linear(in_features=250, out_features=10)
        )
        self.logsoft = Sequential(
            LogSoftmax(dim=1)
        )
        self.flatten = Sequential(
            Flatten() # probably has to be changed
        )

    def forward(self, x):
        x = self.cnn_layers(x)

        x = self.cnn_layer2(x)

        x = self.cnn_layer3(x)

        x = self.flatten(x)
        x = self.linear_layer1(x)
        x = self.linear_layer2(x)
        x = self.linear_layer3(x)
        x = self.linear_layer4(x)
        x = self.logsoft(x)
        return x



model = Net()

#Build a dataset by taking 255 columns and grouping them into 14 * 255 channels
class CustomDataSet():
    def __init__(self, csv_file, label,  transform=None):
        self.df = csv_file
        self.transform = transform
        self.label = label

    def __len__(self):
        return self.df.shape[0]

    def __getitem__(self, index):
        scan = (self.df[index])
        label = self.label[index]
        if self.transform:
            scan = self.transform(scan)

        return scan, label

train_dataset = rows
print(train_dataset.shape)

train_dataset = CustomDataSet(csv_file=rows, label=(labels))

optimizer = SGD(model.parameters(), lr=0.001, weight_decay=5.0e-5)
criterion = CrossEntropyLoss()
num_epochs = 500
train_loss_list = []
batch_size = 500
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
for epoch in range(num_epochs):
    print(f'Epoch {epoch + 1}/{num_epochs}:', end=' ')
    train_loss = 0

    # Iterating over the training dataset in batches
    total_correct = 0
    total_samples = 0
    model.train()
    for i, (scan, labels) in enumerate(train_loader):
        # Extracting images and target labels for the batch being iterated



        # Calculating the model output and the cross entropy loss

        outputs = model(scan)
        print(outputs.shape)

        loss = criterion(outputs, labels)

        # Updating weights according to calculated loss
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        train_loss += loss.item()
        _, predicted = torch.max(outputs, 1)

        total_correct += (predicted == labels).sum().item()
        total_samples += labels.size(0)
        # Printing loss for each epoch
    accuracy = 100 * total_correct / total_samples
    print("Accuracy: ", accuracy)
    train_loss_list.append(train_loss / len(train_loader))
    print(f"Training loss = {train_loss_list[-1]}")

核心问题排查与修复方案

1. 输入数据维度不匹配(最关键)

  • Conv1d要求输入格式为(batch_size, in_channels, sequence_length),但你的CustomDataSet返回的scan是原始一维数据,没有调整为符合要求的通道维度。
  • 修复:在__getitem__里给scan增加通道维度,比如scan = scan.unsqueeze(0)(如果是tensor类型),确保输入形状为(1, 255),匹配Conv1d的输入要求。

2. 卷积池化层设计无效

  • 你用的MaxPool1d(kernel_size=5, stride=1)几乎没有压缩序列长度,经过3层卷积后特征序列依然很长,导致全连接层输入维度35660过大,梯度容易消失,还会引发过拟合。
  • 修复:把池化的stride改成和kernel_size一致,比如MaxPool1d(kernel_size=5, stride=5),有效压缩特征长度;或者改用AdaptiveAvgPool1d(64)这类自适应池化,固定输出维度,不用手动计算。

3. 全连接层过于臃肿

  • 从35660直接降到3500,参数量巨大,训练效率低且极易过拟合。而且这个输入维度是基于错误的序列长度计算的,调整卷积池化后必须重新计算。
  • 修复:先通过卷积池化把特征维度压缩到合理范围(比如几百),再设计全连接层;可以减少全连接层数到1-2层,降低神经元数量,比如从压缩后的特征直接映射到10个分类输出。

4. 优化器与学习率不合理

  • SGD优化器本身收敛慢,搭配0.001的低学习率,模型权重更新幅度极小,很难有效学习。
  • 修复:换成Adam优化器,初始学习率设为1e-4,搭配weight_decay=1e-5;或者把SGD的学习率提到0.01,同时加入学习率调度器(比如torch.optim.lr_scheduler.ReduceLROnPlateau),根据训练损失动态调整学习率。

5. 损失函数与输出层冲突

  • CrossEntropyLoss内部已经包含了LogSoftmax和NLLLoss的计算逻辑,你额外加了LogSoftmax层,相当于重复计算,会导致损失值异常,影响模型训练。
  • 修复:要么删除logsoft层,直接用全连接层输出;要么把损失函数换成NLLLoss。

6. 缺失EEG数据预处理

  • EEG数据幅值差异大,不做标准化会干扰模型学习。
  • 修复:在CustomDataSet的transform里添加标准化操作,比如计算训练集的均值和标准差,对每个样本做Z-score标准化(scan = (scan - mean) / std)。

7. 训练策略调整

  • 当前20000份数据训练500轮容易过早过拟合,优先扩展数据到51000份;同时加入早停机制,当验证集精度连续多轮不提升就停止训练,避免过拟合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 10:04:52