如何解释带有调试信息的Caffe日志?

在训练过程中遇到困难时(例如nan损失不收敛等),有时通过在'solver.prototxt'文件中设置debug_info: true来查看更详细的训练日志会很有帮助。

训练日志看起来会像这样:

I1109 ...]     [Forward] Layer data, top blob data data: 0.343971    I1109 ...]     [Forward] Layer conv1, top blob conv1 data: 0.0645037I1109 ...]     [Forward] Layer conv1, param blob 0 data: 0.00899114I1109 ...]     [Forward] Layer conv1, param blob 1 data: 0I1109 ...]     [Forward] Layer relu1, top blob conv1 data: 0.0337982I1109 ...]     [Forward] Layer conv2, top blob conv2 data: 0.0249297I1109 ...]     [Forward] Layer conv2, param blob 0 data: 0.00875855I1109 ...]     [Forward] Layer conv2, param blob 1 data: 0I1109 ...]     [Forward] Layer relu2, top blob conv2 data: 0.0128249. ..I1109 ...]     [Forward] Layer fc1, top blob fc1 data: 0.00728743I1109 ...]     [Forward] Layer fc1, param blob 0 data: 0.00876866I1109 ...]     [Forward] Layer fc1, param blob 1 data: 0I1109 ...]     [Forward] Layer loss, top blob loss data: 2031.85I1109 ...]     [Backward] Layer loss, bottom blob fc1 diff: 0.124506I1109 ...]     [Backward] Layer fc1, bottom blob conv6 diff: 0.00107067I1109 ...]     [Backward] Layer fc1, param blob 0 diff: 0.483772I1109 ...]     [Backward] Layer fc1, param blob 1 diff: 4079.72...I1109 ...]     [Backward] Layer conv2, bottom blob conv1 diff: 5.99449e-06I1109 ...]     [Backward] Layer conv2, param blob 0 diff: 0.00661093I1109 ...]     [Backward] Layer conv2, param blob 1 diff: 0.10995I1109 ...]     [Backward] Layer relu1, bottom blob conv1 diff: 2.87345e-06I1109 ...]     [Backward] Layer conv1, param blob 0 diff: 0.0220984I1109 ...]     [Backward] Layer conv1, param blob 1 diff: 0.0429201E1109 ...]     [Backward] All net params (data, diff): L1 norm = (2711.42, 7086.66); L2 norm = (6.11659, 4085.07)

这意味着什么呢?


回答:

乍一看,你可以看到这个日志部分分为两部分:[Forward][Backward]。回顾一下,神经网络的训练是通过前向-后向传播来完成的:
一个训练样本(批次)被输入到网络中,前向传递输出当前的预测。
基于这个预测计算损失。然后计算损失的导数,估算梯度并使用链式法则向后传播。

Caffe Blob数据结构
简单回顾一下。Caffe使用Blob数据结构来存储数据/权重/参数等。对于本讨论,重要的是要注意Blob有两个“部分”:datadiffBlob的值存储在data部分。diff部分用于存储后向传播步骤的逐元素梯度。

前向传递

你会在这个日志部分看到从底到顶的所有层。对于每一层,你会看到:

I1109 ...]     [Forward] Layer conv1, top blob conv1 data: 0.0645037
I1109 ...]     [Forward] Layer conv1, param blob 0 data: 0.00899114I1109 ...]     [Forward] Layer conv1, param blob 1 data: 0

"conv1"是一个卷积层,它有两个参数Blob:滤波器和偏置。因此,日志中有三行。滤波器Blob(param blob 0)的data

 I1109 ...]     [Forward] Layer conv1, param blob 0 data: 0.00899114

即卷积滤波器权重的当前L2范数为0.00899。
当前偏置(param blob 1):

 I1109 ...]     [Forward] Layer conv1, param blob 1 data: 0

意味着当前偏置设置为0。

最后但同样重要的是,"conv1"层有一个输出,命名为"conv1"(多么原始…)。输出的L2范数是

 I1109 ...]     [Forward] Layer conv1, top blob conv1 data: 0.0645037

请注意,[Forward]传递的所有L2值都报告在相关Blob的data部分上。

损失和梯度
[Forward]传递结束时,会出现损失层:

I1109 ...]     [Forward] Layer loss, top blob loss data: 2031.85
I1109 ...]     [Backward] Layer loss, bottom blob fc1 diff: 0.124506

在这个例子中,批次损失为2031.85,相对于fc1的损失梯度被计算并传递到fc1 Blob的diff部分。梯度的L2大小为0.1245。

后向传递
所有其余的层在这个部分按从顶到底的顺序列出。你可以看到现在报告的L2大小是Blob的diff部分(参数和层的输入)。

最后
这次迭代的最后一行日志:

[Backward] All net params (data, diff): L1 norm = (2711.42, 7086.66); L2 norm = (6.11659, 4085.07)

报告了数据和梯度的总L1和L2大小。

我应该注意什么?

  1. 如果你的损失中有nan,看看你的数据或diff在什么时候变成nan:在哪个层?在哪个迭代?

  2. 查看梯度的大小,它们应该在合理范围内。如果你开始看到e+8的值,你的数据/梯度开始变得很大。降低你的学习率!

  3. 查看diff是否为零。零diff意味着没有梯度=没有更新=没有学习。如果你从随机权重开始,考虑生成方差更高的随机权重。

  4. 查找激活值(而不是梯度)变为零的情况。如果你使用的是"ReLU",这意味着你的输入/权重导致你进入ReLU门“未激活”的区域,导致“死亡神经元”。考虑将你的输入标准化为零均值,添加"BatchNorm"层,设置ReLU中的negative_slope

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注