你用什么方法调试深度神经网络?这里有四种简单的方式哦

本文作者总结了四种调试深度神经网络的方法,分别是预测合成输出、可视化激活值、梯度分析和分析模型预测。希望这些技巧可以帮助你调试模型哦!

当你花了几个星期构建一个数据集、编码一个神经网络并训练好了模型,然后发现结果并不理想,接下来你会怎么做?

深度学习通常被视为一个黑盒子,我并不反对这种观点——但是你能讲清楚学到的上万参数的意义吗?

但是黑盒子的观点为机器学习从业者指出了一个明显的问题:你如何调试模型?

在这篇文章中,我将会介绍一些我们在 Cardiogram 中调试 DeepHeart 时用到的技术,DeepHeart 是使用来自 Apple Watch、 Garmin、和 WearOS 的数据预测疾病的深度神经网络

在 Cardiogram 中,我们认为构建 DNN 并不是炼金术,而是工程学。

你的心脏暴露了很多你的信息。DeepHeart 使用来自 Apple Watch、 Garmin、和 WearOS 的心率数据来预测你患糖尿病、高血压以及睡眠窒息症(sleep apnea)的风险。

一、预测合成输出

通过预测根据输入数据构建的合成输出任务来测试模型能力。

我们在构建检测睡眠窒息症的模型时使用了这个技术。现有关于睡眠窒息症筛查的文献使用日间和夜间心率标准差的差异作为筛查机制。因此我们为每周的输入数据创建了合成输出任务:

标准差 (日间心率)—标准差 (夜间心率)

为了学习这个函数,模型要能够:

1. 区分白天和黑夜

2. 记住过去几天的数据

这两个都是预测睡眠窒息症的先决条件,所以我们使用新架构进行实验的第一步就是检查它是否能学习这个合成任务。

你也可以通过在合成任务上预训练网络,以半监督的形式来使用类似这样的合成任务。当标记数据很稀缺,而你手头有大量未标记数据时,这种方法很有用。

二、可视化激活值

理解一个训练好的模型的内部机制是很难的。你如何理解成千上万的矩阵乘法呢?

在这篇优秀的 Distill 文章《Four Experiments in Handwriting with a Neural Network》中,作者通过在热图中绘制单元激活值,分析了手写模型。我们发现这是一个「打开 DNN 引擎盖」的好方法。

我们检查了网络中几个层的激活值,希望能够发现一些语义属性,例如,当用户在睡觉、工作或者焦虑时,激活的单元是怎样的?

用 Keras 写的从模型中提取激活值的代码很简单。下面的代码片段创建了一个 Keras 函数 last_output_fn,该函数在给定一些输入数据的情况下,能够获得一层的输出(即它的激活值)。

from keras import backend as K

def extract_layer_output(model, layer_name, input_data):
  layer_output_fn = K.function([model.layers[0].input],
                               [model.get_layer(layer_name).output])

  layer_output = layer_output_fn([input_data])

  # layer_output.shape is (num_units, num_timesteps)
  return layer_output[0]

我们可视化了网络好几层的激活值。在检查第二个卷积层(一个宽为 128 的时间卷积层)的激活值时,我们注意到了一些奇怪的事:

卷积层的每个单元在每个时间步长上的激活值。蓝色的阴影代表的是激活值。

激活值竟然不是随着时间变化的!它们不受输入值影响,被称为「死神经元」。

ReLU 激活函数,f(x) = max(0, x)

这个架构使用了 ReLU 激活函数,当输入是负数的时候它输出的是 0。尽管它是这个神经网络中比较浅的层,但是这确实是实际发生的事情。

在训练的某些时候,较大的梯度会把某一层的所有偏置项都变成负数,使得 ReLU 函数的输入是很小的负数。因此这层的输出就会全部为 0,因为对小于 0 的输入来说,ReLU 的梯度为零,这个问题无法通过梯度下降来解决。

当一个卷积层的输出全部为零时,后续层的单元就会输出其偏置项的值。这就是这个层每个单元输出一个不同值的原因——因为它们的偏置项不同。

我们通过用 Leaky ReLU 替换 ReLU 解决了这个问题,前者允许梯度传播,即使输入为负时。

我们没想到会在此次分析中发现「死神经元」,但最难找到的错误是你没打算找的。

三、梯度分析

梯度的作用当然不止是优化损失函数。在梯度下降中,我们计算与Δparameter 对应的Δloss。尽管通常意义上梯度计算的是改变一个变量对另一个变量的影响。由于梯度计算在梯度下降方法中是必需的,所以像 TensorFlow 这样的框架都提供了计算梯度的函数。

我们使用梯度分析来确定我们的深度神经网络能否捕捉数据中的长期依赖。DNN 的输入数据特别长:4096 个时间步长的心率或者计步数据。我们的模型架构能否捕捉数据中的长期依赖非常重要。例如,心率的恢复时间可以预测糖尿病。这就是锻炼后恢复至休息时的心率所耗的时间。为了计算它,深度神经网络必须能够计算出你休息时的心率,并记住你结束锻炼的时间。

衡量模型能否追踪长期依赖的一种简单方法是去检查输入数据的每个时间步长对输出预测的影响。如果后面的时间步长具有特别大的影响,则说明模型没有有效地利用早期数据。

对于所有时间步长 t,我们想要计算的梯度是与Δinput_t 对应的Δoutput。下面是用 Keras 和 TensorFlow 计算这个梯度的代码示例:

def gradient_output_wrt_input(model, data):
  # [:, 2048, 0] means all users in batch, midpoint timestep, 0th task (diabetes)
  output_tensor = model.model.get_layer('raw_output').output[:, 2048, 0]
  # output_tensor.shape == (num_users)

  # Average output over all users. Result is a scalar.
  output_tensor_sum = tf.reduce_mean(output_tensor)

  inputs = model.model.inputs # (num_users x num_timesteps x num_input_channels)
  gradient_tensors = tf.gradients(output_tensor_sum, inputs)
  # gradient_tensors.shape == (num_users x num_timesteps x num_input_channels)

  # Average over users
  gradient_tensors = tf.reduce_mean(gradient_tensors, axis=0)
  # gradient_tensors.shape == (num_timesteps x num_input_channels)
  # eg gradient_tensor[10, 0] is deriv of last output wrt 10th input heart rate

  # Convert to Keras function
  k_gradients = K.function(inputs=inputs, outputs=gradient_tensors)

  # Apply function to dataset
  return k_gradients([data.X])

在上面的代码中,我们在平均池化之前,在中点时间步长 2048 处计算了输出。我们之所以使用中点而不是最后的时间步长的原因是,我们的 LSTM 单元是双向的,这意味着对一半的单元来说,4095 实际上是第一个时间步长。我们将得到的梯度进行了可视化:

Δoutput_2048 / Δinput_t

请注意我们的 y 轴是 log 尺度的。在时间步长 2048 处,与输入对应的输出梯度是 0.001。但是在时间步长 2500 处,对应的梯度小了一百万倍!通过梯度分析,我们发现这个架构无法捕捉长期依赖。

四、分析模型预测

你可能已经通过观察像 AUROC 和平均绝对误差这样的指标分析了模型预测。你还可以用更多的分析来理解模型的行为。

例如,我们好奇 DNN 是否真的用心率输入来生成预测,或者说它的学习是不是严重依赖于所提供的元数据——我们用性别、年龄这样的用户元数据来初始化 LSTM 的状态。为了理解这个,我们将模型与在元数据上训练的 logistic 回归模型做了对比。

DNN 模型接收了一周的用户数据,所以在下面的散点图中,每个点代表的是一个用户周。

这幅图验证了我们的猜想,因为预测结果并不是高度相关的。

除了进行汇总分析,查看最好和最坏的样本也是很有启发性的。对一个二分类任务而言,你需要查看最令人震惊的假阳性假阴性(也就是预测距离标签最远的情况)。尝试鉴别损失模式,然后过滤掉在你的真阳性和真阴性中出现的这种模式。

一旦你对损失模式有了假设,就通过分层分析进行测试。例如,如果最高损失全部来自第一代 Apple Watch,我们可以用第一代 Apple Watch 计算我们的调优集中用户集的准确率指标,并将这些指标与在剩余调优集上计算的指标进行比较。


原文链接:https://blog.cardiogr.am/4-ways-to-debug-your-deep-neural-network-e5edb14a12d7

工程激活函数线性整流函数Logistic 回归神经网络
8
相关数据
深度学习技术

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

池化技术

池化(Pooling)是卷积神经网络中的一个重要的概念,它实际上是一种形式的降采样。有多种不同形式的非线性池化函数,而其中“最大池化(Max pooling)”是最为常见的。它是将输入的图像划分为若干个矩形区域,对每个子区域输出最大值。直觉上,这种机制能够有效的原因在于,在发现一个特征之后,它的精确位置远不及它和其他特征的相对位置的关系重要。池化层会不断地减小数据的空间大小,因此参数的数量和计算量也会下降,这在一定程度上也控制了过拟合。通常来说,CNN的卷积层之间都会周期性地插入池化层。

激活函数技术

在 计算网络中, 一个节点的激活函数定义了该节点在给定的输入或输入的集合下的输出。标准的计算机芯片电路可以看作是根据输入得到"开"(1)或"关"(0)输出的数字网络激活函数。这与神经网络中的线性感知机的行为类似。 一种函数(例如 ReLU 或 S 型函数),用于对上一层的所有输入求加权和,然后生成一个输出值(通常为非线性值),并将其传递给下一层。

机器学习技术

机器学习是人工智能的一个分支,是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科。机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。因为学习算法中涉及了大量的统计学理论,机器学习与推断统计学联系尤为密切,也被称为统计学习理论。算法设计方面,机器学习理论关注可以实现的,行之有效的学习算法。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

假阳性技术

假阳性是指模型因为种种原因把不应该分类成特定情况的人/物错误地分类到了该分类的情况。

损失函数技术

在数学优化,统计学,计量经济学,决策理论,机器学习和计算神经科学等领域,损失函数或成本函数是将一或多个变量的一个事件或值映射为可以直观地表示某种与之相关“成本”的实数的函数。

TensorFlow技术

TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习。目前被50个团队用于研究和生产许多Google商业产品,如语音识别、Gmail、Google 相册和搜索,其中许多产品曾使用过其前任软件DistBelief。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

梯度下降技术

梯度下降是用于查找函数最小值的一阶迭代优化算法。 要使用梯度下降找到函数的局部最小值,可以采用与当前点的函数梯度(或近似梯度)的负值成比例的步骤。 如果采取的步骤与梯度的正值成比例,则接近该函数的局部最大值,被称为梯度上升。

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

神经元技术

(人工)神经元是一个类比于生物神经元的数学计算模型,是神经网络的基本组成单元。 对于生物神经网络,每个神经元与其他神经元相连,当它“兴奋”时会向相连的神经元发送化学物质,从而改变这些神经元的电位;神经元的“兴奋”由其电位决定,当它的电位超过一个“阈值”(threshold)便会被激活,亦即“兴奋”。 目前最常见的神经元模型是基于1943年 Warren McCulloch 和 Walter Pitts提出的“M-P 神经元模型”。 在这个模型中,神经元通过带权重的连接接处理来自n个其他神经元的输入信号,其总输入值将与神经元的阈值进行比较,最后通过“激活函数”(activation function)产生神经元的输出。

假阴性技术

假阳性是指模型因为种种原因将应该分类成特定情况的人/物错误地分类到了其他分类的情况。

深度神经网络技术

深度神经网络(DNN)是深度学习的一种框架,它是一种具备至少一个隐层的神经网络。与浅层神经网络类似,深度神经网络也能够为复杂非线性系统提供建模,但多出的层次为模型提供了更高的抽象层次,因而提高了模型的能力。

推荐文章
暂无评论
暂无评论~