振荡的训练损失曲线代表什么?

人工智能 训练 计算机视觉 深度神经网络 物体识别
2021-11-01 08:49:33

在此处输入图像描述

我试图创建一个简单的模型来接收80×130像素图像。我只有 35 张图片和 10 张测试图片。我为二进制分类任务训练了这个模型。该模型的架构如下所述。

conv2d_1 (Conv2D)            (None, 80, 130, 64)       640       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 78, 128, 64)       36928     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 39, 64, 64)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 39, 64, 64)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 39, 64, 128)       73856     
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 37, 62, 128)       147584    
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 18, 31, 128)       0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 18, 31, 128)       0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 71424)             0         
_________________________________________________________________
dense_1 (Dense)              (None, 512)               36569600  
_________________________________________________________________
dropout_3 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 513     

上面的振荡训练损失曲线代表什么?为什么验证损失是常数?

4个回答

尝试降低学习率。

这样的损失曲线可以指示高学习率。由于学习率高,该算法可以在梯度方向上大步走,并错过局部最小值。然后它将在下一步尝试回到最小值并再次超过它。

您也可以尝试切换到基于动量的 GD 算法。这样的训练损失曲线可以表示像这个例子中的损失轮廓,基于动量的 GD 方法是有帮助的。

我注意到你的训练集非常小。使用更大的训练数据(约 1000 个示例)或使用预训练的 Conv 网络作为起点可能会更好。

概述

正如已经观察到的那样,除了与训练相关的问题(例如固定学习率)之外,您的主要问题是您基本上没有机会学习如此大的模型和如此小的数据集......从头开始

所以专注于真正的问题,这里有一些你可以使用的技术

  • 数据集扩充
  • 迁移学习
    • 来自预训练模型
    • 从自动编码器的编码器阶段(进入更高级主题之前的最后选择)

数据集扩充

向您希望分类器学习不变的数据集添加转换

让我们假设

  • I是输入图像

  • l其相关标签

  • f(I;θ)I是影响外观但不影响语义的参数变换,例如它是θ角度

然后你可以通过生成来扩充你的数据集{Iθ,l}一组变换的(例如旋转的)图像,它们相关联l标签

迁移学习

迁移学习的基本思想是重用经过训练的神经网络来解决一个任务,来解决其他任务,只重训练一个选定的权重子集

这意味着使用预训练的卷积后端,使用 Conv2D 和池化的模型部分,并仅训练带有 dropout 的密集层(但您仍然应该考虑减少那里的维数)

更正式地考虑如下表示您的 CNN 分类器

  • fC(I;θX): 输入图像的卷积处理

    • 它是CNN的一部分,由Conv2DMaxPooling2D层组成
    • θC是卷积可学习权重集
  • b=fC(I;θC): 瓶颈特征表示

    • 这是Flatten层的结果
  • fD(b;θD): 密集处理

    • 它是由Dense层组成的模型的一部分
    • θD是密集的可学习权重集

这个想法是挑选θC从另一个数据集上执行的训练,比你当前的更大,并在你的任务训练时保持它固定这意味着减少要训练的参数的数量,但是要注意密集层占了大部分权重,因为你可以还可以从您的模式摘要中看到,这意味着您还应该专注于减少该数字,例如减少瓶颈特征张量大小

从预训练模型迁移学习

例如,如果您的实际目标是对某种类似 MNIST 的数据执行二进制分类,那么您可以使用来自 CNN 的卷积后端,该后端已经在 MNIST 0..9 分类任务上进行了预训练,或者您可以对其进行训练你自己,但重要的是θC权重将从 MNIST 数据集中学习,该数据集比您的大得多,即使任务(略有)不同。

此外,对于类似 MNIST 的数据,请考虑您是否真的需要全80 x 130分辨率,因此您的输入张量,考虑到我可以从您的模型摘要中推断出它是灰度(无颜色),需要(80,130,1)或者你可以重新调整到28 x 28MNIST 分辨率,这样你就可以使用更小的(28,28,1)张量

我的建议是从像这样的MNIST Keras 模型这样的架构开始

  • 它的瓶颈表示为 64,足以完成您的任务,并且
  • 还建议去除第一层致密层,以显着减少θD可学习参数的数量,因此需要类似的东西
  model = Sequential()
  # add Convolutional layers
  model.add(Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding='same', input_shape=(10, 10, 1)))
  model.add(MaxPooling2D(pool_size=(2,2)))
  model.add(Conv2D(filters=64, kernel_size=(3,3), activation='relu', padding='same'))
  model.add(MaxPooling2D(pool_size=(2,2)))
  model.add(Conv2D(filters=64, kernel_size=(3,3), activation='relu', padding='same'))
  model.add(MaxPooling2D(pool_size=(2,2)))    
  model.add(Flatten())
  # output layer
  model.add(Dense(1, activation='sigmoid'))

然后用损失编译模型,binary_crossentropy也许开始尝试adam优化器

自编码器的迁移学习

如果您的数据非常特殊,您找不到任何足够大且足够相似的数据集来使用此策略,并且您没有提出任何可用于执行数据集扩充的转换,而无需深入研究,您可以尝试玩最后一张卡片:使用自动编码器学习压缩表示,旨在重建原始图像并仅使用编码器执行迁移学习

例如,再次假设与一个(28,28,1)张量,您可以从如下架构开始

def build_ae(input_img): 
  x = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
  # (28,28,16)

  encoded = MaxPooling2D((8, 8), padding='same')(x)
  # (4,4,8)


  x = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
  # (4,4,8)

  x = UpSampling2D((8, 8))(x)
  # (16,16,8)

  x = Conv2D(16, (3, 3), activation='relu')(x)
  # Note: Convolving without padding='same' in order to get w-2 and h-2 dimensioality reduction so that following upsampling can lead to the desired 28x28 spatial resolution 
  # (14,14,8)

  x = UpSampling2D((2, 2))(x)
  # (28,28,8)

  decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)
  autoencoder = Model(input_img, decoded)
  return autoencoder

在这种情况下,完整模型有 2633 个权重,但编码阶段仅由 Conv2D+Relu+MaxPooling 组成,这意味着3x3x1x16卷积步骤的总权重和16relu 的权重总共只有 160 个权重,潜在表示是(4,4,8)张量,这意味着一个 128 维的扁平张量,因此假设像以前一样,使用密集的 sigmoid 层执行二进制分类,这意味着在实际的二进制分类任务中要学习 128+1 个权重

当然,可以在空间域或通道域上寻求更压缩的潜在表示,从而减少扁平化向量维数,最终学习更少的权重

您能否分享有关您的问题以及您的数据集的更多详细信息,我们可以尝试提供更多帮助

Nicola Bernini 的回答相当全面。以下是我的见解。

首先,想想你是否真的需要神经网络来解决你的问题。想想传统的计算机视觉操作(如边缘检测/基于区域的方法)是否可以帮助您解决问题(OpenCV 可以在这里为您提供帮助)。再次考虑您的数据。如果您决定使用神经网络,可以尝试以下方法:-

  1. 您的数据集太小。试着回忆一下我们正在学习逼近函数(通用逼近定理)。更少的数据 + 更多的参数有很高的过拟合几率。使用迁移学习。(尝试调整图像大小并执行随机调整大小的方形裁剪并用作神经网络的输入。这可能会或可能不会起作用,因为我不知道您到底在做什么)。还可以尝试有意义的数据增强(即:交通标志图像的垂直翻转不起作用)

  2. 如果您决定使用迁移学习,请尝试降低学习率/对网络的不同部分使用不同的学习率。

  3. 检查您的训练和测试数据集分布是否相同。即:不要使用 95% 的标签 0 进行训练并使用具有 95% 的标签 1 的集合进行测试。我不知道您的数据集是否高度不平衡,或者您是否正在进行某种异常检测。

  4. 考虑优化器。如果你还没有,试试亚当。

如果您需要更多帮助,请尝试共享数据,我们会尽力帮助您。

根据我的经验,这种振荡来自:

  • 学习率太高:权重变化太快。
  • 层中的神经元太少:不足以适应。
    • 当没有足够的神经元时,网络根本无法学习,振荡是由于无法适应全局最优;在某些情况下是正确的,在其他情况下是错误的