算法工程师修仙之路:Keras(九)

本文详细介绍了深度学习的基础,包括神经网络的数学基础,特别是基于梯度的优化原理。讲解了张量运算的导数——梯度,以及随机梯度下降和链式求导的反向传播算法在训练神经网络中的应用。通过实例展示了如何在 Keras 中构建和训练模型,以及损失函数和优化器的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深度学习基础

神经网络的数学基础


神经网络的“引擎”:基于梯度的优化

  • 我们的第一个神经网络示例中,每个神经层都用下述方法对输入数据进行变换。

    output = relu(dot(W, input) + b)
    
    • 在这个表达式中,W 和 b 都是张量,均为该层的属性。
    • 它们被称为该层的权重(weight)或可训练参数(trainable parameter),分别对应 kernel 和 bias 属性。
    • 这些权重包含网络从观察训练数据中学到的信息。
    • 一开始,这些权重矩阵取较小的随机值,这一步叫作随机初始化(random initialization)。
    • 下一步则是根据反馈信号逐渐调节这些权重,这个逐渐调节的过程叫作训练,也就是机器学习中的学习。
  • 训练循环(training loop)具体过程如下:

    • 抽取训练样本 x 和对应目标 y 组成的数据批量;
    • 在 x 上运行网络[这一步叫作前向传播(forward pass)],得到预测值 y_pred;
    • 计算网络在这批数据上的损失,用于衡量 y_pred 和 y 之间的距离;
    • 更新网络的所有权重,使网络在这批数据上的损失略微下降;
    • 最终得到的网络在训练数据上的损失非常小,即预测值 y_pred 和预期目标 y 之间的距离非常小,网络“学会”将输入映射到正确的目标。
  • 考虑网络中某个权重系数,如何知道这个系数应该增大还是减小,以及变化多少:

    • 一种简单的解决方案是,保持网络中其他权重不变,只考虑某个标量系数,让其尝试不同的取值。但这种方法是非常低效的,因为对每个系数(系数很多,通常有上千个,有时甚至多达上百万个)都需要计算两次前向传播(计算代价很大)。
    • 一种更好的方法是利用网络中所有运算都是可微(differentiable)的这一事实,计算损失相对于网络系数的梯度(gradient),然后向梯度的反方向改变系数,从而使损失降低。
张量运算的导数:梯度
  • 导数完全描述了改变 x 后 f(x) 会如何变化。如果你希望减小 f(x) 的值,只需将 x 沿着导数的反方向移动一小步。

  • 梯度(gradient)是张量运算的导数,它是导数这一概念向多元函数导数的推广。多元函数是以张量作为输入的函数。

  • 假设有一个输入向量 x、一个矩阵 W、一个目标 y 和一个损失函数 loss。

    • 你可以用 W 来计算预测值 y_pred,然后计算损失,或者说预测值 y_pred 和目标 y 之间的距离:

      y_pred = dot(W, x)
      loss_value = loss(y_pred, y)
      
    • 如果输入数据 x 和 y 保持不变,那么这可以看作将 W 映射到损失值的函数:
      loss_value = f(W)

    • 假设 W 的当前值为 W 0 W_0 W0 f f f W 0 W_0 W0 点的导数是一个张量 g r a d i e n t ( f ) ( W 0 ) gradient{(f)}(W_0) gradient(f)(W0),其形状与 W 相同,每个系数 g r a d i e n t ( f ) ( W 0 ) [ i , j ] gradient(f)(W_0)[i, j] gradient(f)(W0)[i,j] 表示改变 W 0 [ i , j ] W_0[i, j] W0[i,j] 时 loss_value 变化的方向和大小。

    • 张量 g r a d i e n t ( f ) ( W 0 ) gradient(f)(W_0) gradient(f)(W0) 是函数 f ( W ) f(W) f(W) = loss_value 在 W 0 W_0 W0 的导数。

    • g r a d i e n t ( f ) ( W 0 ) gradient(f)(W_0) gradient(f)(W0) 也可以看作表示 f ( W ) f(W) f(W) W 0 W_0 W0 附近曲率(curvature)的张量。

  • 对于一个函数 f ( x ) f(x) f(x),你可以通过将 x x x 向导数的反方向移动一小步来减小 f ( x ) f(x) f(x) 的值。同样,对于张量的函数 f ( W ) f(W) f(W),你也可以通过将 W 向梯度的反方向移动来减小 f ( W ) f(W) f(W),比如 W 1 = W 0 − s t e p ∗ g r a d i e n t ( f ) ( W 0 ) W_1 = W_0 - step * gradient(f)(W_0) W1=W0stepgradient(f)(W0),其中 step 是一个很小的比例因子。也就是说,沿着曲率的反方向移动,直观上来看在曲线上的位置会更低。注意,比例因子 step 是必需的,因为 g r a d i e n t ( f ) ( W 0 ) gradient(f)(W_0) gradient(f)(W0) 只是 W 0 W_0 W0 附近曲率的近似值,不能离 W 0 W_0 W0 太远。

随机梯度下降

  • 给定一个可微函数,理论上可以用解析法找到它的最小值:函数的最小值是导数为0的点,因此你只需找到所有导数为0的点,然后计算函数在其中哪个点具有最小值。

  • 基于当前在随机数据批量上的损失,一点一点地对参数进行调节。由于处理的是一个可微函数,你可以计算出它的梯度,从而有效地更新网络的所有权重,使网络在这批数据上的损失略微下降。沿着梯度的反方向更新权重,损失每次都会变小一点。

  • 小批量随机梯度下降(mini-batch stochastic gradient descent,又称为小批量 SGD),随机(stochastic)是指每批数据都是随机抽取的:

    • 抽取训练样本 x 和对应目标 y 组成的数据批量;
    • 在 x 上运行网络,得到预测值 y_pred;
    • 计算网络在这批数据上的损失,用于衡量 y_pred 和 y 之间的距离;
    • 计算损失相对于网络参数的梯度[一次反向传播(backward pass)];
    • 将参数沿着梯度的反方向移动一点,比如 W -= step * gradient,从而使这批数据上的损失减小一点。
  • 沿着一维损失函数曲线的随机梯度下降(一个需要学习的参数):

    • 网络只有一个参数,并且只有一个训练样本。
      在这里插入图片描述
    • 直观上来看,为 step 因子选取合适的值是很重要的。如果取值太小,则沿着曲线的下降需要很多次迭代,而且可能会陷入局部极小点。如果取值太大,则更新权重值之后可能会出现在曲线上完全随机的位置。
  • 小批量 SGD 算法的一个变体是每次迭代时只抽取一个样本和目标,而不是抽取一批数据,这叫作真 SGD(有别于小批量 SGD)。还有另一种极端,每一次迭代都在所有数据上运行,这叫作批量 SGD。这样做的话,每次更新都更加准确,但计算代价也高得多。这两个极端之间的有效折中则是选择合理的批量大小。

  • SGD 还有多种变体,其区别在于计算下一次权重更新时还要考虑上一次权重更新,而不是仅仅考虑当前梯度值,比如带动量的 SGD、Adagrad、RMSProp 等变体。这些变体被称为优化方法(optimization method)或优化器(optimizer)。其中动量的概念尤其值得关注,它在许多变体中都有应用。

  • 动量解决了 SGD 的两个问题:收敛速度和局部极小点。

    • 损失作为网络参数的函数的曲线:局部极小点和全局最小点
      在这里插入图片描述

    • 在某个参数值附近,有一个局部极小点(local minimum):在这个点附近,向左移动和向右移动都会导致损失值增大。如果使用小学习率的 SGD 进行优化,那么优化过程可能会陷入局部极小点,导致无法找到全局最小点。

    • 使用动量方法可以避免这样的问题,更新参数 w 不仅要考虑当前的梯度值,还要考虑上一次的参数更新:

      past_velocity = 0.
      momentum = 0.1	# 不变的动量因子
      while loss > 0.01:		# 优化循环
      w, loss, gradient = get_current_parameters()
      velocity = past_velocity * momentum - learning_rate * gradient
      w = w + momentum * velocity - learning_rate * gradient
      past_velocity = velocity
      update_parameter(w)
      

链式求导:反向传播算法

  • 我们假设函数是可微的,因此可以明确计算其导数。在实践中,神经网络函数包含许多连接在一起的张量运算,每个运算都有简单的、已知的导数。

  • 将链式法则(chain rule)应用于神经网络梯度值的计算,得到的算法叫作反向传播(backpropagation,有时也叫反式微分,reverse-mode differentiation)。反向传播从最终损失值开始,从最顶层反向作用至最底层,利用链式法则计算每个参数对损失值的贡献大小。

  • 现在以及未来数年,人们将使用能够进行符号微分(symbolic differentiation)的现代框架来实现神经网络,比如 TensorFlow。也就是说,给定一个运算链,并且已知每个运算的导数,这些框架就可以利用链式法则来计算这个运算链的梯度函数,将网络参数值映射为梯度值。对于这样的函数,反向传播就简化为调用这个梯度函数。由于符号微分的出现,你无须手动实现反向传播算法。

回顾第一个例子


  • 下面是输入数据:

    (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
    train_images = train_images.reshape((60000, 28 * 28))
    train_images = train_images.astype('float32') / 255
    test_images = test_images.reshape((10000, 28 * 28))
    test_images = test_images.astype('float32') / 255
    
  • 输入图像保存在 float32 格式的 Numpy 张量中,形状分别为 (60000, 784)(训练数据)和 (10000, 784)(测试数据)。

  • 下面是构建网络:

    network = models.Sequential()
    network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
    network.add(layers.Dense(10, activation='softmax'))
    
  • 这个网络包含两个 Dense 层,每层都对输入数据进行一些简单的张量运算,这些运算都包含权重张量。权重张量是该层的属性,里面保存了网络所学到的知识(knowledge)。

  • 下面是网络的编译:

    network.compile(optimizer='rmsprop', loss='categorical_crossentropy', 
    				metrics=['accuracy'])
    
  • categorical_crossentropy 是损失函数,是用于学习权重张量的反馈信号,在训练阶段应使它最小化。减小损失是通过小批量随机梯度下降来实现的。梯度下降的具体方法由第一个参数给定,即 rmsprop 优化器。

  • 最后,下面是训练循环:

    network.fit(train_images, train_labels, epochs=5, batch_size=128)
    
  • 网络开始在训练数据上进行迭代(每个小批量包含128 个样本),共迭代 5 次[在所有训练数据上迭代一次叫作一个轮次(epoch)]。在每次迭代过程中,网络会计算批量损失相对于权重的梯度,并相应地更新权重。5轮之后,网络进行了2345次梯度更新(每轮469次),网络损失值将变得足够小,使得网络能够以很高的精度对手写数字进行分类。

小结


  • 学习是指找到一组模型参数,使得在给定的训练数据样本和对应目标值上的损失函数最小化。

  • 学习的过程:随机选取包含数据样本及其目标值的批量,并计算批量损失相对于网络参数的梯度。随后将网络参数沿着梯度的反方向稍稍移动(移动距离由学习率指定)。

  • 整个学习过程之所以能够实现,是因为神经网络是一系列可微分的张量运算,因此可以利用求导的链式法则来得到梯度函数,这个函数将当前参数和当前数据批量映射为一个梯度值。

  • 损失和优化器

    • 将数据输入网络之前,你需要先定义这二者。
    • 损失是在训练过程中需要最小化的量,因此,它应该能够衡量当前任务是否已成功解决。
    • 优化器是使用损失梯度更新参数的具体方式,比如 RMSProp 优化器、带动量的随机梯度下降( SGD)等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值