首页 文章

使用BatchNorm,CNN训练准确性停滞不前,快速配备

提问于
浏览
4

我有两种类型的灰度图像,比方说汽车和飞机 . 在我的训练集中,我有1000张图像(大约50/50分割) . 在这个训练集中,我的所有飞机示例都在白色背景上,而所有的汽车示例都在黑色背景上(这是有目的的,模型最终学会区分汽车和飞机,而不是他们的背景) .

作为一个简单的证据,模型将很快适应背景,我创建了一个CNN . 但是,我遇到了两个奇怪的场景:

  • 如果我在一个转换层和另一个层之间的任何地方添加BatchNorm,我的训练准确率似乎徘徊在50%左右,无法改善 .

  • 如果我删除BatchNorm,我的训练准确度会迅速上升到98%ish . 尽管我使用我的训练数据集来创建验证数据集(因此,此验证数据集也有黑/白背景问题),但我的验证数据集徘徊在50%左右 . 我希望我的训练数据集过度使用是由黑白背景引起的,我的验证数据集也有,并且能够预测 .

我附上了我的代码 . 我将数据作为1x4096向量,因此我将其重塑为64x64图像 . 当我在下面的代码中取消注释任何BatchNorm步骤时,训练准确性似乎悬停

#Normalize training data
        self.x = self.x.astype('float32')
        self.x /= 255

        numSamples = self.x.shape[0]
        #Reconstruct images
        width = 64
        height = 64
        xInput = self.x.reshape(numSamples,1,height,width)

        y_test = to_categorical(labels, 2)

        #Split data to get validation set
        X_train, X_test, y_train, y_test = train_test_split(xInput, y_test, test_size=0.3, random_state=0)

        #Construct model
        self.model = Sequential()
        self.model.add(Conv2D(64, kernel_size=(3, 3), strides=(1, 1),
                 activation='relu',
                 input_shape=(1,64,64), data_format='channels_first',activity_regularizer=regularizers.l1(0.01)))
        #self.model.add(BatchNormalization())
        self.model.add(MaxPooling2D((2, 2)))
        self.model.add(Dropout(0.5, noise_shape=None)) 
        self.model.add(Conv2D(128, kernel_size=(3, 3), strides=(1, 1), activation='relu'))
        #self.model.add(BatchNormalization())
        self.model.add(MaxPooling2D((2, 2)))
        self.model.add(Dropout(0.5, noise_shape=None)) 
        self.model.add(Conv2D(256, kernel_size=(3, 3), strides=(1, 1), activation='relu'))
        #self.model.add(BatchNormalization())
        self.model.add(MaxPooling2D((2, 2)))
        self.model.add(Dropout(0.5, noise_shape=None)) 
        self.model.add(Flatten())
        self.model.add(Dense(1000, activation='relu', activity_regularizer=regularizers.l2(0.01)))
        self.model.add(BatchNormalization())
        self.model.add(Dropout(0.5, noise_shape=None)) 
        self.model.add(Dense(units = 2, activation = 'softmax', kernel_initializer='lecun_normal'))

        self.model.compile(loss='categorical_crossentropy',
             optimizer='adam',
             metrics=['accuracy'])

        self.model.fit(X_train, y_train,
            batch_size=32,
            epochs=25,
            verbose=2,
            validation_data = (X_test,y_test),
            callbacks = [EarlyStopping(monitor = 'val_acc', patience =5)])

1 回答

  • 0

    我认为人工神经网络的架构和一些基本问题有很多潜在的改进 .

    Fundamental challenge 与您的训练集的构建方式有关:黑白背景 . 如果意图是背景不应该发挥作用,为什么不将它们全部变成白色或黑色?请注意,ANN与任何机器学习算法一样,都会尝试找出与您的类有什么区别 . 在这种情况下,它将只是背景 . 当背景提供如此清晰和有益的差异化时,为什么要看一下汽车与飞机的微小细节?

    Solution :为两个集合制作背景均匀 . 然后你的人工神经网络将会忘记它 .

    Why Batch Norm was messing up training accuracy? 正如您自己所说,测试准确性仍然很差 . Batch Norm正在解决协方差转移问题 . 后来在看似很好的训练准确性 - 以及糟糕的测试中表现出来了"problem" . 关于批量标准化的精彩视频,有关于covaraince的转变,来自Andrew Ng here .

    修复培训应解决问题 . 其他一些事情:

    • 最后你给出2个密集单位,但你的分类是二进制的 . 使其成为Sigmoid激活的单个单元 .

    • 正如@Upasana Mittal指出的那样,将 categorical_crossentropy 替换为 binary_crossentropy .

    • 考虑使用较小的辍学率 . 请注意,您没有那么多数据总是丢弃一半 . 只有在您有过度拟合的证据后才会增加辍学率 .

    • 使用带有步幅的Conv2D可能比简单的最大池更好 .

    • 你有很多过滤器,似乎不是那么复杂 . 考虑过滤器数量的严重减少,并且只有当您发现ANN没有足够的学习能力时才会增加数量 . 这里只有2个 class ,汽车与喷气机的区别并不那么微妙 .

    • 考虑使用较少数量的图层 . 同样的论点 .

    • 使用至少2个堆叠的3x3 Conv2D层可以产生更好的结果 .

相关问题