ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

人工智能基础:神经网络从单个神经元到BP、CNN、RNN、GNN

人工智能基础:神经网络从单个神经元到BP、CNN、RNN、GNN 很多人第一次碰人工智能基础都是被“神经网络”这四个字挡在门外的——一上来就是矩阵乘法、链式求导、梯度下降公式还没看懂人已经困了。但只要把神经网络拆成几个能摸得着的零件你会发现它本质上就是一套“不断试错、自动修正”的拟合工具。这篇是人工智能基础系列的第六篇专门聊神经网络初步认识我会从最基础的单个神经元讲起一路讲到前馈神经网络、BP反向传播再横向对比CNN卷积神经网络、RNN循环神经网络、图神经网络这些常见结构最后带大家用Python手写一个能拟合曲线的BP网络。不管你是准备做人工智能大作业的学生还是刚想系统入门人工智能的开发者或者只是想搞明白“图像处理为啥用CNN不用前馈神经网络”的爱好者这篇都能给你一条清晰的路径。我不打算堆概念只讲每个设计背后的“为什么”以及我自己踩过的那些坑。1. 神经网络到底是什么从一个“猜数字”游戏说起神经网络这个词听着高级其实它的出发点非常朴素模仿生物神经元的信号传递方式用一堆简单的计算单元拼出一个能学习的系统。生物智能、计算智能和我们现在说的人工智能三者之间是一种很微妙的层次关系——生物智能是自然界进化出来的计算智能是我们用数学和算法去逼近的手段而人工智能是最终想达到的目标。这也就是常说的ABC层次先有生物原型再有计算工具最后谈智能表现。很多人一上来就盯着“智能”两个字反而忽略了中间那层“计算”结果学得云里雾里。1.1 神经元就是一个加权投票器一个神经元做的事情用生活里的场景解释最清楚假设你要评一道菜好不好吃找了5个评委来打分。但每个评委的权重不一样专业美食评论家权重高路人甲权重低。最后把每个人的分数乘以各自的权重加起来再减去一个及格线超过就判“好吃”没超过就判“不好吃”。这就是一个神经元。用数学写出来就是先算加权和z w1*x1 w2*x2 ... wn*xn b再经过一个激活函数a f(z)得到输出。这里的w就是权重代表每个输入有多重要b是偏置相当于那条及格线f是激活函数负责做最后那个“是否超过”的判断。我见过太多新手卡在偏置上觉得它是可有可无的小尾巴其实偏置非常关键——如果没有它所有的判断线都必须穿过原点模型的表达能力会被砍掉一大截。提示权重决定“输入往哪个方向影响结果、影响多大”偏置决定“整体门槛往哪挪”。两者缺一不可调参时它们的量级往往也不一样。1.2 从单个神经元到网络为什么非要“分层”单个神经元只能解决线性可分的问题。什么叫线性可分就是在平面上画一条直线就能把两类点分开。但现实里的问题大多不是这样。最经典的例子是异或问题XOR同样两个输入0和0输出00和1输出11和0输出11和1输出0。你无论怎么画一条直线都没法把这四组数据分对。这个问题当年直接让第一代感知机陷入了低谷。解决办法就是“加层”。把多个神经元并排放在一起构成一个隐藏层再让隐藏层的输出接到下一层。这样网络就可以先在第一层学会一些简单的中间特征再在第二层把这些特征组合起来表达出非线性的判断边界。这背后的逻辑其实和人类理解图像是一样的最底层看的是边缘和线条中间层看的是形状和纹理高层才看得到整张脸。每多一层抽象能力就强一分。这就是“深度”神经网络的由来也是为什么现在动不动就是几十层、上百层的模型。2. 拆解前馈神经网络的核心零件前馈神经网络Feedforward Neural Network是最基础的一类结构也叫多层感知机MLP。它的特点只有一个数据从输入层进去经过若干隐藏层最后从输出层出来全程单向流动没有回路。别看它简单理解了它CNN、RNN你都能找到熟悉的影子。所以学神经网络前馈网络是绕不过去的第一关。2.1 输入层、隐藏层、输出层分别管什么输入层的维度等于你喂给模型的特征数量。比如你要预测房价特征有面积、房龄、楼层、距离地铁站的距离那就是4维输入。输入层不做任何计算它只是把数据接进来这一点很多人第一次会误解以为输入层也是个“计算层”。隐藏层是真正干活的地方。它的层数和每层的宽度神经元个数决定了模型的容量。层数多、宽度大模型能表达更复杂的函数但也更容易过拟合、更难训练。隐藏层的数量没有标准答案一般先用1到2层试水除非你确定任务很复杂。输出层则取决于任务类型。回归任务比如预测一个具体数值通常输出1个神经元不加激活二分类任务输出1个用sigmoid压到0到1之间表示概率多分类任务输出类别数个用softmax归一化成概率分布。这张表我建议新手直接记住任务类型输出层神经元数输出层激活函数损失函数回归1无线性MSE二分类1sigmoid二元交叉熵多分类类别数softmax交叉熵2.2 权重、偏置和激活函数的三角关系这三个东西是整个网络的灵魂我单独拎出来讲清楚。权重是网络要学的主要参数它决定了每个连接的重要程度偏置是每个神经元自带的调节量让判断边界可以整体平移激活函数负责引入非线性是网络能拟合复杂曲线的根本原因。这里有个特别容易被忽略的点如果你把激活函数去掉哪怕堆一百层整个网络等价于一层线性变换。因为线性变换的复合还是线性变换W2(W1*x) (W2*W1)*x白搭。所以激活函数不是“锦上添花”而是深度网络存在的意义所在。参数量也要会算面试和调参都用得上。假设一个网络输入层10维隐藏层20个神经元输出层3个神经元。第一层参数是10*20 20 220第二层是20*3 3 63总共283个参数。每层都别忘了加偏置那部分很多新手算参数量时只算权重结果对不上号。2.3 常见激活函数怎么选别乱用激活函数有好几种随便用会出问题我按使用频率和场景给你理一遍Sigmoid输出范围0到1看着像概率。但它有个致命缺点输入很大或很小时梯度几乎为0也就是“饱和”导致深层网络梯度消失训练不动。现在基本只在二分类输出层用。Tanh输出范围-1到1均值为0比sigmoid好一点但饱和问题还在深层网络依然不推荐。ReLUmax(0, x)计算极快正区间梯度恒为1能有效缓解梯度消失。隐藏层的默认首选。缺点是负区间梯度为0神经元可能“死亡”一旦输入长期为负就再也不更新了。Leaky ReLU给负区间留一个小斜率解决神经元死亡问题ReLU效果不好时可以换它试试。Softmax专门用在多分类输出层把一堆实数变成加起来为1的概率分布。注意隐藏层优先用ReLU别用sigmoid。我早期做的一个手写数字分类隐藏层用了sigmoid训练几十轮损失几乎不动换成ReLU后几轮就收敛了。这个坑非常典型。3. 训练是怎么发生的前向传播与反向传播网络搭好了参数是随机初始化的一开始预测得乱七八糟。训练的过程就是让网络通过数据不断调整这些参数直到预测越来越准。这一整套流程分两步走前向传播负责算预测值反向传播负责算梯度、改参数。理解了这两步你才算真正入门了神经网络。3.1 前向传播数据在网络里走一遍前向传播就是从输入开始一层一层往前算直到得到输出。每一层做的都是同一件事先算线性组合z W*a_prev b再套激活函数a f(z)然后把a传给下一层。矩阵化的写法让整批数据可以一起算这也是为什么GPU对神经网络这么重要——矩阵乘法正是GPU的强项。举个具体的小例子。输入x [1, 2]第一层权重矩阵W1 [[0.5, -0.3], [0.2, 0.8]]偏置b1 [0.1, -0.1]。那么第一个隐藏神经元的z 0.5*1 (-0.3)*2 0.1 0经过ReLU还是0第二个神经元的z 0.2*1 0.8*2 - 0.1 1.7经过ReLU是1.7。这就是前向传播的一个片段手算一遍你会对“数据在网络里流动”有非常直观的感觉。3.2 损失函数网络怎么知道自己错了网络算出了预测值但怎么知道它错得离谱还是错了一点点靠损失函数。它把预测值和真实值之间的差距量化成一个数字这个数字就是网络要努力变小的目标。回归任务常用均方误差MSE就是把每个样本的预测值和真实值相减、平方、再平均。平方是为了让正负误差都变成正数同时放大大误差的惩罚。分类任务则用交叉熵。为什么分类不用MSE因为当预测概率和真实标签差很远时交叉熵的梯度依然很大能快速把参数拉回来而MSE在这个区间梯度很小学得慢。这也是我踩过的一个坑早期做分类任务用MSE模型收敛奇慢换成交叉熵后立刻顺畅。记住这个对应关系能少走很多弯路。3.3 反向传播与梯度下降参数到底怎么被修正反向传播的核心就一个词链式法则。损失函数对某个参数的梯度等于损失对输出的梯度乘以输出对中间层的梯度再乘以中间层对这个参数的梯度一层层往回乘。听起来绕但本质就是“这个参数每变动一点点最终损失会变多少”。算出梯度后用梯度下降更新参数w w - 学习率 * 梯度。梯度指向损失上升最快的方向所以我们往反方向走损失就会下降。学习率是这里最关键的超参数太大步子迈大了容易震荡甚至发散太小收敛慢得像蜗牛。经验值一般从0.01或0.001开始试。为了让它更聪明现在普遍用Adam这类自适应优化器它能给不同参数自动调整步长新手直接上Adam通常不会错。3.4 手写一个能跑的BP网络光看公式容易飘动手写一遍最扎实。下面用numpy实现一个拟合正弦曲线的BP网络隐藏层用ReLU输出层线性损失用MSE一看就懂import numpy as np # 构造数据拟合 y sin(x) np.random.seed(42) x np.linspace(-np.pi, np.pi, 200).reshape(-1, 1) y np.sin(x) # 网络结构1 - 16 - 16 - 1 def relu(z): return np.maximum(0, z) def relu_grad(z): return (z 0).astype(float) W1 np.random.randn(1, 16) * 0.5 b1 np.zeros((1, 16)) W2 np.random.randn(16, 16) * 0.5 b2 np.zeros((1, 16)) W3 np.random.randn(16, 1) * 0.5 b3 np.zeros((1, 1)) lr 0.01 for epoch in range(5000): # 前向传播 z1 x W1 b1 a1 relu(z1) z2 a1 W2 b2 a2 relu(z2) y_pred a2 W3 b3 # 损失 loss np.mean((y_pred - y) ** 2) # 反向传播 d_loss 2 * (y_pred - y) / len(x) dW3 a2.T d_loss db3 d_loss.sum(axis0, keepdimsTrue) da2 d_loss W3.T dz2 da2 * relu_grad(z2) dW2 a1.T dz2 db2 dz2.sum(axis0, keepdimsTrue) da1 dz2 W2.T dz1 da1 * relu_grad(z1) dW1 x.T dz1 db1 dz1.sum(axis0, keepdimsTrue) # 参数更新 W1 - lr * dW1; b1 - lr * db1 W2 - lr * dW2; b2 - lr * db2 W3 - lr * dW3; b3 - lr * db3 if epoch % 1000 0: print(fepoch {epoch}, loss {loss:.5f})跑下来你会发现loss从零点几一路降到接近0模型能把正弦曲线拟合得挺像。如果把隐藏层换成sigmoid或者把学习率调到1.0你会亲眼看到训练变慢或者直接发散。这种亲手“制造bug”的实验比看十篇文章都管用。4. 主流网络家族横向对比CNN、RNN、GNN各管什么到这里你已经掌握了前馈神经网络和BP的完整逻辑。但现实里的任务五花八门图像、文本、关系网络各有各的结构所以才衍生出了不同的网络家族。这一节帮你建立一张全局地图知道什么任务该用什么网络。4.1 CNN卷积神经网络为什么图像不用前馈网络很多人问图像处理为啥不用前馈神经网络答案就俩字太多。一张224×224的彩色图展平后是15万维输入如果接一个1000神经元的隐藏层光这一层就有1.5亿个参数根本训不动还容易过拟合。CNN的解法很聪明用局部感受野加权值共享。一个卷积核比如3×3在整个图上滑动每个位置都用同一组权重这样参数从1.5亿直接降到几十个。它的三个核心思想你要记住局部性相邻像素关系更近、权值共享同一个特征在全图通用、平移不变性猫在左上角还是右下角都是猫。卷积负责提取特征池化负责降维压缩最后接几层全连接做分类。图像、视频、甚至一些文本任务都能用CNN。4.2 RNN循环神经网络处理有先后顺序的数据语言、语音、股票走势这类数据前后是有顺序关系的前馈网络和CNN都不擅长。RNN的做法是给网络加一条“记忆通路”每一步的输出不仅取决于当前输入还取决于上一步的隐藏状态。就好像你读一句话理解当前词的意思时脑子里还记着前面读过的词。但RNN有个硬伤——梯度消失。时间步一长梯度往回传的时候会不断衰减模型记不住太久远的信息。后来就有了LSTM和GRU用“门控机制”决定哪些信息该记、哪些该忘。现在做序列任务基本没人用原始RNN了都是LSTM、GRU或者更火的Transformer。小波Elman神经网络这类结构本质也是RNN的变体用在小波变换处理过的时序信号上。4.3 图神经网络GNN处理关系型数据还有一类数据既不是网格状也不是序列而是关系网——社交网络、分子结构、推荐系统里的用户-商品图。这类数据的核心是“节点”和“边”以及它们之间的关系。图神经网络GNN的思路叫消息传递每个节点从邻居那里收集信息更新自己的表示几轮下来每个节点就聚合了整个局部结构的信息。这个方向这几年非常热很多科研课题和竞赛题都在这上面做文章。4.4 一张表看懂怎么选网络类型擅长数据核心机制典型场景前馈网络MLP表格型、固定维度特征全连接激活房价预测、简单分类CNN图像、网格数据卷积池化权值共享图像识别、目标检测RNN/LSTM序列数据隐藏状态门控文本、语音、时序预测GNN图结构数据消息传递聚合社交网络、分子性质预测提示别迷信复杂结构。我做过一个表格数据的项目先用了GNN效果还不如老老实实的MLP。选网络的黄金法则是“数据结构决定网络结构”数据是网格就用CNN是序列就用RNN是图才用GNN。5. 动手实操用BP网络拟合一条曲线理论讲完来一个完整可复现的实操。这个流程和我做人工智能大作业、参加数学建模时的思路一模一样你照着做就能跑通。5.1 数据准备与归一化数据是拟合曲线的起点。先确定目标函数比如y sin(x) 0.1*cos(3x)然后在区间上均匀采样500个点再叠加一点高斯噪声模拟真实数据。归一化这一步千万别省把输入x和输出y都缩放到[-1, 1]或[0, 1]区间。为什么因为如果输入量级是几千权重就得学得很小梯度下降会非常慢甚至发散。归一化之后网络收敛速度能快好几倍这是我最常推荐给新手的技巧。5.2 网络搭建与参数选择网络结构用1 → 32 → 32 → 1隐藏层ReLU输出层线性。为什么选32个神经元因为拟合一条单变量曲线16到64之间通常够用先取中间值试。学习率从0.01起步优化器用Adambatch size设成全部数据这里数据量小全批训练更稳。损失函数用MSE。这些参数不是拍脑袋定的而是基于“数据量小、任务简单”的判断做的保守选择。5.3 训练过程与结果观察训练时重点看损失曲线的走势。健康的训练曲线会先快速下降然后慢慢变平最后稳定在一个很小的值附近。如果损失上下剧烈震荡多半是学习率太大如果损失几乎不动可能是学习率太小、激活函数选错或者数据没归一化。我习惯每500轮打印一次损失训练完再把预测曲线和真实曲线画在一起一眼就能看出拟合得好不好。如果预测曲线过度弯曲、把噪声也学进去了那就是过拟合需要减少参数量或者加正则。5.4 调参的几点实战经验调参这件事说到底是经验和耐心的结合。我的几条心得第一先调学习率它对结果的影响最大别的参数先别动第二隐藏层宽度优先于层数很多任务加宽比加深更有效还更好训练第三Batch Normalization是救命稻草训练不稳定、收敛慢时加上它经常立竿见影第四固定随机种子不然每次结果不一样你根本分不清是调参起效了还是运气好。我早期调参就是随机乱试后来养成“每次只改一个变量、记录结果”的习惯效率高了不止一倍。6. 新手最容易踩的坑与排查清单神经网络入门阶段真正让人崩溃的不是理论而是“明明照着教程写的就是训不出来”。这一节把我这些年踩过和帮别人排查过的典型问题整理一下遇到问题可以直接对照。6.1 训练不收敛的常见原因损失一直不下降先按顺序排查这几项数据有没有归一化学习率是不是太大或太小激活函数在隐藏层用了sigmoid导致梯度消失标签有没有搞错比如类别从1开始而不是0损失函数和任务类型匹配吗回归用MSE、分类用交叉熵初始化是不是全零全零会导致所有神经元对称学不出东西我用这套清单排查过很多次八成的问题都能在前几项里找到。尤其是“全零初始化”和“损失函数不匹配”这两个新手极容易犯。6.2 过拟合和欠拟合怎么区分看训练损失和验证损失的差距。两者都很高是欠拟合——模型太简单或者训练不够解法是加层、加宽、多训几轮。训练损失低但验证损失高是过拟合——模型把训练数据背下来了解法是加Dropout、加L2正则权重衰减、减少参数量、或者补充更多数据。注意别只盯着训练损失看。我见过有人训练损失降到0.0001还很开心结果验证集一塌糊涂。永远留一部分数据做验证这是底线。6.3 问题速查表现象可能原因解决方向损失不下降学习率不当、没归一化、激活函数错误调学习率、归一化、换ReLU损失震荡发散学习率过大、batch太小降学习率、增大batch训练好验证差过拟合Dropout、正则、加数据训练验证都差欠拟合加容量、多训练神经元大量死亡ReLU负区间过多换Leaky ReLU、降学习率6.4 我个人总结的几个实用习惯分享几个让我少走弯路的小习惯。第一先用小数据跑通再上全量用几十条数据把整条流程验证一遍确认没bug再喂大数据能省下大量等待时间。第二把超参数记在本子上哪个组合对应哪个效果时间久了你会有自己的“参数直觉”。第三可视化永远比看数字有用损失曲线、预测对比图、特征分布图该画就画。第四别一开始就追最新最复杂的模型把MLP和CNN吃透你会发现大部分问题用它们就能解决剩下的再考虑Transformer这些。至于像图像滤镜、人工智能机器人这些应用背后用的也是这些基础网络结构原理都是通的。最后分享一个我自己的体会学神经网络最忌讳“只看不写”。我当年看了一堆教程自认为懂了前向反向传播结果第一次自己写代码时连梯度的维度都对不上调了大半天。后来我强迫自己每个结构都手写一遍哪怕是照着抄抄完再默写一次理解深度完全不一样。你在学习路径上如果卡住了先别急着往前冲回头把BP网络手推一遍、手写一遍很多后面的概念会突然变得顺理成章。这个过程没有捷径但走过之后你会发现那些曾经吓人的公式其实都只是把“试错”这件事写成了数学而已。
返回列表