浅尝AI大模型基础(一):初识神经网络
Nbc Lv3

浅尝 AI 大模型基础(一):初识神经网络

写这篇文章主要还是为了能获得更多的记忆。作为主要做安全方向的,想学ai安全,但在学习过程中我发现,通过搜索找到的很多文章要么比较零散,要么过于专业,很难找到既有整体思路又适合入门理解的内容。后来偶然看到博主飞天闪客的相关视频,讲解思路非常清晰,所以就一边视频一边搜文章。但视频学习容易遗忘,于是决定把学习过程整理成文字,一方面作为自己的学习记录,另一方面也希望能给同样想了解这部分内容的人提供一点参考。

万物皆函数

image-20260315163148474

Function Described the world

学习以下内容之前,要有一个思想就是万物皆函数,一切事务都可以用函数来描述。

就是先输入->经过f(x)->输出

比如,你现在看这些字是一个函数,听到的声音也是

image-20260315165738214

F = ma也是

输入两个直角三角形的变成得到第三边边长也是。通过符号化来解释现实世界

image-20260315165953260

从函数到神经网络

早起的人工智能是符号主义思想,但是这种思想的限制太大,总会有事务是我们想不到用什么函数来表示。所以就想到了另一个思路,也是人类的特长之一,猜,靠猜得到一个近似解也不错

比如一些点在坐标系中的是这样的

image-20260315171220616

我们不好直接求出这个函数是什么但是我们可以猜出这个函数差不多是怎么样的

比如这样

image-20260315171306825

比如这个函数是y = wx + b,我们一直调整w和b,直到这条直线差不多了,就点到为止了,只要最接近结果就可以了。

这是现代人工智能的思路,也就是联结主义。

在找不到精确函数的结果下,找一个从结果上看大差不差的函数,连蒙带猜逐渐逼近真实答案。

但是刚才输入的点是靠猜直线就可以了,比较简单。但如果是一些复杂的点,比如这样

image-20260315171950232

那我们就没办法用线性方程来表示了,需要用非线性方程来表示。

将线性函数f(x) = wx + b转化为非线性函数,只需要套一个非线性函数就可以了,比如平方、正弦函数、指数函数。:

image-20260315172229222

也就是f(x) = g(wx+b)

像这样多个输入,激活函数外面加一次线性变换,再套一个激活函数,并且还可以不断嵌套。通过这样的方式,我们可以构造出非常复杂的关系,理论上可以逼近任意的连续函数。

但这样看起来太复杂了,所以我们引入神经元的概念,多个神经元互相连接形成的网状结构就叫做神经网络

比如先是一层最基本的输入和输出

image-20260315173003631

可能有多个输入并且,不断进行线性变换套激活函数,就像这样

image-20260315173900723

可以看到每套一层,神经元就向水平方向扩展一个,扩展之后,中间这一层就不是最终输出了,包裹在了一个很复杂的函数变换之中看不到,叫做隐藏层

这一整个就叫神经网络

image-20260315174157726

一些基础知识可以了解一下:

  1. 设计一个神经网络时,输入层与输出层的节点数往往是固定的,中间层则可以自由指定;
  2. 神经网络结构图中的拓扑与箭头代表着预测过程时数据的流向,跟训练时的数据流有一定的区别;
  3. 结构图里的关键不是圆圈(代表“神经元”),而是连接线(代表“神经元”之间的连接)。每个连接线对应一个不同的权重(其值称为权值),这是需要训练得到的。

权重的训练

损失函数

刚才我们知道,猜出一个最合适的函数就可以很好的拟合真实数据了。那以线性方程f(x)=wx+b为例,什么样的w和b才能让这个线性方程为好的呢。

最直观的例子

image-20260315180629638

这样就是拟合的比较好

image-20260315180723215

这样肯定是拟合的不好了。

如何用数学语言来描述我们直觉上的理解呢。

我们可以将我们预测的数据y和真实数据y做差并取绝对值,即为|y-y|。将所有的差值加起来平方并取均值来消除样本数量大小的影响得到的公式为均方误差

Loos=1Ni=1N(yiy^i)2Loos=\frac{1}{N}\sum_{i=1}^{N}(y_i-\hat{y}_i)^2

在机器学习中也是损失函数的一种

image-20260315182317674

现在我们也就可以懂神经网络的训练了。训练的目的,就是使得参数尽可能的与真实的模型逼近,也就是误差最小的方向,即损失函数最小。

线性回归

现在的问题就是如何优化参数,能够让损失函数的值最小。一个最常用的方法就是高中数学中学到的知识,求导

我们来推导一下求导

我们先假设是线性方程y=wx,那损失函数就是

L(w)=1Ni=1N(yiwxi)2L(w)=\frac{1}{N}\sum_{i=1}^{N}(y_i-wx_i)^2

平方展开

L(w)=1Ni=1N(yi22yiwxi+w2xi2)L(w)=\frac{1}{N}\sum_{i=1}^{N}(y_i^2-2y_iwx_i+w^2x_i^2)

求和展开

L(w)=1N(i=1Nyi22wi=1Nyixi+w2i=1Nxi2)L(w)=\frac{1}{N} \left( \sum_{i=1}^{N}y_i^2 - 2w\sum_{i=1}^{N}y_ix_i + w^2\sum_{i=1}^{N}x_i^2 \right)

对w求导

dL(w)dw=1N(02i=1Nyixi+2wi=1Nxi2)\frac{dL(w)}{dw} = \frac{1}{N} \left( 0 - 2\sum_{i=1}^{N}y_ix_i + 2w\sum_{i=1}^{N}x_i^2 \right)

化简

dL(w)dw=2N(wi=1Nxi2i=1Nyixi)\frac{dL(w)}{dw} = \frac{2}{N} \left( w\sum_{i=1}^{N}x_i^2 - \sum_{i=1}^{N}y_ix_i \right)

那令L(w)最小也就是当导数为0的时候,即

dL(w)dw=0\frac{dL(w)}{dw}=0

那很明显

L(w)=1N(i=1Nyi22wi=1Nyixi+w2i=1Nxi2)L(w)=\frac{1}{N} \left( \sum_{i=1}^{N}y_i^2 - 2w\sum_{i=1}^{N}y_ix_i + w^2\sum_{i=1}^{N}x_i^2 \right)

是一个二元一次方程,是一个抛物线即为求抛物线的最低点,刚刚采用的办法是令导数=0

看起来挺简单的,但是别忘了,我们刚才限制的是非常简单的函数,就是一条过零点的直线。当加上b的时候,那损失函数就从一个二维的抛物线变成一个三维函数了。

当为多元函数的时候,就是求偏导数了,可以现象为一个切面。

image-20260315185047880

通过寻找一种线性函数来拟合x和y的关系,就是机器学习中最基本的一种分析法:线性回归

梯度下降

但是神经网络通常都是非常复杂的非线性函数,它的损失函数也一般非常复杂,那么此时我们用什么办法可以解决这个麻烦呢?

采用的方法就是梯度下降。

简单来说也是"猜",假设我们现在函数为y=wx+b,那么损失函数为

L(w,b)=1Ni=1N(yiy^i)2L(w,b)=\frac{1}{N}\sum_{i=1}^{N}(y_i-\hat{y}_i)^2

当w=5,b=5。那L(5,5)=10

我们尝试把w增加一个单位

那么就是L(6,5)=9。这说明我们这次调整方向是对的。

L(6,6)=11 说明b会让损失函数增大,L(6,3)=7。

就这样不断调整w和b(所有参数)使得损失函数不断减小。而损失函数L随着参数w变化而变化的程度,其实就是损失函数对w的偏导数。而我们要做的,就是让w和b不断地向偏导数地反方向去变化。具体变化的快慢,我们再增加一个系数(学习率)来控制。这些偏导数所构成的向量就叫做梯度。不断变化w和b使得损失函数不断减小,进而求出最后的w和b,这个过程就叫做梯度下降

梯度下降算法每次计算参数在当前的梯度,然后让参数向着梯度的反方向前进一段距离,不断重复,直到梯度接近零时截止。一般这个时候,所有的参数恰好达到使损失函数达到一个最低值的状态。

链式法则和反向传播

那现在问题就在怎么求偏导数了,从偏导数的实际意义入手

image-20260316161922012对于这样一个简单的神经元来说,求偏导就是想看看,w变化一点L会变化多少了。

image-20260316162105222

拿w1举例,想看w1变化一点L会变化多少,就可以先看w1变化一点a变化多少。然后a变化一点,y会变化多少。再看y变化一点L会变化多少。这个过程每一个都是一个简单的偏导数。把这三者乘起来就知道w1变化一点L会变化多少了

Lw1=Ly^y^aaw1\frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial a} \cdot \frac{\partial a}{\partial w_1}

可以想象一下齿轮

image-20260316163602000

我们想知道第一个齿轮转一圈最后一个齿轮转几圈的时候,就是把他们乘起来。这个也是一样。

这种偏导数的计算方式就是链式法则。也就是微积分中的复合函数求导。

而由于我们可以从右向左计算这些偏导数,然后调整每一层的参数,计算前一层的时候用到的偏导数的值,后面也会用到(更左边的层),所以可以让这些值从右向左传播,这个过程就叫做反向传播。反向传播算法是利用了神经网络的结构进行的计算。不一次计算所有参数的梯度,而是从后往前。首先计算输出层的梯度,然后是第二个参数矩阵的梯度,接着是中间层的梯度,再然后是第一个参数矩阵的梯度,最后是输入层的梯度。计算结束以后,所要的两个参数矩阵的梯度就都有了。

小结

其实我学到这里的时候,也是感觉具体看哪点可以懂。但是又不是很有自己的理解,也就是容易忘。所有我打算小结一下到这里的自己对权重训练的理解。

损失函数就不用说了,就是体现预测值与真实值之间的误差了。关键就是在于这个损失函数的计算。当我们想让一个函数的值最小,通常都是想到求导,线性函数也还好,但是在神经网络中通常都是非常复杂的非线性函数,也就是直接求导会很困难。所以我们想到了一个算法,梯度下降算法,这个算法可以说是靠"猜"(沿着梯度的反方向迭代搜索最小值)来降解求导的复杂性,我们通过一点一点调整各个参数的值,来看参数对于损失函数的影响,再向影响损失函数相反的方向调整参数。其中,会有系数来控制参数变化的大小,这个系数就叫学习率。参数的变化对函数的影响其实就是求参数的偏导。所有参数的偏导数构成的向量就叫梯度。当梯度趋近于 0 时,说明损失函数在该点附近已经基本不再下降,此时参数通常接近最优解。

现在的问题转化为求梯度了,也可以说求偏导数。以看第一个参数w1的变化会对损失函数L的影响为例,直接算Lw1\frac{\partial L}{\partial w_1}会非常麻烦。由于L并不直接依赖w1,而是通过w1→a→y^→L逐层影响的,所以如果拆成Ly^y^aaw1\frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial a} \cdot \frac{\partial a}{\partial w_1},那么每一步都是简单的函数求导。这个求导过程就是链式法则

或许到这里,光看文字和函数,有些很久没有接触数学的师傅会困惑,那为什么要反向。所以拆分一下细节举一些具体的例子:

给出一个最简单的神经网络

1
x → a → ŷ → L

a=w1xa = w_1 x

y^=w2a\hat{y} = w_2 a

L=(yy^)2L = (y - \hat{y})^2

为了直观,不要激活函数,不要 b

给出参数

1
2
3
4
5
x = 2
y = 10

w1 = 3
w2 = 4

现在计算出L

1
x=2 ───▶ a=6 ───▶ y^ =24 ───▶ L=196

也就是正向传播,算出结果

然后现在我们想知道w1变化一点,L会改变多少,也就是算参数的梯度。就是求Lw1\frac{\partial L}{\partial w_1} ,但是L不是直接依赖w1,而是w1 → a → ŷ → L。所以要从后往前计算也就是Ly^\frac{\partial L}{\partial \hat{y}}

带入

1
2
求导 2(y^−y)
带入 2(24-10) = 28

也就是y^增加1 L增加28

按照这种依次得到,a 增加 1 y^增加 4,w1增加1 a增加2

最后乘起来得到 w1增加1 L增加224。

到这可以发现我们倒着算的时候,前一步算的,往左方向继续算,前一个的值可以用上,也就是每一层的梯度可以复用。那如果要是正向算呢?

先算aw1\frac{\partial a}{\partial w1} 但是L 不直接依赖 a,又不知道a 变化 L 会变化多少,所以要算Ly^\frac{\partial L}{\partial \hat{y}} 因为知道L。发现还是要算Ly^\frac{\partial L}{\partial \hat{y}}

这样一对比就知道,反向传播的算法可以避免重复计算梯度,也就可以减少很多计算量了。

通过这个例子可以发现,当我们从后往前计算梯度时,每一层计算得到的梯度都可以被前一层继续复用。如果尝试从前往后计算,由于损失函数L并不直接依赖中间变量a,就无法直接得到a对 L 的影响,最终仍然需要回到Ly^\frac{\partial L}{\partial \hat{y}}的计算。因此从前往后计算会产生大量重复计算。反向传播算法正是利用链式法则,从损失函数开始逐层向前传播梯度,从而高效地计算出每个参数的梯度。

一些调教神经网络的方法

从上面的内容看,如果一个神经网络足够大,那岂不是什么问题都可以解决。理想很丰满,现实很骨感,如果真是这样,那现在的大模型也没那么多迭代了。

过拟合

所谓过拟合,就是模型太复杂了,在学习数据时把噪声和随机波动也学会了,这样对新数据的预测能力甚至不如简单的线性模型。

image-20260316183804241

比如这两张图,似乎右边拟合的更好,但好像有点好的太过了。导致结果可能只适合训练数据,对于新数据的预测甚至不如左边。

image-20260316183703985

像这种在见过的数据上表现的太过完美,但是在没见过的数据上的表现(泛化能力)又很糟糕的,就叫过拟合

但是模型最终是要部署到没有见过训练数据的真实场景的,所以我们想要的是不仅要求数据在训练集上求得一个较小的误差,在测试集上也要表现好。

那该怎么办呢?

降低模型复杂度

模型越复杂,参数越多,越容易过拟合训练数据。那我们就可以减少神经网络层数、减少每层神经元数量、选择更简单的模型结构等方法来降低模型的复杂度。

比如我们用一个非常复杂的神经网络训练,有时候甚至不如线性模型好

image-20260316185015138

​ 简单来说,就是让模型“不要太聪明”,避免它把训练数据记得过于细致。

增加训练数据

从本质上来说,过拟合往往是因为数据量不足,而模型又过于复杂。当模型参数很多,但训练数据有限时,模型就很容易“记住”每一个样本。

因此,增加训练数据量是最直接有效的方式。数据越多,模型就越难去记住每一个样本的细节,而更容易学习到真正的规律。

在实际项目中,如果无法获取更多真实数据,也可以通过 数据增强(Data Augmentation) 的方式扩充数据,例如:

  • 图像旋转、裁剪、翻转

  • 添加噪声

  • 改变亮度或对比度

这些方法都可以在一定程度上得到更多数据,还可以让模型的鲁棒性更强,提高模型的泛化能力。

正则化

神经网络的训练通过调整参数来让模型逼近真实数据,如果模型在向着过拟合的方向发展,那我们停止训练就好了,这样也能一定程度上避免过拟合。但显然,这种寸止挑战还是太粗糙了O.0

更精致的方法就是在原来的损失函数的基础上加上被调整参数本身,这样当参数调整让损失函数减小的幅度甚至不如参数本身增大的幅度,新的损失函数就是增大的,这次调整显然就是不合适的。即L1正则化

L=L0+λwL = L_0 + \lambda \sum |w|

除了加上参数本身之外,我们还可以加上参数的平方和,这样在参数大的时候,抑制的效果就更强了。即L2正则化

LL2=L0+λwi2L_{L2} = L_0 + \lambda \sum w_i^2

我们加上的这一项就叫做惩罚项。把通过向损失函数中添加权重惩罚项来抑制参数野蛮增长的方法叫做正则化。惩罚项的力度则由正则化系数λ来控制。这些控制参数的参数叫做超参数。那为啥叫L1、L2正则化,因为绝对值之和叫L1范数,平方和的平方根叫L2范数

Dropout

这种方法就非常简单了,就是丢弃。为了避免模型过于依赖某些参数,我们在每次训练时都随即丢弃掉一部分参数就好了。

举个例子,现在Nbc和4个朋友进行CSGO游戏,Nbc的段位为S,其他4个人的段位都是B或A。由于有Nbc的绝对实力主导,会让S局的对手误以为Nbc方都是S哥。但是一但遇到特殊情况,比如Nbc不在其他四人四排,这时再遇到S局对手,就会败北。这就是过度依赖某一个参数的表现。

解决办法就是在训练过程中随机“关闭”一部分神经元。例如,在某一次训练中,随机让 30% 的神经元不参与计算。这样可以防止神经元之间形成过强的依赖关系。从直观上理解,Dropout 相当于在训练过程中同时训练了许多个不同的子网络,从而提高模型的泛化能力。

其他

过拟合的问题解决了,就万事大吉,可以获得一个很好的神经网络了吗?并不是,其实还有很多其他问题,简单提一下

问题 原因 解决方法
梯度消失 神经网络越来越深,梯度反向传播时越来越小,参数更新困难 用残差网络来防止深层网络的梯度衰减
梯度爆炸 梯度数值越来越大,参数的调整幅度失去控制 用梯度裁剪来防止梯度的更新过大
收敛速度慢 可能陷入局部最优或者来回震荡 用动量法、RMSProp、Adam等自适应优化器来加速收敛,减少震荡
计算开销大 数据规模太大,完整的前向传播和反向传播都耗费巨大 用 mini-batch 把巨量数据分割成小批次,来降低单次计算开销

从这些简单的了解,其实可以思考出一些道理:当我们试图“调教”神经网络时,很容易把注意力集中在各种技巧上:学习率如何设置、优化器如何选择、正则化是否合适。但如果从更宏观的角度来看,训练神经网络其实是一种在复杂系统中寻找稳定结构的过程。我们不断通过梯度、损失函数和数据分布去调整参数,让一个原本随机初始化的模型逐渐形成某种能够表达世界规律的结构。在这个过程中,人类并没有直接告诉模型“答案”,而是通过规则和反馈,让模型在巨大的参数空间中自己逐渐靠近一个合理的解。这种方式某种程度上也反映了学习本身的本质:无论是机器还是人类,理解世界都不是一蹴而就的,而是在不断试错和修正中逐渐逼近真相。

或许从这个角度来看,训练神经网络不仅仅是一项工程任务,它更像是一种对“学习如何发生”的模拟。我们调节参数、设计结构、观察收敛,而模型则在无数次微小的更新中逐渐形成能力。在这些看似机械的计算背后,其实隐藏着一种非常朴素的思想:复杂的智能,往往来自于无数简单规则的持续迭代。

这个系列打算我自己学到哪就记录到哪

参考文献

https://space.bilibili.com/325864133?spm_id_from=333.788.upinfo.head.click

https://www.cnblogs.com/subconscious/p/5058741.html

https://www.cnblogs.com/subconscious/p/4107357.html

https://www.youtube.com/@HungyiLeeNTU

https://deeplizard.com/learn/playlist/PLZbbT5o_s2xq7LwI2y8_QtvuXZedL6tQU

由 Hexo 驱动 & 主题 Keep
访客数 访问量