Python 迁移学习实用指南:1~5(2)https://developer.aliyun.com/article/1426847
数学上,softmax 函数如下所示,其中z
是输出层输入的向量(如果有 10 个输出单元,则z
中有 10 个元素)。 同样,j
索引输出单元,因此j = 1, 2, ..., K
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9G03nSSn-1681567233321)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/c6d124bb-1721-4458-82e8-4d805f6440b6.png)]
学习一个简单的非线性单元 – Logistic 单元
假设我们有两个类分类问题; 也就是说,我们需要预测二元结果变量y
的值。 就概率而言,结果y
取决于特征x
的伯努利分布。 神经网络需要预测概率P(y = 1 | x)
。 为了使神经网络的输出成为有效概率,它应该位于[0, 1]
中。 为此,我们使用 Sigmoid 激活函数并获得非线性逻辑单元。
要学习逻辑单元的权重,首先我们需要一个成本函数并找到成本函数的导数。 从概率的角度来看,如果我们想最大化输入数据的可能性,则交叉熵损失会作为自然成本函数出现。 假设我们有一个训练数据集X = {x[n], t[n]}
,n = 1, …, N
,似然函数可以写成:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4qwyJfeL-1681567233321)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/9b17fcb0-2380-4a14-a86a-bf3bf235f078.png)]
其中y[n]
是在将x[n]
作为输入数据传递到逻辑单元之后,Sigmoid 单元的输出。 注意t
和w
分别表示 Sigmoid 单元的目标向量(训练集中的所有N
个目标值)和权重向量(所有权重的集合)。 可以通过采用似然性的负算法来定义误差函数,这给出了交叉熵代价函数:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-krI4KNaf-1681567233321)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/504e31b7-bbd1-4ae6-ae1c-a09536802838.png)]
要学习逻辑神经单元的权重,我们需要关于每个权重的输出导数。 我们将使用导数的链式规则来导出逻辑单元的误差导数:
让:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vW8tJKzH-1681567233321)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/7628813a-e498-4e7a-9eaa-160d5169eebb.png)]
因此:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fmU9gtPs-1681567233322)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/f774189e-1543-4caf-b12e-a89dcb004d66.png)]
就线性单元的平方误差损失而言,我们发现的导数看起来与导数非常相似,但它们并不相同。 让我们仔细看一下交叉熵损失,看看它与平方误差有何不同。 我们可以如下重写交叉熵损失:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JvCKentw-1681567233322)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/d7ee5e5b-72b4-4115-a7e2-f5f0834b7053.png)]
- 因此,对于
t[n] = 1
,y[n] = 1 => E(w) = 0
,但y[n] = 0 => E(w) = +∞
- 对于
t[n] = 0
,y[n] = 1 => E(w) = +∞
,但y[n] = 0 => E(w) = 0
- 也就是说,如果类别标签的预测和真实值不同,则该算法将受到很大的惩罚。
现在,让我们尝试将平方误差损失与逻辑输出一起使用。 因此,我们的成本函数为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-frPF8Svx-1681567233322)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/67da829c-5832-4cb4-8d09-fe4617f87e1c.png)]
因此:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2nkkyKwo-1681567233322)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/780a5531-7c6f-4872-b6fd-dba4f22ac05f.png)]
该误差导数直接取决于 Sigmoid 函数σ'(y[n])
的导数。 现在,当y[n]
高度负值时,Sigmoid 函数趋于 0;当y[n]
高度正值时,Sigmoid 函数趋于 1。 从 Sigmoid 曲线的平坦水平区域可以明显看出,对于y[n]
的这种值,梯度可以缩小得太小。 因此,即使t[n]
和y[n]
不一致,对于这些数据点,平方误差导数也将具有很小的更新。 也就是说,它们被网络严重错误分类。 这称为消失梯度问题。 因此,基于最大似然的交叉熵损失几乎始终是训练逻辑单元的首选损失函数。
损失函数
损失函数将神经网络的输出与训练中的目标值进行比较,产生一个损失值/分数,以测量网络的预测与期望值的匹配程度。 在上一节中,我们看到了针对不同任务(例如回归和二分类)的不同类型损失函数的需求。 以下是一些其他流行的损失函数:
- 二元交叉熵:关于逻辑单元的上一节讨论的两类分类问题的对数损失或交叉熵损失。
- 分类交叉熵:如果我们有 K 类分类问题,那么我们将广义交叉熵用于 K 类。
- 均方误差:这是我们讨论过几次的均方和误差。 这广泛用于各种回归任务。
- 平均绝对误差:测量一组预测中误差的平均大小,而不考虑其方向。 这是测试样本中预测值与实际观测值之间的绝对差异的平均值。 平均绝对误差(MAE)对大误差赋予相对较高的权重,因为它会平方误差。
- 平均绝对百分比误差:以百分比形式度量误差的大小。 计算为无符号百分比误差的平均值。 使用平均绝对百分比误差(MAPE)是因为容易理解百分比。
- 铰链损失/平方铰链损失:铰链损耗用于 SVM。 他们对边际错误分类点的惩罚不同。 它们是克服交叉熵损失的好选择,并且还可以更快地训练神经网络。 对于某些分类任务,更高阶的铰链损耗(例如平方铰损耗)甚至更好。
- Kullback-Leibler(KL)散度:KL 散度是一种概率分布与第二个预期概率分布之间如何偏离的度量。
数据表示
神经网络训练的训练集中的所有输入和目标都必须表示为张量(或多维数组)。 张量实际上是将二维矩阵推广到任意数量的维。 通常,这些是浮点张量或整数张量。 无论原始输入数据类型是什么(图像,声音,文本),都应首先将其转换为合适的张量表示形式。 此步骤称为数据向量化。 以下是本书中经常使用的不同维度的张量:
- 零维张量或标量:仅包含一个数字的张量称为零维张量,零维张量或标量。
- 一维张量或向量:包含数字数组的张量称为向量或一维张量。 张量的维数也称为张量的轴。 一维张量恰好具有一个轴。
- 矩阵(二维张量):包含向量数组的张量是矩阵或二维张量。 矩阵具有两个轴(由行和列表示)。
- 三维张量:通过将一组(相同维度的)矩阵堆叠在一个数组中,我们得到一个三维张量。
通过将三维张量放置在一个数组中,可以创建三维张量。 等等。 在深度学习中,通常我们使用零维到四维张量。
张量具有三个关键属性:
- 轴的尺寸或数量
- 张量的形状,即张量在每个轴上具有多少个元素
- 数据类型 - 是整数张量还是浮点型张量
张量示例
以下是在讨论迁移学习用例时将经常使用的一些示例张量。
- 时间序列数据:典型的时间序列数据将具有时间维度,并且该维度将对应于每个时间步的特征。 例如,一天中每小时的温度和湿度测量是一个时间序列数据,可以用形状为
(24, 2)
的 2D 张量表示。 因此,数据批量将由 3D 张量表示。 - 图像数据:图像通常具有三个维度:宽度,高度和颜色通道。 因此,可以用 3D 张量表示。 图像批量由 4D 张量表示,如下图所示。
- 视频数据:视频由图像帧组成。 因此,要表示单个视频,我们还需要一个尺寸。 一帧是彩色图像,需要三个维度来表示一帧。 该视频由形状(帧,宽度,高度,颜色通道)的 4D 张量表示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dZgRy1JN-1681567233322)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/e567faa7-d096-4c23-a921-00b647dced4f.png)]
- 作为张量的数据批次:假设我们有一批 10 张图像。 诸如 MNIST 数据中的二元图像可以由 2D 张量表示。 对于一批 10 张图像,可以用 3D 张量表示。 此 3D 张量的第一个轴(轴 0)称为批次尺寸。
张量运算
可以通过一组张量运算来表述用于训练/测试深度神经网络的所有计算。 例如,张量的相加,相乘和相减。 以下是本书中一些常用的张量运算:
- 逐元素运算:在深度学习中非常普遍地将函数独立地应用于张量的所有元素。 例如,将激活函数应用于层中的所有单元。 其他按元素进行的运算包括将基本数学运算符(例如
+
,-
和*
)按元素进行对相同形状的两个张量进行运算。 - 张量点积:两个张量的点积与两个张量的元素乘积不同。 两个向量的点积是一个标量,等于两个向量的元素乘积之和。 矩阵和兼容形状的向量的点积是向量,而兼容形状的两个矩阵的点积是另一个矩阵。 对于具有兼容形状的两个矩阵 x,y,我们的意思是要定义点
(x, y)
,我们应具有x.shape[1] = y.shape[0]
。 - 广播:假设我们要添加两个形状不同的张量。 这通常出现在神经网络的每一层。 让我们以 ReLU 层为例。 ReLU 层可以通过张量操作表示如下:
output = relu(dot(W, input) + b)
。 在这里,我们正在计算权重矩阵与输入向量x
的点积。 这将产生一个向量,然后添加一个标量偏差项。 实际上,我们希望将偏置项添加到点积输出向量的每个元素中。 但是,偏置张量是零维张量,向量是一维。 因此,这里我们需要广播较小的张量以匹配较大张量的形状。 广播涉及两个步骤:将轴添加到较小的张量以匹配较大张量的尺寸。 然后,重复较小的张量以匹配较大张量的形状。 我们将通过一个具体示例对此进行说明:令x
为形状(32, 10)
,y
为形状(10)
。 我们要计算x + y
。 在广播的第一步之后,我们将轴添加到y
(较小的张量),并得到形状为(1, 10)
的张量y1
。 为了匹配x
的尺寸,我们将y1
重复 32 次,并得到形状为(32, 10)
的y2
张量。 然后,我们计算元素加法x + y2
。 - 重塑:张量重塑是沿轴向重新排列张量元素的操作。 重塑的一个简单示例是转置 2D 张量。 在矩阵的转置操作中,行和列互换。 重塑的另一个例子是拉紧张量。 通过将张量的所有元素沿一个轴放置,可以将多维张量重塑为向量或一维张量。 以下是 TensorFlow 中的一些张量操作实现示例:
#EXAMPLE of Tensor Operations using tensorflow. import tensorflow as tf # Initialize 3 constants: 2 vectors, a scalar and a 2D tensor x1 = tf.constant([1,2,3,4]) x2 = tf.constant([5,6,7,8]) b = tf.constant(10) W = tf.constant(-1, shape=[4, 2]) # Elementwise Multiply/subtract res_elem_wise_mult = tf.multiply(x1, x2) res_elem_wise_sub = tf.subtract(x1, x2) #dot product of two tensors of compatable shapes res_dot_product = tf.tensordot(x1, x2, axes=1) #broadcasting : add scalar 10 to all elements of the vector res_broadcast = tf.add(x1, b) #Calculating Wtx res_matrix_vector_dot = tf.multiply(tf.transpose(W), x1) #scalar multiplication scal_mult_matrix = tf.scalar_mul(scalar=10, x=W) # Initialize Session and execute with tf.Session() as sess: output = sess.run([res_elem_wise_mult,res_elem_wise_sub, res_dot_product, res_broadcast,res_matrix_vector_dot, scal_mult_matrix]) print(output)
多层神经网络
单层非线性单元对于它可以学习的输入输出转换的能力仍然有限。 可以通过查看 XOR 问题来解释。 在 XOR 问题中,我们需要一个神经网络模型来学习 XOR 函数。 XOR 函数采用两个布尔输入,如果它们不同则输出 1,如果输入相同则输出 0。
我们可以将其视为输入模式为X = {(0, 0), (0, 1), (1, 0), (1, 1)}
的模式分类问题。 第一个和第四个在类 0 中,其他在第 1 类中。让我们将此问题视为回归问题,损失为均方误差(MSE),并尝试使用线性单元。 通过分析求解,得出所需权重:w = (0, 0)
和偏差:b = 1/2
。 该模型为所有输入值输出 0.5。 因此,简单的线性神经元无法学习 XOR 函数。
解决 XOR 问题的一种方法是使用输入的不同表示形式,以便线性模型能够找到解决方案。 这可以通过向网络添加非线性隐藏层来实现。 我们将使用带有两个隐藏单元的 ReLU 层。 输出是布尔值,因此最适合的输出神经元是逻辑单元。 我们可以使用二元交叉熵损失来学习权重:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HIaHqEyN-1681567233323)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/7c2d473b-3c3c-4d00-ab64-c2a35fe6dfc3.png)]
让我们使用 SGD 学习此网络的权重。 以下是 XOR 函数学习问题的keras
代码:
model_input = Input(shape=(2,), dtype='float32') z = Dense(2,name='HiddenLayer', kernel_initializer='ones')(model_input) z = Activation('relu')(z) #hidden activation ReLu z = Dense(1, name='OutputLayer')(z) model_output = Activation('sigmoid')(z) #Output activation model = Model(model_input, model_output) model.summary() #Compile model with SGD optimization, with learning rate = 0.5 sgd = SGD(lr=0.5) model.compile(loss="binary_crossentropy", optimizer=sgd) #The data set is very small - will use full batch - setting batch size = 4 model.fit(X, y, batch_size=4, epochs=300,verbose=0) #Output of model preds = np.round(model.predict(X),decimals=3) pd.DataFrame({'Y_actual':list(y), 'Predictions':list(preds)})
前面代码的输出如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kDvOgtzq-1681567233323)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/b78cd483-fea2-4c10-81ef-85f419250bd9.png)]
(左)显示 4 点的原始空间-显然没有行可以将 0 类{(0, 0), (1, 1)}
与其他类分开。 (中心)显示隐藏的 ReLU 层学习到的变换空间。 (右)该表显示了通过该函数获得的预测值
具有一层隐藏层的神经网络能够学习 XOR 函数。 这个例子说明了神经网络需要非线性隐藏层来做有意义的事情。 让我们仔细看一下隐藏层学习了哪些输入转换,从而使输出逻辑神经元学习该函数。 在 Keras 中,我们可以从学习的模型中提取中间隐藏层,并使用它来提取传递给输出层之前输入的转换。 上图显示了如何转换四个点的输入空间。 转换后,可以用一条线轻松地分隔 1 类和 0 类点。 这是为原始空间和变换后的空间生成图的代码:
import matplotlib.pyplot as plt #Extract intermediate Layer function from Model hidden_layer_output = Model(inputs=model.input, outputs=model.get_layer('HiddenLayer').output) projection = hidden_layer_output.predict(X) #use predict function to extract the transformations
#Plotting the transformed input fig = plt.figure(figsize=(5,10)) ax = fig.add_subplot(211) plt.scatter(x=projection[:, 0], y=projection[:, 1], c=('g'))
通过堆叠多个非线性隐藏层,我们可以构建能够学习非常复杂的非线性输入输出转换的网络。
反向传播 – 训练深度神经网络
为了训练深层的神经网络,我们仍然可以使用梯度下降 SGD。 但是,SGD 将需要针对网络的所有权重计算损失函数的导数。 我们已经看到了如何应用导数链式规则来计算逻辑单元的导数。
现在,对于更深的网络,我们可以逐层递归地应用相同的链式规则,以获得与网络中不同深度处的层对应的权重有关的损失函数的导数。 这称为反向传播算法。
反向传播技术是在 1970 年代发明的,它是一种用于对复杂的嵌套函数或函数的函数进行自动微分的一般优化方法。 但是,直到 1986 年,Rumelhart,Hinton 和 Williams 发表了一篇论文,标题为《通过反向传播的误差学习算法》,该算法的重要性已为大型 ML 社区所认可。 反向传播是最早能够证明人工神经网络可以学习良好内部表示的方法之一。 也就是说,它们的隐藏层学习了非平凡的特征。
反向传播算法是在单个训练示例上针对每个权重计算误差导数dE/dθ
的有效方法。 为了理解反向传播算法,让我们首先代表一个带有计算图符号的神经网络。 神经网络的计算图将具有节点和有向边,其中节点代表变量(张量),边代表连接到下一个变量的变量的运算。 如果y = f(x)
,则变量x
通过有向边连接到y
,对于某些函数f
。
例如,逻辑单元的图形可以表示如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GbAVlkh9-1681567233323)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/4654a29a-6aef-4c89-8ad1-e7dc98dbb64f.png)]
(左)逻辑回归作为计算图。 (右)三层网络计算图的 BP 算法信息流
我们用u[1], u[2], ..., u[n]
表示计算节点。 另外,我们按顺序排列节点,以便可以一个接一个地计算它们。 u[n]
是一个标量-损失函数。 让我们用节点θ[k]
表示网络的参数或权重。 要应用梯度下降,我们需要计算所有导数∂u^n/∂θ[k]
。 可以通过遵循从输入节点到最终节点∂u^n
的计算图中的有向路径来计算该图的正向计算。 这称为前向传播。
由于图中的节点为张量,因此要计算偏导数∂u^n/∂θ[k]
,将使用多个变量函数的导数链式规则,该规则由雅可比矩阵与梯度的乘积表示。 反向传播算法涉及一系列这样的雅可比梯度积。
反向传播算法表示如下:
- 给定输入向量
X = {x[n]}
,目标向量Y = {t[n]}
,用于测量网络误差的成本函数C
以及网络的初始权重集,以计算网络的前向通过并计算损耗C
- 向后传递-对于每个训练示例
(x[n], t[n])
,针对每个层参数/权重计算损耗的导数C
-此步骤讨论如下:
- 通过对输入目标对或它们的小批量的所有梯度求平均值来组合各个梯度
- 更新每个参数
Δθ[l] = -α · ∂C/∂θ[l]
,α
为学习率
我们将使用完全连接的三层神经网络解释反向传播。 上图显示了为此的计算图。 令z(i)
表示图中的计算节点。 为了执行反向传播,导数∂C/∂z(i)
的计算将与正向传递的反向顺序完全相同。 这些由向下箭头指示。 让我们表示关于层l
的输入z(l)
的成本函数的导数δ(l)
。 对于最顶层,让δ(4) = 1
。 为了递归计算,让我们考虑一个单层。 一层具有输入z(l)
和输出z(l+1)
。 同样,该层将接受输入δ(l + 1)
并产生δ(l)
和∂C/∂θ[l]
。
对于层l
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Np4Bb0TP-1681567233323)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/05f06392-f5cc-44ff-8755-ebeded169ff2.png)]
i
代表梯度δ(l)[i]
的第i
个分量。
因此,我们得出了用于计算反向消息的递归公式。 使用这些,我们还可以计算关于模型参数的成本导数,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9peOzrJw-1681567233324)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/05544f28-196c-4245-83df-4fcf348f236d.png)]
反向传播算法在计算图中相对于其祖先x
,计算标量成本函数z
的梯度。 该算法开始于计算关于其本身的成本z
的导数∂z/∂z = 1
。 可以通过将当前梯度乘以产生z
的运算的雅可比行列式来计算关于z
父级的梯度。 我们一直向后遍历计算图并乘以雅可比行列式,直到达到输入x
为止。
神经网络学习中的挑战
通常,优化是一项非常困难的任务。 在本节中,我们讨论了用于训练深度模型的优化方法所涉及的一些常见挑战。 了解这些挑战对于评估神经网络模型的训练表现并采取纠正措施以缓解问题至关重要。
病态条件
矩阵的条件数是最大奇异值与最小奇异值之比。 如果条件数非常高,则矩阵是病态的,通常表示最低的奇异值比最高的奇异值小几个数量级,并且矩阵的行彼此高度相关。 这是优化中非常普遍的问题。 实际上,这甚至使凸优化问题也难以解决。 通常,神经网络会出现此问题,这会导致 SGD 卡住,即,尽管存在很强的梯度,学习也会变得非常缓慢。 对于具有良好条件数(接近 1)的数据集,误差轮廓几乎是圆形的,并且负梯度始终笔直指向误差表面的最小值。 对于条件差的数据集,误差表面在一个或多个方向上相对平坦,而在其他方向上则强烈弯曲。 对于复杂的神经网络,可能无法通过解析找到 Hessian 和病态效应。 但是,可以通过在训练周期内绘制平方梯度范数和g^T H[g]
来绘制图表,以监控疾病的影响。
让我们考虑我们要优化的f(x)
函数的二阶泰勒级数逼近。z[0]
点的泰勒级数由下式给出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VR9l7kff-1681567233324)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/28d6a247-eb12-45c2-a471-8673b8610e63.png)]
其中g
是梯度向量, H
是f(x)
在x[0]
时的 Hessian。 如果ε
是我们使用的学习率,则根据梯度下降的新点为x[0] - ε[g]
。 将其替换为 Taylor 系列展开式,我们得到:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iigbiBQp-1681567233324)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/88f6f0bb-b7d9-4a33-8d96-f46e8db8138b.png)]
注意,如果-ε g^t g + ½ε^2 g^T H[g] > 0
,则与x[0]
相比,新点的函数值会增加。 同样,在存在强梯度的情况下,我们将具有较高的平方梯度范数||g||^2 = g^T g
,但同时,如果其他数量为g^T H[g]
增长一个数量级,那么我们将看到f(x)
的下降速度非常缓慢。 但是,如果此时可以缩小学习率ε
,则可能会在某种程度上使这种影响无效,因为g^T H[g]
数量乘以ε^2
。 可以通过在训练周期绘制平方梯度范数和g^T H[g]
来监测疾病的影响。 我们在热板中看到了如何计算梯度范数的示例。
局部最小值和鞍点
DNN 模型实质上可以保证具有极大数量的局部最小值。 如果局部最小值与全局最小值相比成本较高,则可能会出现问题。 长期以来,人们一直认为,由于存在这样的局部极小值,神经网络训练受到了困扰。 这仍然是一个活跃的研究领域,但是现在怀疑对于 DNN,大多数局部最小值具有较低的成本值,没有必要找到全局最小值,而是在权重空间中具有足够低的成本函数值。 可以通过监视梯度范数来检测强局部极小值的存在。 如果梯度范数减小到很小的数量级,则表明存在局部极小值。
鞍点是既不是最大值也不是最小值的点,而是被平坦区域围绕,该平坦区域的一侧目标函数值增大,而另一侧目标函数减小。 由于该平坦区域,梯度变得非常小。 然而,已经观察到,凭经验梯度下降迅速逃离了这些区域。
悬崖和梯度爆炸
高度非线性 DNN 的目标函数具有非常陡峭的区域,类似于悬崖,如下图所示。 在极陡峭的悬崖结构的负梯度方向上移动会使权重移得太远,以致我们完全跳下悬崖结构。 因此,在我们非常接近的时候错过了极小值。
因此,取消了为达到当前解决方案所做的许多工作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fPZ8r2pA-1681567233324)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/7da599f5-2250-4acf-b6ef-e8dd7d188957.png)]
解释何时需要裁剪梯度范数
我们可以通过裁剪梯度来避免梯度下降中的此类不良动作,也就是说,设置梯度幅度的上限。 我们记得梯度下降是基于函数的一阶泰勒近似。 这种近似在计算梯度的点附近的无穷小区域中保持良好。 如果我们跳出该区域,成本函数可能开始增加或向上弯曲。 因此,我们需要限制移动的时间。 梯度仍然可以给出大致正确的方向。 必须将更新选择为足够小,以避免越过向上的弯曲。 一种实现此目的的方法是通过设置标准的上限阈值来限制梯度边界:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WWrj8RVe-1681567233325)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/2fbcbddc-c681-475e-a924-7491c6bcf2a8.png)]
在 Keras 中,可以如下实现:
#The parameters clipnorm and clipvalue can be used with all optimizers #to control gradient clipping: from keras import optimizers # All parameter gradients will be clipped to max norm of 1.0 sgd = optimizers.SGD(lr=0.01, clipnorm=1.) #Similarly for ADAM optmizer adam = optimizers.Adam(clipnorm=1.)
初始化 – 目标的本地和全局结构之间的不良对应关系
要启动数值优化算法(例如 SGD),我们需要初始化权重。 如果我们具有目标函数,如下图所示,通过进行 SGD 建议的局部移动,我们将浪费大量时间,如果我们从真正的极小值所在的山侧开始。 在这种情况下,目标函数的局部结构不会给出任何关于最小值位于何处的提示。 可以通过适当的初始化来避免这种情况。 如果我们可以在山的另一侧的某个位置启动 SGD,则优化会快得多:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvsHcfyF-1681567233325)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/a59194e9-3b84-4be6-b6d2-f1d2fa8c7f01.png)]
解释初始化误差的情况以及对基于梯度的优化的影响
不精确的梯度
大多数优化算法都是基于这样的假设,即我们在给定点具有已知的精确梯度。 但是,实际上我们只对梯度有一个估计。 这个估计有多好? 在 SGD 中,批次大小会极大地影响随机优化算法的行为,因为它确定了梯度估计的方差。
总之,可以通过以下四个技巧来解决神经网络训练中面临的不同问题:
- 选择合适的学习率,可能是每个参数的自适应学习率
- 选择合适的批次大小 - 梯度估计取决于此
- 选择权重的良好初始化
- 为隐藏层选择正确的激活函数
现在,让我们简要讨论一下各种启发式方法/策略,这些方法使学习 DNN 切实可行并继续使深度学习取得巨大成功。
模型参数的初始化
以下是初始点的选择如何影响深度神经网络的迭代学习算法的表现:
- 初始点可以确定学习是否会收敛
- 即使学习收敛,收敛的速度也取决于起始点
- 成本相似的初始点可能具有不同的泛化误差
初始化算法主要是启发式的。 良好初始化的全部要点是可以以某种方式使学习更快。 初始化的重要方面之一是破坏初始权重集对隐藏层单元的对称性。 如果以相同的权重对其进行初始化,则在网络相同级别上具有相同激活函数的两个单元将被同等更新。 多个单元保留在隐藏层中的原因是它们应该学习不同的特征。 因此,获得同等更新不会影响其他特征的学习。
打破对称性的一种简单方法是使用随机初始化-从高斯或均匀分布中采样。 模型中的偏差参数可以通过启发式选择常量。 选择权重的大小取决于优化和正则化之间的权衡。 正则化要求权重不应太大-这可能导致不良的泛化表现。 优化需要权重足够大,才能成功地通过网络传播信息。
启发式初始化
让我们考虑具有m
输入和n
输出单元的密集层:
- 从均匀分布
[-1/√m, 1/√m]
中采样每个权重。 - Glorot 和 Bengio 建议使用统一分布初始化的规范化版本:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0MM8PpJP-1681567233325)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/f9f07288-c498-4754-98ab-67000c76d58c.png)]
它被设计为在每一层中具有相同的梯度变化,称为 Glorot Uniform 。 - 从平均值为 0 且方差为
√(2/(m+n))
的正态分布中采样每个权重。 这类似于 Glorot Uniform,称为 Glorot Normal。 - 对于非常大的层,单个权重将变得非常小。 要解决此问题,另一种方法是仅初始化 k 非零权重。 这称为稀疏初始化。
- 将权重初始化为随机正交矩阵。 可以在初始权重矩阵上使用 Gram-Schmidt 正交化。
初始化方案也可以视为神经网络训练中的超参数。 如果我们有足够的计算资源,则可以评估不同的初始化方案,我们可以选择具有最佳泛化表现和更快的收敛速度的方案。
SGD 的改进
近年来,已提出了不同的优化算法,这些算法使用不同的方程式更新模型的参数。
动量法
成本函数可能具有高曲率和较小但一致的梯度的区域。 这是由于 Hessian 矩阵的条件不佳以及随机梯度的方差。 SGD 在这些地区可能会放慢很多速度。 动量算法会累积先前梯度的指数加权移动平均值(EWMA),并朝该方向移动,而不是 SGD 建议的局部梯度方向。 指数加权由超参数α ∈ [0, 1)
控制,该超参数确定先前梯度的影响衰减的速度。 动量法通过组合相反符号的梯度来阻尼高曲率方向上的振荡。
Nesterov 动量
Nesterov 动量是动量算法的一种变体,仅在计算梯度时与动量方法不同。 标准动量法首先在当前位置计算梯度,然后在累积梯度的方向上发生较大的跳跃。 涅斯特罗夫动量首先沿先前累积的梯度的方向跃升,然后计算新点的梯度。 通过再次采用所有先前梯度的 EWMA 来校正新梯度:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hpx0UDKq-1681567233325)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/1cb15e3c-28b7-46d1-9475-859ca97ba73b.png)]
自适应学习率 – 每个连接均独立
在前面的方法中,将相同的学习率应用于所有参数更新。 由于数据稀疏,我们可能想在不同程度上更新参数。 诸如 AdaGrad,AdaDelta,RMSprop 和 Adam 之类的自适应梯度下降算法通过保持每个参数的学习率,提供了经典 SGD 的替代方法。
AdaGrad
AdaGrad 算法通过按与先前所有梯度的平方和值的平方根成比例的方式将它们成反比例缩放来调整每个连接的学习率。 因此,在误差表面的平缓倾斜方向上进行了较大的移动。 但是,从一开始就采用这种技巧可能会导致某些学习率急剧下降。 但是,AdaGrad 在一些深度学习任务上仍然表现出色。
RMSprop
RMSprop 通过采用先前平方梯度的 EWMA 来修改 AdaGrad 算法。 它具有移动平均参数ρ
,它控制移动平均的长度和比例。 这是深度神经网络训练最成功的算法之一。
Adam
自适应力矩(Adam)。 它充分利用了基于动量的算法和自适应学习率算法,并将它们组合在一起。 在此,动量算法应用于由 RMSprop 计算的重新缩放的梯度。
神经网络中的过拟合和欠拟合
与其他任何 ML 训练一样,用于训练深度学习模型的数据集也分为训练,测试和验证。 在模型的迭代训练期间,通常,验证误差比训练误差略大。 如果测试误差和验证误差之间的差距随着迭代的增加而增加,则是过拟合的情况。 如果训练误差不再减小到足够低的值,我们可以得出结论,该模型是欠拟合的。
模型容量
模型的能力描述了模型可以建模的输入输出关系的复杂性。 也就是说,在模型的假设空间中允许有多大的函数集。 例如,可以将线性回归模型推广为包括多项式,而不只是线性函数。 这可以通过在构建模型时将 x 的 n 积分乘以 x 作为积分来完成。 还可以通过向网络添加多个隐藏的非线性层来控制模型的容量。 因此,我们可以使神经网络模型更宽或更深,或两者同时进行,以增加模型的容量。
但是,在模型容量和模型的泛化误差之间需要权衡:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6h0FqmLD-1681567233325)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/1fa01356-977d-41e1-ab20-36fab28171bf.png)]
(左):线性函数根据数据拟合而拟合。 (中):适合数据的二次函数可以很好地推广到看不见的点
(右)适合数据的次数为 9 的多项式存在过拟合的问题
具有极高容量的模型可能通过训练集中的学习模式而过拟合训练集,而训练模式可能无法很好地推广到看不见的测试集。 而且,它非常适合少量的训练数据。 另一方面,低容量的模型可能难以适应训练集:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w5SKZYSo-1681567233326)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/2ade6f4c-448f-4fad-acd7-2ef73fac4d5e.png)]
在训练和验证损失方面过拟合/欠拟合
如何避免过拟合 - 正则化
过拟合是 ML 中的核心问题。 对于神经网络,开发了许多策略来避免过拟合并减少泛化误差。 这些策略统称为正则化。
权重共享
权重共享意味着同一组权重在网络的不同层中使用,因此我们需要优化的参数更少。 在一些流行的深度学习架构中可以看到这一点,例如暹罗网络和 RNN。 在几层中使用共享权重可以通过控制模型容量来更好地推广模型。 反向传播可以轻松合并线性权重约束,例如权重共享。 CNN 中使用了另一种权重分配方式,其中与完全连接的隐藏层不同,卷积层在局部区域之间具有连接。 在 CNN 中,假设可以将要由网络处理的输入(例如图像或文本)分解为具有相同性质的一组局部区域,因此可以使用相同的一组转换来处理它们。 是,共享权重。 RNN 可以被视为前馈网络,其中每个连续的层共享相同的权重集。
权重衰减
可以看到,像前面示例中的多项式一样,过拟合模型的权重非常大。 为了避免这种情况,可以将罚分项Ω
添加到目标函数中,这将使权重更接近原点。 因此,惩罚项应该是权重范数的函数。 同样,可以通过乘以超参数α
来控制惩罚项的效果。 因此我们的目标函数变为:E(w) + αΩ(w)
。 常用的惩罚条款是:
- L2 正则化:惩罚项由
Ω = 1/2 · ||w||^2
给出。 在回归文献中,这称为岭回归。 - L1 正则化:惩罚项由
Ω = ||w||[1] = Σ[i](w[i])
给出。 这称为 LASSO 回归。
L1 正则化导致稀疏解; 也就是说,它会将许多权重设置为零,因此可以作为回归问题的良好特征选择方法。
早期停止
随着对大型神经网络的训练的进行,训练误差会随着时间的推移而稳步减少,但如下图所示,验证集误差开始增加,超出了某些迭代:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U6hWAtrE-1681567233326)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/14c4482c-cab1-4fa7-841f-f1130804fa87.png)]
提前停止:训练与验证误差
如果在验证误差开始增加的时候停止训练,我们可以建立一个具有更好泛化表现的模型。 这称为提前停止。 它由耐心超参数控制,该参数设置了中止训练之前观察增加的验证集误差的次数。 提前停止可以单独使用,也可以与其他正则化策略结合使用。
丢弃法
丢弃法是一种在深度神经网络中进行正则化的计算廉价但功能强大的方法。 它可以分别应用于输入层和隐藏层。 通过在正向传递过程中将节点的输出设置为零,丢弃法随机掩盖了一部分节点的输出。 这等效于从层中删除一部分节点,并创建一个具有更少节点的新神经网络。 通常,在输入层上会删除 0.2 个节点,而在隐藏层中最多会删除 0.5 个节点。
模型平均(集成方法)在 ML 中被大量使用,通过组合各种模型的输出来减少泛化误差。 套袋是一种整体方法,其中通过从训练集中替换并随机抽样来构建 k 不同的数据集,并在每个模型上训练单独的 k 模型。 特别地,对于回归问题,模型的最终输出是 k 模型的输出的平均值。 还有其他组合策略。
还可以将丢弃视为一种模型平均方法,其中通过更改应用了丢弃的基本模型的各个层上的活动节点数来创建许多模型。
批量标准化
在 ML 中,通常的做法是先缩放并标准化输入的训练数据,然后再将其输入模型进行训练。 对于神经网络而言,缩放也是预处理步骤之一,并且已显示出模型表现的一些改进。 在将数据馈送到隐藏层之前,我们可以应用相同的技巧吗? 批量规范化基于此思想。 它通过减去激活的最小批量平均值μ
并除以最小批量标准差σ
来归一化前一层的激活。 在进行预测时,我们一次可能只有一个示例。 因此,不可能计算批次均值μ
和批次σ
。 将这些值替换为训练时收集的所有值的平均值。
我们需要更多数据吗?
使神经模型具有更好的概括性或测试表现的最佳方法是通过训练它获得更多数据。 实际上,我们的训练数据非常有限。 以下是一些用于获取更多训练数据的流行策略:
- 模拟合成一些训练样本:生成假训练数据并不总是那么容易。 但是,对于某些类型的数据,例如图像/视频/语音,可以将转换应用于原始数据以生成新数据。 例如,可以平移,旋转或缩放图像以生成新的图像样本。
- 带噪声的训练:将受控随机噪声添加到训练数据是另一种流行的数据增强策略。 噪声也可以添加到神经网络的隐藏层中。
神经网络的超参数
神经网络的架构级参数,例如隐藏层数,每个隐藏层的单元数,以及与训练相关的参数,例如学习率,优化器算法,优化器参数-动量,L1/L2 正则化器和丢弃法统称为神经网络的超参数。 神经网络的权重称为神经网络的参数。 一些超参数影响训练算法的时间和成本,而一些影响模型的泛化表现。
自动超参数调整
开发了多种用于超参数调整的方法。 但是,对于大多数参数,需要为每个超参数指定一个特定范围的值。 可以通过了解它们对模型容量的影响来设置大多数超参数。
网格搜索
网格搜索是对超参数空间的手动指定子集的详尽搜索。 网格搜索算法需要表现指标,例如交叉验证误差或验证集误差,以评估最佳可能参数。 通常,网格搜索涉及选择对数刻度的参数。 例如,可以从集合{50, 100, 200, 500, 1000,...}
中选择在集合{0.1, 0.01, 0.001, 0.0001}
内获得的学习率或多个隐藏单元。 网格搜索的计算成本随着超参数的数量呈指数增长。 因此,另一种流行的技术是随机网格搜索。 随机搜索从所有指定的参数范围中对参数采样固定次数。 当我们具有高维超参数空间时,发现这比穷举搜索更有效。 更好,因为可能存在一些不会显着影响损耗的超参数。
总结
在本章中,我们涉及了深度学习的基础知识。 我们真的赞扬您为实现这一目标所做的努力! 本章的目的是向您介绍与深度学习领域有关的核心概念和术语。 我们首先简要介绍了深度学习,然后介绍了当今深度学习领域中流行的框架。 还包括详细的分步指南,用于设置您自己的深度学习环境,以在 GPU 上开发和训练大规模深度学习模型。
最后,我们涵盖了围绕神经网络的基本概念,包括线性和非线性神经元,数据表示,链式规则,损失函数,多层网络和 SGD。 还讨论了神经网络中的学习挑战,包括围绕局部极小值和梯度爆炸的常见警告。 我们研究了神经网络中过拟合和欠拟合的问题,以及处理这些问题的策略。 然后,我们介绍了神经网络单元的流行初始化启发法。 除此之外,我们还探索了一些更新的优化技术,它们是对香草 SGD 的改进,其中包括 RMSprop 和 Adam 之类的流行方法。
在下一章中,我们将探讨深度学习模型周围的各种架构,这些架构可用于解决不同类型的问题。
三、了解深度学习架构
本章将着重于理解当今深度学习中存在的各种架构。 神经网络的许多成功都在于对神经网络架构的精心设计。 自 1960 年代的传统人工神经网络(ANNs)以来,我们已经走了很长一段路。 在本书中,我们介绍了基本模型架构,例如完全连接的深度神经网络,卷积神经网络(CNN),循环神经网络(RNN),长短期记忆(LSTM)网络,以及最新的胶囊网络。
在本章中,我们将介绍以下主题:
- 为什么神经网络架构设计很重要
- 各种流行的架构设计和应用
神经网络架构
架构一词是指神经网络的整体结构,包括其可以具有多少层以及各层中的单元应如何相互连接(例如,连续层中的单元可以完全连接) ,部分连接,或者甚至可以完全跳过下一层,然后再连接到网络中更高级别的一层。 随着模块化深度学习框架(例如 Caffe,Torch 和 TensorFlow)的出现,复杂的神经网络设计发生了革命性的变化。 现在,我们可以将神经网络设计与 Lego 块进行比较,在这里您可以构建几乎可以想象的任何结构。 但是,这些设计不仅仅是随机的猜测。 这些设计背后的直觉通常是由设计人员对问题的领域知识以及一些反复试验来精调最终设计的结果所驱动。
为什么需要不同的架构
前馈多层神经网络具有学习巨大的假设空间并提取每个非线性隐藏层中复杂特征的能力。 那么,为什么我们需要不同的架构? 让我们尝试理解这一点。
特征工程是机器学习(ML)中最重要的方面之一。 如果特征太少或不相关,则可能会导致拟合不足。 而且特征太多,可能会使数据过拟合。 创建一组好的手工制作的特征是一项繁琐,耗时且重复的任务。
深度学习带有一个希望,即给定足够的数据,深度学习模型能够自动确定正确的特征集,即复杂性不断增加的特征层次。 好吧,深度学习的希望是真实的,并且会产生误导。 深度学习确实在许多情况下简化了特征工程,但是它并没有完全消除对它的需求。 随着手动特征工程的减少,神经网络模型本身的架构变得越来越复杂。 特定架构旨在解决特定问题。 与手工特征工程相比,架构工程是一种更为通用的方法。 在架构工程中,与特征工程不同,领域知识不会硬编码为特定特征,而只会在抽象级别使用。 例如,如果我们要处理图像数据,则有关该数据的一个非常高级的信息是对象像素的二维局部性,而另一个是平移不变性。 换句话说,将猫的图像平移几个像素仍然可以保持猫的状态。
在特征工程方法中,我们必须使用非常具体的特征(例如边缘检测器,拐角检测器和各种平滑滤波器)来为任何图像处理/计算机视觉任务构建分类器。 现在,对于神经网络,我们如何编码二维局部性和翻译不变性信息? 如果将密集的完全连接层放置在输入数据层之前,则图像中的每个像素都将连接到密集层中的每个单元。 但是,来自两个空间遥远对象的像素不必连接到同一隐藏单元。 经过长时间的大量数据训练后,具有很强的 L1 正则化能力的神经网络可能能够稀疏权重。 我们可以设计架构以仅将本地连接限制到下一层。 少量的相邻像素(例如,像素的10 x 10
子图像)可能具有与隐藏层的一个单元的连接。 由于转换不变,因此可以重用这些连接中使用的权重。 CNN 就是这样做的。 这种权重重用策略还有其他好处,例如大大减少了模型参数的数量。 这有助于模型进行概括。
让我们再举一个例子,说明如何将抽象领域知识硬编码到神经网络中。 假设我们有时间数据或顺序数据。 正常的前馈网络会将每个输入示例视为独立于先前的输入。 因此,学习到的任何隐藏特征表示也应取决于数据的最近历史,而不仅仅是当前数据。 因此,神经网络应该具有一些反馈回路或记忆。 这个关键思想产生了循环神经网络架构及其现代的强大变体,例如 LSTM 网络。
其他高级 ML 问题(例如语音翻译,问题解答系统和关系建模)要求开发各种深度学习架构。
各种架构
现在让我们看一些流行的神经网络架构及其应用。 我们将从多层感知器(MLP)网络开始。 我们已经介绍了单层感知器网络,这是最基本的神经网络架构。
MLP 和深度神经网络
MLP 或简单的深层神经网络(DNNs)是神经网络架构的最基本形式。 神经单元一层又一层地排列,相邻的网络层彼此完全连接。 我们已经在上一章中对此进行了详细讨论:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oenQf7nx-1681567233326)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/12eeeba8-9883-4473-a839-66a9d7304c32.png)]
自编码器神经网络
自编码器通常用于减少神经网络中数据的维数。 自编码器也已成功用于异常检测和新颖性检测问题。 自编码器神经网络属于无监督学习类别。 在此,目标值设置为等于输入值。 换句话说,我们想学习单位特征。 通过这样做,我们可以获得数据的紧凑表示。
通过最小化输入和输出之间的差异来训练网络。 典型的自编码器架构是 DNN 架构的略微变体,其中,每个隐藏层的单元数量逐渐减少,直到某个点,然后逐渐增加,最终层尺寸等于输入尺寸。 其背后的关键思想是在网络中引入瓶颈,并迫使其学习有意义的紧凑表示形式。 隐藏单元的中间层(瓶颈)基本上是输入的降维编码。 隐藏层的前半部分称为编码器,后半部分称为解码器。 下面描述了一个简单的自编码器架构。 名为z
的层是此处的表示层:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EkdSmdTn-1681567233326)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/39e61d86-4db6-460c-a13b-8da4dbcd4889.png)]
变分自编码器
深度很深的自编码器很难训练,并且容易过度安装。 有许多改进了自编码器训练方式的开发,例如使用受限玻尔兹曼机(RBM)进行生成式预训练。 变分自编码器(VAE)也是生成模型,与其他深层生成模型相比,VAE 在计算上易于处理且稳定,可以通过有效的反向传播算法进行估计。 它们受到贝叶斯分析中变分推理的启发。
变分推理的概念如下:给定输入分布x
时,输出y
上的后验概率分布太复杂而无法使用。 因此,让我们用一个更简单的分布q(y)
来近似复杂的后验p(y|x)
。 在这里, q
是从最接近后验的分布族Q
中选择的。 例如,此技术用于训练潜在 Dirichlet 分配(LDA)(它们对文本进行主题建模,并且是贝叶斯生成模型)。 但是,经典变分推论的一个关键局限性是需要对似然性和先验共轭才能进行优化。 VAE 引入了使用神经网络来输出条件后验的方法(Kingma 和 Welling,2013 年),从而允许使用随机梯度下降(SGD)和反向传播来优化变分推断目标。 。 该方法称为重新参数化技巧。
给定数据集X
,VAE 可以生成与样本X
类似但不一定相等的新样本。数据集X
具有连续或离散随机变量x
的N
个独立且完全相同的样本。 假设数据是通过某种随机过程生成的,涉及一个未观察到的连续随机变量z
。 在简单自编码器的此示例中,变量z
是确定性的,并且是随机变量。 数据生成是一个两步过程:
z
的值是根据先验分布生成的,ρ[θ](z)
- 根据条件分布生成
x
的值,ρ[θ](x|z)
因此, p(x)
基本上是边缘概率,计算公式为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cxlOyV5F-1681567233327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/b2a7d0c1-ab50-49bf-8b01-9b77ea936dda.png)]
分布的参数θ
和潜变量z
都是未知的。 在此,x
可以通过从边际p(x)
取样来生成。 反向传播无法处理网络中的随机变量z
或随机层z
。 假设先验分布p(z)
为高斯分布,我们可以利用高斯分布的位置尺度属性,并将随机层重写为z =μ + σε
,其中μ
是位置参数,σ
是刻度,ε
是白噪声。 现在,我们可以获得噪声ε
的多个样本,并将它们作为确定性输入提供给神经网络。
然后,该模型成为端到端确定性深度神经网络,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TUPf55zX-1681567233327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/0cf59473-54cf-44b5-a5d3-36699ee1e65c.png)]
在这里,解码器部分与我们之前介绍的简单自编码器的情况相同。 训练此网络的损失函数如何? 因为这是一个概率模型,所以最直接的方法是通过边际p(x)
的最大似然来推导损失函数。 但是,该函数在计算上变得难以处理。 这样,我们将变分推理技术应用于下限L
。 导出边际似然,然后通过最大化下限L
导出损失函数。 可以在 Kingma 及其合作者的论文《自编码变分贝叶斯》(ICLR,2014 年)。 VAE 已成功应用于各个领域。 例如,文本的深层语义哈希是由 VAE 完成的,其中将文本文档转换为二进制代码。 同样,相似的文档具有相似的二进制地址。 这样,这些代码可用于更快,更有效的检索,以及文档的聚类和分类。
生成对抗网络
自从 Ian Goodfellow 及其合著者在 2014 年 NIPS 论文中首次引入以来,生成对抗网络(GAN)就广受青睐。 现在我们看到了 GAN 在各个领域的应用。 Insilico Medicine 的研究人员提出了一种使用 GAN 进行人工药物发现的方法。 他们还发现了在图像处理和视频处理问题中的应用,例如图像样式转换和深度卷积生成对抗网络(DCGAN)。
顾名思义,这是使用神经网络的另一种生成模型。 GAN 具有两个主要组成部分:生成器神经网络和判别器神经网络。 生成器网络采用随机噪声输入,并尝试生成数据样本。 判别器网络将生成的数据与真实数据进行比较,并使用 S 型输出激活来解决生成的数据是否为伪造的二分类问题。 生成器和判别器都在不断竞争,并试图互相愚弄-这就是 GAN 也被称为对抗网络的原因。 这种竞争驱使两个网络都提高其权重,直到判别器开始输出 0.5 的概率为止。 也就是说,直到生成器开始生成真实图像为止。 通过反向传播同时训练两个网络。 这是 GAN 的高级结构图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C7ROWZhx-1681567233327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/e1a9d83e-820d-491b-8427-d1068af52a1e.png)]
训练这些网络的损失函数可以定义如下。 令p(data)
为数据的概率分布,p(g)
为生成器分布。 D(x)
表示x
来自p(data)
而非来自p(g)
的概率。 对D
进行了训练,以使将正确标签分配给G
的训练示例和样本的概率最大化。 同时,训练G
以最小化log(1 - D(G(z)))*
。 因此,D
和G
玩一个具有值函数V(D, G)
的两人 minimax 游戏:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DbCGm8iH-1681567233327)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/dc4229cc-0d2e-44a0-99a8-b6792459c1d2.png)]
可以证明,对于p(g) = p(data)
来说,这种极小极大游戏具有全局最优性。
以下是通过反向传播训练 GAN 以获得所需结果的算法:
for N epochs do: #update discriminator net first for k steps do: Sample minibatch of m noise samples {z(1), , . . . , z (m)} from noise prior pg(z). Sample minibatch of m examples {x(1), . . . , x(m)} from data generating distribution pdata(x). Update the discriminator by: end for Sample minibatch of m noise samples {z(1) , . . . , z (m)} from noise prior pg(z). Update the generator by descending its stochastic gradient: end for
使用 GAN 架构的文本到图像合成
让我们看看使用 GAN 从文本描述生成图像。 下图显示了这种 GAN 的完整架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aluSR7qU-1681567233328)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/bdfbe2ec-0f06-47ee-b805-057f3369231b.png)]
这是条件 GAN 的一种。 生成器网络获取带有噪声向量的输入文本以生成图像。 生成的图像以输入文本为条件。 使用嵌入层φ(t)
将图像描述转换为密集向量。 使用完全连接的层对其进行压缩,然后将其与噪声向量连接。 检测器网络是 CNN,并且生成器网络的架构使用具有与 CNN 网络中使用的过滤器相同的过滤器的反卷积层。 反卷积基本上是转置的卷积,我们将在后面讨论。
CNN
CNN 是专门设计用于识别形状图案的多层神经网络,这些形状图案对于二维图像数据的平移,缩放和旋转具有高度不变性。 这些网络需要以监督的方式进行训练。 通常,提供一组标记的对象类(例如 MNIST 或 ImageNet)作为训练集。 任何 CNN 模型的关键都在于卷积层和子采样/合并层。 因此,让我们详细了解在这些层中执行的操作。
卷积运算符
CNN 背后的中心思想是卷积的数学运算,这是一种特殊的线性运算。 它广泛用于物理,统计,计算机视觉以及图像和信号处理等各个领域。 为了理解这一点,让我们从一个例子开始。 嘈杂的激光传感器正在跟踪飞船的位置。 为了更好地估计飞船的位置,我们可以取几个读数的平均值,对最近的观测结果给予更多的权重。 令x(t)
代表时间位置,t
,令w(t)
为加权函数。
该职位的估计可以写成:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jA2WYaMo-1681567233328)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/482af651-725c-47b7-916b-3e2347490314.png)]
这里,权重函数w(t)
被称为卷积的内核。 我们可以使用卷积计算位置传感器数据的简单移动平均值(SMA)。 令m
为 SMA 的窗口大小。
内核定义为:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KIAc3Zhl-1681567233328)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/3ea03e05-e414-414b-a22f-a33b8cb39f64.png)]
这是使用卷积的 SMA 的 NumPy 实现:
x = [1, 2, 3, 4, 5, 6, 7] m = 3 #moving average window size sma = np.convolve(x, np.ones((m,))/m, mode='valid') #Outputs #array([ 2., 3., 4., 5., 6.])
在深度学习中,输入通常是多维数据数组,而内核通常是由训练算法学习的参数多维数组。 尽管我们在卷积公式中具有无限求和,但对于实际实现而言,权重函数的值仅在值的有限子集时才为非零(如 SMA 的情况)。 因此,公式中的求和变为有限求和。 卷积可应用于多个轴。 如果我们有一个二维图像I
和一个二维平滑核K
,则卷积图像的计算方式如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OcCC1TKG-1681567233329)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/f1df58da-ec48-4fda-828a-1979a036e221.png)]
或者,也可以如下计算:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCDUYLNK-1681567233329)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/3401841c-2937-4b3b-9e6a-d565df408d9e.png)]
下图说明了如何使用大小为 2 且步幅为 1 的内核来计算卷积层输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QS8BoYAI-1681567233329)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/11fdb71c-0ba2-48d1-a1ba-a28381d1a907.png)]
卷积中的跨步和填充模式
卷积内核通过一次移动一列/行来围绕输入体积进行卷积。 滤波器移位的量称为跨度。 在前面的场景中,将跨度隐式设置为 1。如果将内核跨度移动 2(两列或两行),则输出单元的数量将减少:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fDBKDNyI-1681567233329)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/a65a1d73-ae70-45c8-b643-0b27aa9fe394.png)]
卷积运算符减小了输入的大小。 如果要保留输入的大小,则需要在输入周围均匀填充零。 对于二维图像,这意味着在图像的四个侧面周围添加零像素的边框。 边框的粗细(即添加的像素行数)取决于所应用的内核大小。 任何卷积运算符实现通常都采用指定填充类型的模式参数。 有两个这样的参数:
SAME
:指定输出大小与输入大小相同。 这要求过滤器窗口滑到输入图的外部,因此需要填充。VALID
:指定过滤器窗口停留在输入图内的有效位置,因此输出大小缩小filter_size
减一。 没有填充发生。
在前面的一维卷积码中,我们将模式设置为VALID
,因此没有填充发生。 您可以尝试使用相同的填充。
卷积层
卷积层包括三个主要阶段,每个阶段在多层网络上都构成一些结构约束:
- 特征提取:每个单元都从上一层的本地接受域建立连接,从而迫使网络提取本地特征。 如果我们有一个
32 x 32
的图像,并且接收区域的大小为4 x 4
,则一个隐藏层将连接到先前层中的 16 个单元,而我们总共将拥有28 x 28
个隐藏单元。 因此,输入层与隐藏层建立了28 x 28 x 16
的连接,这是这两层之间的参数数(每个连接的权重)。 如果它是一个完全连接的密集隐藏层,则将有32 x 32 x 28 x 28
个参数。 因此,在这种架构约束下,我们大大减少了参数数量。 现在,此局部线性激活的输出通过非线性激活函数(例如 ReLU)运行。 该阶段有时称为检测器阶段。 一旦学习了特征检测器,只要保留其相对于其他特征的位置,该特征在看不见的图像中的确切位置就不重要了。 与隐藏神经元的感受野相关的突触权重是卷积的核心。 - 特征映射:特征检测器创建平面(绿色平面如下所示)形式的特征图。 为了提取不同类型的局部特征并具有更丰富的数据表示,并行执行多个卷积以产生多个特征图,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eeFR4FXo-1681567233330)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/51b9fe99-1a68-45a1-87b6-3c24c4ce603c.png)]
- 通过合并进行二次采样:这是由计算层完成的,该计算层通过用附近单元的摘要统计替换某些位置的特征检测器单元来对特征检测器的输出进行二次采样。 摘要统计信息可以是最大值或平均值。 此操作降低了将特征图输出到简单失真(例如线性移位和旋转)的敏感性。 池引入不变性:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ek86gr5B-1681567233330)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/3cf0fe3d-bbc6-41cb-ac42-589a9a9d8c53.png)]
将这三个阶段结合在一起,就可以为我们提供 CNN 中的一个复杂层,这三个阶段中的每个本身就是简单层:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fNMOC0rb-1681567233330)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/b6ac6afe-c059-42a3-89cb-dbd4f5e81844.png)]
可以通过将并排堆叠在一起的方式,将合并后的特征图按一个体积进行排列,如下所示。 然后,我们可以再次对此应用下一个卷积级别。 现在,单个特征图中隐藏单元的接受场将是神经单元的体积,如下图所示。 但是,将在整个深度上使用同一组二维权重。 深度尺寸通常由通道组成。 如果我们有 RGB 输入图像,那么我们的输入本身将具有三个通道。 但是,卷积是二维应用的,并且所有通道之间的权重相同:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TO2kxZFH-1681567233331)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/handson-tl-py/img/d6e194c3-df63-489c-94bd-527a19d1783f.png)]
Python 迁移学习实用指南:1~5(4)https://developer.aliyun.com/article/1426849