模型拟合时令人沮丧的值或平滑结果

数据挖掘 深度学习 回归 音频识别
2022-03-13 12:01:13

我正在训练一个网络来进行到达方向预测,但我遇到的问题是,无论我的网络是什么(ResNet 18 - 101、CRNN、CNN 等),我的结果都倾向于一个小范围如下图所示的值

地面实况和预测的直方图

这显然会导致以下错误:

极差图

我试图“等待”直到我的网络最终学习,但我的验证损失几乎立即分歧。下面可以看到一个例子。

训练和验证损失

奇怪的是,即使我的训练损失也没有达到 0。我认为如果我的网络过度拟合,它只会完美地学习我的数据集,但这不会发生,不管我的模型有多复杂。我唯一能想到的是我的特征表示完全是荒谬的,或者我在训练功能的某个地方有错字,并且正在发生一些奇怪的事情。

我尝试过使用损失函数,在网络末端尝试了不同的激活函数,例如 Tanh、sigmoid、ReLU,但根本没有激活函数。目前我已经尽可能地简化了我的训练数据,并且正在使用一个 8 通道 1s 长的啁啾信号,可以在这里找到(至少是暂时的):https ://file.re/2021/06/20 /啁啾/

如上所述,我尝试了各种尺寸的标准 ResNet,以及各种不同的特征表示,最近的一次是采用所有 8 个通道的复杂 STFT,垂直堆叠幅度并将角度信息添加到 X 轴,如下所示:

样本特征

如果有人有任何想法,我很乐意尝试。目前,我正在使用具有垂直卷积且没有池化操作的 CNN,以尝试保存时间信息。

我的主要训练方法如下:

def train(self):
        steps, losses, metrics = TrainingUtilities.get_training_variables(self.parameters)
        patience_counter = 0
        best_epoch_data = None
        best_epoch_validation_loss = 999
        best_epoch = 0
        exit_training = False
        try:
            for epoch in range(steps, self.epoch_count):
                epoch_metrics = TrainingUtilities.initialize_metrics(self.mode)
                if exit_training:
                    break
                for idx, phase in enumerate(['train', 'val']):
                    if phase == 'train':
                        self.model.train()
                    else:
                        self.model.eval()
                    for _, data in tqdm(enumerate(self.data_loaders[idx])):

                        self.optimizer.zero_grad()
                        inputs, labels = data

                        outputs = self.model(inputs.to(self.device))
                        # labels = azi_class.squeeze_().to(self.device)
                        loss = self.criterion(outputs.squeeze(), labels.to(self.device))

                        epoch_metrics = TrainingUtilities.get_epoch_metrics(
                            outputs, labels, loss, epoch_metrics, phase, self.mode)

                        if phase == 'train':
                            loss.backward()
                            self.optimizer.step()

                    TrainingUtilities.report_metrics(self.writer, epoch_metrics, epoch, phase, self.parameters, self.mode)
                    if phase == "val":
                        TrainingUtilities.step_scheduler(
                            self.scheduler, np.mean(epoch_metrics[0][phase]), self.parameters)
                  
                losses.append(epoch_metrics[0])
                metrics.append(epoch_metrics)
                if epoch % self.epoch_save_count == 0:
                    TrainingUtilities.save_checkpoint(self.model, losses, metrics, self.training_dir, epoch, self.mode, self.model_name, self.size)

                steps += 1

        except (KeyboardInterrupt, RuntimeError) as error:
            print(f"Error: {error}")
            TrainingUtilities.save_checkpoint(self.model, losses, metrics, self.training_dir, steps, self.mode, self.model_name, self.size)

我很可能错过了一些东西,但主要思想是,我认为很简单。由于使用不同的数据集测试了许多不同的模型,并且希望在分类和回归之间轻松切换,我已经抽象了很多东西。

1个回答

我无法访问该文件。如果不能分享,可以分享一个小样本吗?

一些想法:

1-您是否尝试规范化您的数据?一些具有异常值的数据需要进行归一化才能正确训练。

2-训练中也可能存在问题,可能是过度拟合。您是否应用了 dropout 来增加泛化能力。

3- 如果您使用的任何模型都存在相同的错误,则可能是您的学习过程中有问题:可能是您未对预测数据应用的初始数据转换。