深度学习-1.神经网络理解

发布于:2025-06-10 ⋅ 阅读:(16) ⋅ 点赞:(0)

0. 前言

        机器学习中的算法挺难,数学要求挺高。深度学习其实没有那么难,而且目前应用场景广,方便,其中之一的原因就是他更简单。

        机器学习任务中,经常要“我觉得什么重要”,很主观,问题就在于“你觉得”对的东西,不一定对,“你觉得”重要的数据,不一定重要。

        那么深度学习就是让这个主观的思考交给了计算机,让它自己去决定。

1. 神经网络基础

图像分类

以图像分类任务举个例子:

        图像分类其实就是计算机把我们人类认识的东西,转换成计算机认识的特征。所以“怎么把特征提取的很好”就是很关键的一点了。

(一只猫.jpg)

        在人类眼中是个猫,但是在计算机中就是一个矩阵,是一堆数值。一张图片被表示成三维数组的形式,每个像素的值从0-255。例如一张彩色图片,300*100*3,其中300是长,100是宽,3就是RGB,是颜色通道。

线性函数:

y = kx + b

在我们的图像分类任务中,谁是已知条件,谁是要求解的?

        图像数据已知,标签也是已知的,也就是x,y都已知;要求的就是k和b,在以后的任务中,来了新的x,就会产生正确的y。

那么怎么去求这个权重w(k)呢?

        假如输入的图片包含 32*32*3 = 3072 个像素点,把他们写成一个列向量 3072*1。

        我们要求预测结果,需要权重参数w,我们的输入包含了3072个特征,权重需要一对一的服务特征,所以需要3072个权重,这就是一组权重参数,也就是一个行向量 1*3072,从y=wx+b 可以看出,w*x 在这种情况下就是一个值。

        在一个十分类(图片是猫?狗?青蛙?)任务中,我们最终得到的不是回归任务中预测的一个值,分类任务中得到的应该是这个图片属于各个类别的概率是多少。

        在我们上面的叙述中,一组权重和一组特征,得到的是一个值,十分类就需要扩展到10组权重(10*3072的矩阵),数据的特征还是3072,我们就可以得到10个结果。

        所以我们的权重是矩阵类型的。

那么偏置呢?偏置难道就是一个数字吗?我们今天这个任务中,这个偏置应该是多少个数呢?

        偏置是对结果进行微调,所以需要对每个结果进行微调,也就是10个数,偏置永远和输出挂钩。

什么叫神经网络呢?

        将很多个线性模型组合到一起。

权重是怎么去得到的呢?

        他们一开始是做一个随机的初始化,有正有负、有大有小,这个东西之后一定会进行更新,那怎么进行更新就是我们的重点。

        这就涉及到了损失和权重的关系,我们一定有一个最好的权重,能够让损失最小。预测值和真实值差距就是损失,也就是说,预测值和真实值差距越小,权重越好。

        权重是肯定有一个最优解的,需要想办法解出这个最优解,但是基本做不到,我们只能尝试着去逼近这个最优解。从一开始的随机值,它可以有很多种方向去更新,不应该是盲目的去猜所有的方向,应该沿着正确的方向去猜,那么就沿着损失降低的方向去猜可以吗?

        我们不只沿着正确的方向去猜,我们应该沿着最优的方向去猜,这就引出了梯度下降。

        要更新这个随机的权重,就好比在山顶下山,每一步都沿着最陡的方向下山,就可以最快的下到最底部。沿着这个方向走一步,重新计算最陡的方向,再走一步......

        我们要更新的次数是非常多的,每次是走很大一步,还是走很小一步呢?这个就是接下来要考虑的方向了。人生地不熟,先认识下大小王,我们的模型也是如此,所以我们希望每步迈的小一点,小步最多就是慢,而大步就不好说了。现在算力、时间都不是特别重要的问题。

        梯度下降说白了就是用来求最优的参数的,而实际上的梯度方向,是向上的,不是向下的,我们是沿着梯度的反方向做更新,所以会有负号。

这个权重参数矩阵这么多数,我们是一起更新呢?还是单独更新呢?

        我们现在的参数不多,如果我们有几百万,上千万个参数,GPT-3 有1750亿个参数,能够同时计算吗?那显然不可能,我们只能分别对每个权重参数更新。

损失是什么?其实就是错误的程度,损失这个东西要怎么算出来呢?

        分类任务的损失是怎么算的呢?

        当我们对一张图片算出了它的得分,这个分有啥用呢?我们应该是要一个概率值,怎么  把这个数值转换成概率呢?计算出来的得分值,差异往往并不大,我们要让模型学出各类图片的差异,所以我们就需要放大这种差异。乘个10这种线性的放大,不够劲,需要来个指数级别的放大。最后我们需要使用归一化来得到一个概率,比如 0.13 是怎么得到的:24.5/24.5+164+0.18 = 0.13。

        如果我们输入的是一只猫的图片,我们当然希望模型预测猫的概率是1,也就是说损失为0。在数学上,有一个东西叫对数,他在x=1时,y为0,正好符合我们目前的这种情况。x就是概率,而y就是损失。

        log是单调函数,也就是说x越小,y越小。当x逼近0,y就趋于负无穷大。而且我们发现在0-1的概率区间,y恒为负,我们希望损失是一个正数,损失越大?越小?加个负号。

        这就是Softmax分类器。

什么叫前向传播?前向传播有什么用?

        我们现在由输入数据到产生结果,这个就叫前向传播。但是计算出损失不是我们的最终目标,我们的最终目标应该是总结经验,在这个损失下,怎么去进行更新权重参数。

        所以整个神经网络由两部分构成:

1. 第一部分就叫做前向传播:试一试当前的权重参数咋样,是骡子是马拉出来溜溜。看看损失多少
2. 第二部分就叫反向传播:你这组权重效果不好,那我给你纠正一下。

所以现在叫深度学习,而以前叫bp(反向传播)。

学习率需要衰减吗?

        学习率(步长):对结果影响巨大,一般小一些。

        刚开始大一点,快到最优解时,向小的整学习率。这种是比较科学的。

        除了衰减,还有其他的要做吗?---warmup,模型在开始啥都不会,一开始热热身,达到一个初始的比较合适的学习率,再去慢慢衰减。一般热身占的比例很少,不会经过很多次数,后续的慢慢衰减是一个比较漫长的过程。

批处理的大小什么意思?他有什么用?

        算损失时,是按一个样本去算呢?还是一堆样本去做呢?理论上越多越好(batch大好一点),但是实际上由于硬件限制,没法搞那么大。

什么叫反向传播?

        有了损失之后,把损失(Loss)对每一个中间变量或参数的影响,用链式法则一层层“往回传”,算出它们各自该往哪个方向“微调”才能让最终的损失变小。

        先算出它对最靠近输出的变量 z 的偏导,再求上一层y的,最后算到损失对输入的偏导​。

        对某个参数 w ,如果 ∂L/∂w>0,说明在当前点,把 w 增大会让损失 L 变大;反方向(减小 w)会让损失变小。

        如果 ∂L/∂w<0,则把 w 减小会让损失变大,增大 w 才能让损失下降。

2. 神经网络

整体架构

        透过数据发掘出本质,第一个隐藏层就是从输入层中提取特征,第二个隐藏层就是从第一个隐藏层中再提取特征......

        刚开始就只能学一些皮毛,慢慢加多隐藏层,越学越深,学到的特征越精华。 

        这么说,隐藏层难道越多越好吗?实则不然,原因有两个:一个是代码的大小,一个就是“过拟合”。

        理论上神经元数量越多,模型越能学到深层特征,更能解决问题。但是我们的数据集中往往存在离群点,异常点,如果模型太过较真,就会为了某一个离群点,而导致过分的学到了数据中的特征,这就是过拟合。

激活函数

激活函数是什么,用来做什么的?

        激活函数是神经网络中每一层“线性”变换后的非线性映射,用来给网络引入非线性能力。单纯的线性函数能力十分有限。

        如果没有激活函数,所有层都是线性的,任意多层的叠加都等价于一个线性变换,无法拟合复杂的非线性关系。激活函数的导数 σ′(u) 会参与反向传播,用于调整前面层的参数。

        对于一个神经元,首先会做一个线性计算,然后把这个线性结果 u 输入到一个非线性函数 σ(u),输出就是该神经元的激活值:a=σ(u).

        当年神经网络停滞不前就是Sigmoid影响的,当u很大或很小时,这个函数的切线斜率逼近于0,也就是梯度为0,而我们前面提到的反向传播链式求导是相乘的,如果有损失对某个中间参数的梯度为0,这时候最终损失对输入的梯度直接成0了,也就不会更新了。

        现在用什么的都有,比较经典的就是Relu=max(0,x),输入值u小于0的都不要,这个合理吗?其实也合理,在 ReLU 里,你只保留“确信度”足够高的那一侧(正数),把“不确定”或“否定”区域都当成 0,不让它们往后面传——让模型专注在有用的、正向的信息上。

过拟合怎么解决呢?

        可以降低神经元的数量

数据预处理

        

一开始这个数据歪歪的,不对称,不太好看,我们最好能让数据存在某种有规律的分布。

第二个图,虽然对称了,但是现在的数据不是在同一个维度,需要标准化到同一个维度。

参数初始化

参数初始化同样非常重要,通常这个初始化的权重最好小一点,如果大了训练时会“跳来跳去”甚至发散。

DROP-OUT

        神经元越多,负担越大,每次训练都随机杀死一部分,减少训练负担