Python 为什么CNN的损失会在很长一段时间内减少,然后突然增加?

Python 为什么CNN的损失会在很长一段时间内减少,然后突然增加?,python,tensorflow,keras,Python,Tensorflow,Keras,我建立了一个简单的网络来寻找断裂的线,我进行了一次非常奇怪的训练。损失keras.loss.binary_crossentropy在大约1500个时期内一直在稳步下降,然后突然上升并趋于平稳 发生这种情况的原因是什么?优化器,损失函数,网络结构 我检查了权重,没有一个权重具有NaN值。输入数据是250000+32x32个图像,图像上有线条,相同的图像堆栈中,线条从中删除了一些像素,因此它们“断开” 以下是模型创建代码: input_shape = (1, 32, 32) kernel_sha

我建立了一个简单的网络来寻找断裂的线,我进行了一次非常奇怪的训练。损失keras.loss.binary_crossentropy在大约1500个时期内一直在稳步下降,然后突然上升并趋于平稳

发生这种情况的原因是什么?优化器,损失函数,网络结构

我检查了权重,没有一个权重具有NaN值。输入数据是250000+32x32个图像,图像上有线条,相同的图像堆栈中,线条从中删除了一些像素,因此它们“断开”

以下是模型创建代码:

input_shape = (1, 32, 32)
kernel_shape = (16, 16)
keras.backend.set_image_data_format("channels_first")
n_filters = 64
input_layer = engine.Input(input_shape)
active_1 = layers.Activation("relu")(input_layer)
conv_1 = layers.Conv2D(n_filters, kernel_shape)(active_1)
conv_2 = layers.Conv2D(2*n_filters, kernel_shape)(conv_1)
pool_1 = layers.MaxPooling2D()(conv_2)

s = tupleFromShape(pool_1.shape)
p = 1
for d in s:
    p *= d

shaped_1 = layers.Reshape((p,))(pool_1)
dense_1 = layers.Dense(2)(shaped_1)
out = layers.Activation("softmax")(dense_1)
model = engine.Model(input_layer, out)
model.save("broken-lines-start.h5")
以及培训守则:

full = #numpy array (c, slices, 32, 32)
broken = #numpy array(c, slices, 32, 32)
full = full[0]
broken = broken[0]

n = len(full) - 1024
n2 = len(broken) - 1024

random.shuffle(full)
random.shuffle(broken)

optimizer = keras.optimizers.Adam(0.00001)
loss_function = keras.losses.binary_crossentropy
model.compile(
        model, 
        optimizer, 
        loss_function=loss_function)
batch_size = 256
steps = n//batch_size + n2//batch_size
model.fit_generator(generator=getDataGenerator(full[:n], broken[:n2], batch_size),
                steps_per_epoch=steps,
                epochs=4680,
                validation_data=getDataGenerator(full[n:], broken[n2:], batch_size),
                validation_steps=2048//batch_size,
                callbacks=[saves_last_epoch_and_best_epoch]
                    )
model.save("broken-lines-trained.h5")
发电机代码:

def getDataGenerator(solid, broken, batch_size=128):
    zed = [([chunk], [1, 0]) for chunk in solid] + [([chunk], [0, 1]) for chunk in broken]
    random.shuffle(zed)
    xbatch = []
    ybatch = []
    while True:
        for i in range(len(zed)):
            x,y = zed[i]
            xbatch.append(x)
            ybatch.append(y)
            if len(xbatch)==batch_size:
                yield numpy.array(xbatch),numpy.array(ybatch)
                xbatch = []
                ybatch = []
我已经大大改进了这个模型,它还没有表现出这种行为,但我想了解为什么会发生这种情况

后来我尝试过的事情:

将损耗函数更改为logcosh->works

更改adam优化器的epsilon值->仍然会爆炸


将优化器更改为SGD->爆炸速度更快,没有初始下降。

一个可能的问题可能是Adam优化器——众所周知,当您长时间训练它时,它会“爆炸”

让我们看一下Adam的配方(很抱歉,演示很难看,稍后可能会改为美丽的乳胶):


t这是一些需要了解的好信息。除了重新运行模型之外,您知道一种验证这一点的好方法吗?我正在重新运行模型来检查它。在重新运行模型后,除了epsilon值之外,所有东西都保持不变,它仍然会爆炸。到目前为止,改变损失函数已经防止了它爆炸。我不明白这怎么会太广泛。问题非常具体。我对网络进行了很长时间的训练,结果它崩溃了。我不知道这是什么原因。我还包括了所有的细节,以便有人可以根据需要重现问题。出于好奇@matt,你为什么设置
kernel\u shape=(16,16)
?@来自KerasimportMichael也出于好奇,我试图探索内核大小的影响,并了解发生了什么。我切换到一个更小的内核(5,5),结果要好得多。在这种情况下,可能更小的也适用,因为我可以找到3x3区域的虚线。当我在@matt出现这种行为时,我的直觉(可能是100%错误)是因为我设置了一些使网络难以学习的东西(糟糕的超参数或结构)。网络挣扎了一段时间,但它走错方向并爆炸只是时间问题。我想知道您的大内核大小是否会使网络难以学习(大内核中的小信号,信号通过其他层时会变得更小,等等)。再说一次,只是直觉,不是我自己赌的东西。
t <- t + 1
lr_t <- learning_rate * sqrt(1 - beta2^t) / (1 - beta1^t)

m_t <- beta1 * m_{t-1} + (1 - beta1) * g
v_t <- beta2 * v_{t-1} + (1 - beta2) * g * g
variable <- variable - lr_t * m_t / (sqrt(v_t) + epsilon)