我建立了一个简单的网络来查找虚线,并且进行了非常奇怪的训练。损失keras.losses.binary_crossentropy在大约1500个时期稳定下降,然后突然上升并达到平稳状态。
发生这种情况有哪些原因?优化器,损失函数,网络结构?
我检查了砝码,所有砝码都没有NaN值。输入数据是250,000+张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->有效
更改adam优化器的epsilon值->仍然爆炸。
将优化程序更改为SGD->爆炸速度更快,没有初始下降。
答案 0 :(得分:2)
亚当优化器可能是一个问题-长时间训练它会“爆炸”。
让我们看看 Adam 的公式(很抱歉,我们的演示很丑,以后可能会更改为漂亮的LaTeX):
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)
其中m
和v
分别是梯度的第一矩(均值)和第二矩(无中心方差)的估计。长时间训练模型后,v
可能会变得很小。
默认情况下,根据tensorflow docs,beta1=0.9
和beta2=0.999
。因此m
比v
的更改速度更快。因此,m
可以再次变大,而v
不能追赶。这将导致大量数字除以非常小的值并爆炸。
尝试增加epsilon
参数,默认情况下为1e-08
。根据模型,尝试使用0.01
或0.001
之类的值。