深度学习笔记(三)梯度下降法进行学习&MNIST介绍

使用梯度下降法进行学习

MNIST介绍

现在我们有了神经⽹络的设计,它怎样可以学习识别数字呢?我们需要的第⼀样东西是⼀个
⽤来学习的数据集——称为训练数据集。我们将使⽤ MNIST dataset 数据集,其包含有数以万计的连带
着正确分类器的⼿写数字的扫描图像。MNIST 的名字来源于 NIST ——美国国家标准与技术研究
所——收集的两个数据集改进后的⼦集。这是取⾃ MNIST 的⼀些图像
a
MNIST 数据分为两个部分。第⼀部分包含 60,000 幅⽤于训练数据的图像。这些图像扫描⾃250 ⼈的⼿写样本,他们中⼀半⼈是美国⼈⼝普查局的员⼯,⼀半⼈是⾼校学⽣。这些图像是28 × 28 ⼤⼩的灰度图像。第⼆部分是 10,000 幅⽤于测试数据的图像,同样是 28 × 28 的灰度图像。我们将⽤这些测试数据来评估我们的神经⽹络学会识别数字有多好。为了让其有好的的测试表现,测试数据取⾃和原始训练数据不同的另外⼀组 250 ⼈(尽管仍然分别是美国⼈⼝普查局和⾼校学⽣)。这有助于确保我们的系统能识别那些没有看到训练数据的⼈写的数.

我们将⽤符号 x 来表⽰⼀个训练输⼊。为了⽅便,把每个训练输⼊ x 看作⼀个 28 × 28 = 784
维的向量。每个向量中的项⽬代表图像中单个像素的灰度值。我们⽤ y = y(x) 表⽰对应的期
望输出,这⾥ y 是⼀个 10 维的向量。例如,如果有⼀个特定的画成 6 的训练图像,x,那么
y ( x ) = ( 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 ) T y(x) = (0, 0, 0, 0, 0, 0, 1, 0, 0, 0)^T y(x)=(0,0,0,0,0,0,1,0,0,0)T则是⽹络的期望输出。注意这⾥ T 是转置操作,把⼀个⾏向量
转换成⼀个列向量.

cost function 代价函数

我们需要用一种算法来求得weights 和 bias,来使得网络的输出Y(x)能拟合所有的训练输入x.
为了实现这个目标,我们定义cost functions
aa
∥ v ∥ \| v \| v指向量v的模.
Here, w denotes the collection of all weights in the network, b all the biases, n is the total number of training inputs, a is the vector of outputs from the network when x is input, and the sum is over all training inputs, x.Of course, the output a depends on x, w and b, but to keep the notation simple I haven’t explicitly indicated this dependence.

我们称C为二次代价函数(quadratic cost function);it’s also sometimes known as the mean squared error or just MSE(均方误差或MSE).观察C,我们可以发现其是非负的,此外,精确地说,当对于所有的训练输⼊ x,y(x) 接近于输出 a 时,其值相当小,及C(w,b)≈0.

因此,只要找到合适的bias和weight,使得C(w,b)≈0,即可让其很好的工作.相反,当 C(w, b) 很⼤时就不怎么好了,那意味着对于⼤量地输⼊,y(x) 与输出 a 相差很⼤。因此我们的训练算法的⽬的,是最⼩化权重和偏置的代价函数 C(w, b)。 In other words, we want to find a set of weights and biases which make the cost as small as possible.

而为了实现cost function的最小化,我们就需要用到 gradient descent (梯度下降)这一算法

Gradient descent 梯度下降法

为什么要通过quadratic cost function 来进行选取最优解而不直接对bias和weights求最优解呢?因为weights和bias在神经网络系统中不是一个光滑的函数,大多数时候改变bias和weights不会影响output的改变,因此通过计算weights和bias的改变量来获得更好的结果是十分困难的.而用光滑的quadratic cost function则会很容易衡量.也很容易监视我们的accuracy.

当然,cost function也不止一种,我们先用这种较为容易理解的方式来做.

好的,现在回归到我们的最小化cost function上来.

OKey,好了,假设我们要最⼩化某些函数,C(v)。它可以是任意的多元实值函数,v = v1, v2, . . .。注意我们⽤ v 代替了 w 和 b 以强调它可能是任意的函数——我们现在先不局限于神经⽹络的环境。为了最⼩化 C(v),想象 C 是⼀个只有两个变量 v1 和 v2 的函数:如图
如上图所示,我们可以肉眼观测出最小值大致在哪里,但是对于多变量则很难观测到.

⼀种解决这个问题的⽅式是⽤微积分来解析最⼩值。我们可以计算导数去寻找 C 的极值点。
运⽓好的话,C 是⼀个只有⼀个或少数⼏个变量的函数。但是变量过多的话那就是噩梦。⽽且
神经⽹络中我们经常需要⼤量的变量——最⼤的神经⽹络有依赖数亿权重和偏置的代价函数,极
其复杂。⽤微积分来计算最⼩值已经不可⾏了。

好吧,微积分是不能⽤了。幸运的是,有⼀个漂亮的推导法暗⽰有⼀种算法能得到很好的效
果。⾸先把我们的函数想象成⼀个⼭⾕。只要瞄⼀眼上⾯的绘图就不难理解。我们想象有⼀个
⼩球从⼭⾕的斜坡滚落下来。我们的⽇常经验告诉我们这个球最终会滚到⾕底。也许我们可以
⽤这⼀想法来找到函数的最⼩值?我们会为⼀个(假想的)球体随机选择⼀个起始位置,然后
模拟球体滚落到⾕底的运动。我们可以通过计算 C 的导数(或者⼆阶导数)来简单模拟——这
些导数会告诉我们⼭⾕中局部“形状”的⼀切,由此知道我们的球将怎样滚动。

为了更精确地描述这个问题,让我们思考⼀下,当我们在 v1 和 v2 ⽅向分别将球体移动⼀个
很⼩的量,即 ∆v1 和 ∆v2 时,球体将会发⽣什么情况。微积分告诉我们 C 将会有如下变化
a
我们要寻找⼀种选择 ∆v1 和 ∆v2 的⽅法使得 ∆C 为负;即,我们选择它们是为了让球体滚
落。为了弄明⽩如何选择,需要定义 ∆v 为 v 变化的向量, Δ v ≡ ( Δ v 1 , Δ v 2 ) T \Delta v \equiv (\Delta v_1, \Delta v_2)^T Δv(Δv1,Δv2)T
We’ll also define the gradient of C to be the vector of partial derivatives, ( ∂ C ∂ v 1 , ∂ C ∂ v 2 ) T \left(\frac{\partial C}{\partial v_1}, \frac{\partial C}{\partial v_2}\right)^T (v1C,v2C)T,。我们⽤ ∇C 来表⽰梯度向量(gradient vector),及可得 ∇ C ≡ ( ∂ C ∂ v 1 , ∂ C ∂ v 2 ) T . \nabla C \equiv \left( \frac{\partial C}{\partial v_1}, \frac{\partial C}{\partial v_2} \right)^T. C(v1C,v2C)T.
我们⻢上会⽤ ∆v 和梯度 ∇C 来重写 ∆C 的变化。
有了这些定义,∆C 的表达式 (7) 可以被重写为
.
这个表达式解释了为什么 ∇C 被称为梯度向量:∇C 把 v 的变化关联为 C 的变化,正如我们
期望的⽤梯度来表⽰。但是这个⽅程真正让我们兴奋的是它让我们看到了如何选取 ∆v 才能让
∆C 为负数。假设我们选取:.
η \eta η是一个微小的正数,known as the learning rate.则可得到 Δ C ≈ − η ∇ C ⋅ ∇ C = − η ∥ ∇ C ∥ 2 \Delta C \approx -\eta \nabla C \cdot \nabla C = -\eta \|\nabla C\|^2 ΔCηCC=ηC2及可得 Δ C ≤ 0 \Delta C \leq 0 ΔC0,及C会永远的下降.!因此我们
把⽅程 (10) ⽤于定义球体在梯度下降算法下的“运动定律”。也就是说,我们⽤⽅程 (10) 计算∆v,来移动球体的位置 v:.

Then we’ll use this update rule again, to make another move. If we keep doing this, over and over, we’ll keep decreasing C until - we hope - we reach a global minimum.
总结⼀下,梯度下降算法⼯作的⽅式就是重复计算梯度 ∇C,然后沿着相反的⽅向移动,沿着⼭⾕“滚落”。我们可以想象它像这样
1
为了使梯度下降能够正确地运⾏,我们需要选择⾜够⼩的学习速率 η 使得⽅程 (9) 能得到很
好的近似。如果不这样,我们会以 ∆C > 0 结束,这显然不好。同时,我们也不想 η 太⼩,因为
这会使 ∆v 的变化极⼩,梯度下降算法就会运⾏得⾮常缓慢。在真正的实现中,η 通常是变化的,
以⾄⽅程 (9) 能保持很好的近似度,但算法⼜不会太慢。我们后⾯会看这是如何⼯作的。

若C有多个变量例如有m个 variables, v1,…,vm,则 Δ v = ( Δ v 1 , … , Δ v m ) T \Delta v = (\Delta v_1, \ldots, \Delta v_m)^T Δv=(Δv1,,Δvm)T,梯度 ▽C变为: ∇ C ≡ ( ∂ C ∂ v 1 , … , ∂ C ∂ v m ) T . \nabla C \equiv \left(\frac{\partial C}{\partial v_1}, \ldots, \frac{\partial C}{\partial v_m}\right)^T. C(v1C,,vmC)T.


z
仍然令z ,及确保△C为负,球运动的位置变化. 及可重复运用该规则,实现△C始终为负..
You can think of this update rule as defining the gradient descent algorithm.

gradient descent 应用到数字识别中来

那么回到我们的代价函数,.
.

补充

具体的我的更多有关deeplearning的文章在我的机器学习专栏内,有兴趣可以详细浏览机器学习专栏.


qiqi

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是使用梯度下降法和牛顿法实现MNIST数据集的训练及分类的 Python 代码: 首先,我们需要加载 MNIST 数据集,可以使用 `tensorflow` 的 `keras` 库来加载数据集: ```python import tensorflow as tf from tensorflow import keras (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() # 归一化 x_train, x_test = x_train / 255.0, x_test / 255.0 ``` 接下来,我们可以使用梯度下降法实现 MNIST 数据集的训练及分类: ```python import numpy as np # 将样本矩阵转换为向量 def flatten(X): m = X.shape[0] return X.reshape(m, -1) def init(X, y): m, n = X.shape X = np.hstack((np.ones((m, 1)), X)) y = y.reshape(-1, 1) theta = np.zeros((n+1, 1)) return X, y, theta # 计算sigmoid函数 def sigmoid(z): return 1 / (1 + np.exp(-z)) # 损失函数 def cost(theta, X, y): m = len(y) h = sigmoid(X @ theta) J = -1/m * (y.T @ np.log(h) + (1-y).T @ np.log(1-h)) return J # 梯度下降法 def gradient(theta, X, y): m = len(y) h = sigmoid(X @ theta) grad = 1/m * X.T @ (h - y) return grad def gradient_descent(X, y, theta, alpha, num_iters): J_history = np.zeros((num_iters, 1)) for i in range(num_iters): grad = gradient(theta, X, y) theta -= alpha * grad J_history[i] = cost(theta, X, y) return J_history, theta # 初始化 X_train_flatten = flatten(x_train) X_test_flatten = flatten(x_test) X_train, Y_train, theta = init(X_train_flatten, y_train) # 梯度下降训练 alpha = 0.1 num_iters = 1000 J_history, theta = gradient_descent(X_train, Y_train, theta, alpha, num_iters) # 预测 X_test, Y_test, _ = init(X_test_flatten, y_test) y_pred = np.round(sigmoid(X_test @ theta)) accuracy = np.mean(y_pred == Y_test) * 100 print("Accuracy:", accuracy) ``` 接下来,我们可以使用牛顿法实现 MNIST 数据集的训练及分类: ```python # 计算sigmoid函数 def sigmoid(z): return 1 / (1 + np.exp(-z)) # 损失函数 def cost(theta, X, y): m = len(y) h = sigmoid(X @ theta) J = -1/m * (y.T @ np.log(h) + (1-y).T @ np.log(1-h)) return J # 梯度 def gradient(theta, X, y): m = len(y) h = sigmoid(X @ theta) grad = 1/m * X.T @ (h - y) return grad # Hessian矩阵 def hessian(theta, X): m = X.shape[0] h = sigmoid(X @ theta) H = 1/m * (X.T @ np.diag(h.ravel()) @ np.diag((1-h).ravel()) @ X) return H # 牛顿法 def newton(theta, X, y): J_history = [] for i in range(10): grad = gradient(theta, X, y) H = hessian(theta, X) theta -= np.linalg.inv(H) @ grad J_history.append(cost(theta, X, y)) return J_history, theta # 初始化 X_train_flatten = flatten(x_train) X_test_flatten = flatten(x_test) X_train, Y_train, theta = init(X_train_flatten, y_train) # 牛顿法训练 J_history, theta = newton(theta, X_train, Y_train) # 预测 X_test, Y_test, _ = init(X_test_flatten, y_test) y_pred = np.round(sigmoid(X_test @ theta)) accuracy = np.mean(y_pred == Y_test) * 100 print("Accuracy:", accuracy) ``` 以上就是使用梯度下降法和牛顿法实现MNIST数据集的训练及分类的 Python 代码。需要注意的是,这里我们只是简单地使用了逻辑回归模型对 MNIST 数据集进行分类,在实际应用可能需要更加复杂的模型和算法来提高分类准确率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值