尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

神经网络入门:从逻辑回归到前馈网络的核心原理与实现

神经网络入门:从逻辑回归到前馈网络的核心原理与实现 1. 从“Hello World”到理解神经网络为什么它不只是数学如果你刚开始接触“吴恩达deeplearning.ai”的课程尤其是卡在第一课第一章《神经网络的基本概念》上感觉一堆术语和公式扑面而来有点懵那太正常了。我刚开始学的时候也觉得神经网络像是一个黑盒子输入数据输出结果中间发生了什么全靠猜。但后来我发现理解它的关键不在于一开始就死磕反向传播的偏导数而在于建立一个正确的“心智模型”——把它想象成一个我们每天都在用的、极其强大的模式识别工具而不是一堆冰冷的数学符号。“神经网络的基本概念”这一章本质上是在为你搭建这个心智模型的地基。它要回答的核心问题不是“公式怎么写”而是“这个东西到底在干什么以及为什么要这么干”。很多教程一上来就给你看神经元结构图、讲激活函数这就像学开车先教你发动机原理很容易让人打退堂鼓。吴恩达课程的高明之处在于它用逻辑回归这个“简化版”神经网络作为引子让你先理解最核心的“学习”过程模型如何根据错误调整自己。所以这篇笔记不会是对课程内容的简单复述而是结合我多次学习、教学和实践的经验帮你把P1-P6中那些看似分散的知识点串成一条清晰的主线。我们会暂时放下对“深度”的恐惧聚焦于“网络”是如何“神经”地工作的。你会发现理解前馈神经网络这是你热搜词里出现的也是本章的核心的关键在于搞懂三个核心构件单个神经元感知机、激活函数、以及从输入到输出的数据流动前馈过程。搞懂了这些再看卷积神经网络CNN或者图卷积神经网络GCN你就能明白它们无非是在这个基本框架上针对图像、图结构数据做了特定的“神经元”连接方式优化。2. 核心构件拆解神经元、激活函数与“前馈”的本质很多教材喜欢一上来就画一个圆圈代表神经元然后画一堆箭头。我们换个方式从一个实际的场景开始你要训练一个模型根据房屋面积一个特征来预测房价。这就是最最简单的神经网络可能处理的问题。2.1 单个神经元一个加权决策器把这个预测模型想象成一个神经元。它接收一个输入房屋面积x然后输出一个预测值房价ŷ。它内部做了两件事加权求和给输入x乘以一个权重w再加上一个偏置b。即z w*x b。你可以把w理解为“每平米单价”b理解为“基础费用”比如税费、杂费。这个z是一个线性计算的结果。非线性激活如果直接输出z那我们的模型就只是一个线性回归能力非常有限。现实中房价和面积不是严格的直线关系比如超过一定面积后单价可能变化。因此我们需要一个“激活函数”来引入非线性。这里对于回归问题我们有时可以直接用线性输出但为了概念统一我们引入一个最简单的非线性函数Sigmoid。它会把z映射到0到1之间。公式是a σ(z) 1 / (1 e^{-z})。这个a就是神经元的最终输出。所以一个神经元的工作就是输入x → 计算z w*x b → 激活a σ(z) → 输出a。为什么需要偏置b你可以把它理解为模型的“灵活性”。如果只有w*x那么当x0时输出永远是0。偏置b允许模型拟合的直线或超平面可以不经过原点大大增加了模型的表达能力。2.2 激活函数引入非线性的“灵魂”没有激活函数的神经网络无论堆多少层最终都可以等效为一个线性模型。这就失去了“深度”学习的意义。激活函数决定了神经元的“兴奋”模式。Sigmoid (σ)如上所述将输入压缩到(0,1)。在课程早期用于引入概念非常直观因为它输出可以理解为概率。但它在深度网络中有两个大问题1) 两端饱和区梯度接近于0容易导致梯度消失训练停滞2) 输出不是零均值的会影响后续层的梯度优化效率。所以在现代深度网络中它很少用在隐藏层。Tanh类似Sigmoid但输出范围是(-1, 1)是零均值的收敛通常比Sigmoid快。但它仍有梯度饱和问题。ReLU (Rectified Linear Unit)这是目前最常用的激活函数公式为f(z) max(0, z)。它的优点是在正区间梯度恒为1彻底解决了梯度消失问题在正区间计算速度极快。它的缺点是“Dead ReLU”问题如果输入恒为负梯度为0神经元可能永久“死亡”。不过有Leaky ReLU、PReLU等变体来缓解。在第一章吴恩达主要用Sigmoid来建立概念因为它的数学形式优美求导简单σ‘ σ*(1-σ)。但你要心里有数工业界早就是ReLU的天下了。理解Sigmoid是为了理解“非线性变换”这个概念本身。2.3 前馈过程数据如何“流”过网络现在我们把多个神经元连接起来。一个最简单的前馈神经网络也叫多层感知机MLP包含输入层、隐藏层至少一层、输出层。“前馈”指的是数据单向流动从输入层开始一层一层地计算直到输出层没有循环或反馈。这个过程就是一次前向传播。举个例子假设我们用两个特征面积x1卧室数量x2预测房价。网络结构是输入层2个节点 - 隐藏层3个神经元 - 输出层1个神经元。输入层只是接收数据[x1, x2]不做计算。隐藏层计算第一个隐藏神经元z1 w11*x1 w12*x2 b1然后a1 σ(z1)第二个隐藏神经元z2 w21*x1 w22*x2 b2然后a2 σ(z2)第三个隐藏神经元z3 w31*x1 w32*x2 b3然后a3 σ(z3)这里w11, w12, w21, ...就是连接输入和隐藏层的权重。我们可以用矩阵形式优雅地表示Z[1] W[1] * X b[1],A[1] σ(Z[1])。其中W[1]是一个3x2的矩阵X是2x1的向量b[1]是3x1的向量。输出层计算将隐藏层的输出A[1]作为输入进行类似计算z[2] W[2] * A[1] b[2],a[2] σ(z[2])。这里的a[2]就是最终的预测值ŷ。这个过程就是一次完整的前向传播。你可以看到信息从原始输入X经过层层加权求和与非线性变换最终得到预测输出。网络的“深度”就体现在隐藏层的层数上而“宽度”体现在每一层神经元的数量上。注意这里为了简化所有层都用了Sigmoid。实际中输出层根据任务不同会选择不同的激活函数如回归问题用线性二分类用Sigmoid多分类用Softmax隐藏层则多用ReLU。3. 从逻辑回归看神经网络的“学习”本质第一章花了很大篇幅讲逻辑回归这绝非偶然。逻辑回归可以看作是一个没有隐藏层的神经网络只有输入层和输出层。通过剖析它我们能最清晰地看到神经网络学习的核心机制损失函数与梯度下降。3.1 损失函数衡量“错”得有多离谱模型做出了预测ŷ但真实值是y。我们需要一个量化的标准来衡量这次预测的“损失”或“错误”。对于二分类逻辑回归最常用的损失函数是交叉熵损失。对于单个样本L(ŷ, y) -[y*log(ŷ) (1-y)*log(1-ŷ)]这个公式设计得很巧妙当真实标签y1时损失变为-log(ŷ)。如果模型预测ŷ越接近1正确log(ŷ)越接近0损失越小如果ŷ越接近0错误log(ŷ)会趋向负无穷-log(ŷ)趋向正无穷损失巨大。当y0时同理。它严厉地惩罚了“ confidently wrong”的预测比如真实是0你却预测0.9。对于整个训练集我们计算所有样本损失的平均值称为成本函数J (1/m) * Σ L(ŷ^(i), y^(i))。训练神经网络的目标就是找到一组参数W, b使得成本函数J最小。3.2 梯度下降如何“调整”参数知道了“错”的程度J下一步就是知道“如何改”。梯度下降提供了方向。梯度Gradient就是成本函数J对每个参数如w, b的偏导数。它指向了J增长最快的方向。那么反方向负梯度就是J下降最快的方向。参数更新公式w w - α * (∂J/∂w)。其中α是学习率一个超参数控制每次更新的步长。这个过程可以想象成你在山上找最低点最小化J。你环顾四周计算梯度找到当前最陡的下山方向然后迈一小步学习率α。重复这个过程你最终会走到一个山谷局部最低点。在神经网络中我们需要计算J对每一层每一个参数的梯度。这就是著名的反向传播算法。它的核心思想是链式法则从输出层的损失开始层层反向将误差“分配”给前面每一层的每一个参数计算出各自的梯度。在第一章吴恩达通过逻辑回归详细推导了dw和db的计算这其实就是反向传播在最简单网络中的应用。理解了这个以后再看到复杂的多层网络反向传播你就知道它只是这个基本过程的重复和叠加。实操心得初学者常犯的一个错误是只关注前向传播的公式而忽略了反向传播的直观理解。一定要亲手推导一遍逻辑回归的梯度公式dw X*(ŷ-y).T / m,db np.sum(ŷ-y) / m。这个简单的形式蕴含着反向传播的精髓梯度等于输入乘以误差。在深层网络中这个“误差”会通过链式法则层层传递。4. 向量化为什么能“瞬间”完成计算当你从单个样本的逻辑回归扩展到整个训练集时如果不做特殊处理你需要写一个for循环来遍历所有样本进行计算。这在数据量巨大时是灾难性的慢。向量化是深度学习得以实现的技术基石。4.1 从循环到矩阵运算假设我们有m个样本每个样本有n_x个特征。在逻辑回归中非向量化需要循环for i in range(m): z_i w.T * X[:, i] b ...向量化Z np.dot(w.T, X) b。这里X是一个(n_x, m)的矩阵每一列是一个样本。w.T是(1, n_x)b通过广播机制自动加到每一列结果上。这个np.dot矩阵乘法操作在底层是由高度优化的线性代数库如BLAS完成的它利用了CPU或GPU的并行计算能力速度比Python的for循环快成百上千倍。4.2 深度网络中的向量化对于前面提到的双层网络向量化形式更加清晰前向传播Z[1] np.dot(W[1], X) b[1]A[1] σ(Z[1])Z[2] np.dot(W[2], A[1]) b[2]A[2] σ(Z[2])反向传播dZ[2] A[2] - Y(这里Y是真实标签矩阵形状(1, m))dW[2] (1/m) * np.dot(dZ[2], A[1].T)db[2] (1/m) * np.sum(dZ[2], axis1, keepdimsTrue)dZ[1] np.dot(W[2].T, dZ[2]) * σ‘(Z[1])(这里*是元素乘)dW[1] (1/m) * np.dot(dZ[1], X.T)db[1] (1/m) * np.sum(dZ[1], axis1, keepdimsTrue)注意看dW的计算公式np.dot(dZ[l], A[l-1].T)。这完美印证了之前说的“梯度等于误差乘以输入”只不过现在是矩阵形式同时计算了所有样本的梯度总和。为什么keepdimsTrue很重要在计算db时np.sum(dZ, axis1)会把一个形状为(n_l, m)的矩阵压缩成一个形状为(n_l,)的一维数组。后续在与b形状(n_l, 1)做减法更新时可能会因形状不匹配而出错或导致难以察觉的广播错误。keepdimsTrue会保持维度为(n_l, 1)确保计算安全。这是一个非常常见的编程细节坑。5. 初始化、学习率与代码实现避坑指南理解了原理最终要落到代码上。第一章虽然没有涉及复杂网络但建立正确的实现习惯至关重要。5.1 参数初始化不能全为零对于逻辑回归将权重w初始化为零是可以的。但对于有隐藏层的神经网络千万不能将权重矩阵W初始化为全零。为什么假设一个两层网络W[1]和W[2]都初始化为0。那么在前向传播时同一层所有神经元的输出a将完全相同因为计算相同。在反向传播时同一层所有神经元接收到的梯度dz也完全相同。导致的结果是同一层的所有神经元在每次更新后其参数依然保持完全相同。这相当于每一层只有一个神经元在起作用严重削弱了网络的表达能力。正确的初始化方法小随机数W np.random.randn(n_l, n_{l-1}) * 0.01。用很小的随机数如0.01打破对称性。He初始化配合ReLUW np.random.randn(n_l, n_{l-1}) * np.sqrt(2./n_{l-1})Xavier初始化配合Tanh/SigmoidW np.random.randn(n_l, n_{l-1}) * np.sqrt(1./n_{l-1})在初期使用小随机数初始化就足够了。记住原则打破对称性避免梯度爆炸或消失。5.2 学习率α最重要的超参数学习率决定了参数更新的步长。太大可能在山谷两侧来回跳跃无法收敛甚至导致损失爆炸。太小收敛速度极慢训练时间过长。没有放之四海而皆准的值。常见的策略是先尝试一个经验值如0.01, 0.001, 0.0001。观察损失曲线如果损失下降很慢可以适当增大α如果损失剧烈震荡甚至上升必须减小α。使用学习率衰减随着训练进行逐步减小α有助于后期精细调参收敛到更优点。在第一章的简单例子中可能感受不明显。但当你训练复杂网络时调好学习率往往是成功的第一步。5.3 代码实现中的维度检查这是新手调试代码时最耗时的地方。务必养成维度检查的习惯。# 假设网络结构为: n_x2, n_h4, n_y1 # 初始化参数 W1 np.random.randn(n_h, n_x) * 0.01 # (4, 2) b1 np.zeros((n_h, 1)) # (4, 1) W2 np.random.randn(n_y, n_h) * 0.01 # (1, 4) b2 np.zeros((n_y, 1)) # (1, 1) # 前向传播 Z1 np.dot(W1, X) b1 # W1(4,2) dot X(2, m) - (4, m) b1(4,1)广播 - (4, m) A1 np.tanh(Z1) # (4, m) Z2 np.dot(W2, A1) b2 # W2(1,4) dot A1(4, m) - (1, m) b2(1,1)广播 - (1, m) A2 sigmoid(Z2) # (1, m) 即 ŷ在每一步关键计算后特别是np.dot之后用print(Z1.shape)检查矩阵维度是否符合预期。90%的运行时错误都源于维度不匹配。记住一个口诀np.dot(A, B)要求A的列数等于B的行数结果形状是(A的行数 B的列数)。6. 概念延伸从基础网络到热搜中的复杂变体学懂了这一章的基础你再去看那些热搜词就不会再觉得它们是陌生的黑魔法了。卷积神经网络CNN它的核心“卷积层”你可以理解为一种特殊的、参数共享的“神经元连接方式”。普通神经网络全连接里每个神经元都和上一层的所有神经元相连。在CNN中一个卷积核相当于一个神经元只和输入图像的一小块区域局部感受野相连并且这个卷积核会滑动遍历整个图像参数共享。这极大地减少了参数量并抓住了图像的局部空间特征。池化层则是一种下采样增强特征的不变性。理解了前馈和梯度下降CNN的训练过程在本质上是一样的。图卷积神经网络GCN这是处理图结构数据如社交网络、分子结构的神经网络。传统CNN处理的是规整的网格数据图像而图是不规整的。GCN的核心思想是让每个节点的特征信息通过图的边关系传播给它的邻居节点。这个过程可以类比为一种特殊的“前馈”每个节点的新特征是其自身和邻居节点特征的加权平均聚合然后再经过一个非线性变换激活函数。所以它依然是“特征变换加权非线性激活”这个基本范式在图数据上的应用。BP神经网络结构图BPBackpropagation就是反向传播。你看到的那些带箭头的结构图描述的就是前馈过程。而BP的误差反向流动在结构图上是看不见的它是一种计算过程。神经网络多目标算法这通常指网络有多个输出头分别对应不同的任务如同时检测物体和分割图像。在基础网络上无非就是在最后的隐藏层后连接多个不同的输出层每个输出层有自己的损失函数。最终的总损失是这些损失的加权和。反向传播时梯度会从各个输出层反向传播回来共同更新共享的隐藏层参数。所以万变不离其宗。第一章教给你的就是那个“宗”神经网络是通过堆叠“加权求和非线性激活”的单元通过前向传播计算预测通过损失函数衡量误差再通过反向传播的梯度下降来迭代优化参数从而学习数据中的模式。牢牢抓住这条主线后续的所有复杂模型都是在这个骨架上生长出的血肉。我个人在最初学习时曾试图跳过这些“简单”的基础直接去跑通一个CNN模型。结果就是模型出问题时我完全不知道从哪里下手调试。后来回头扎扎实实理解了这些基本概念特别是维度变化、梯度流动和初始化再遇到问题就能很快定位到是数据预处理不对、是梯度爆炸了、还是网络结构设计有缺陷。这就像学武功内功心法基础概念远比一招一式的花架子调包跑模型重要得多。
返回列表