零基础入门神经网络:从数学公式到通俗理解
零基础入门神经网络:从数学公式到通俗理解
今天我们抛开复杂术语,从最基础的数学原理讲起,搭配简单案例,帮你真正入门神经网络
一、先搞懂:神经网络到底在做什么?
我们先从一个生活场景切入:怎么判断“一杯水能不能喝”?
通常我们会看两个指标:水温(x₁) 和 水质(x₂)。
- 水温太高(比如80℃)或太低(比如0℃),不能喝;
- 水质差(比如有杂质,用0表示),不能喝;水质好(用1表示),才有可能喝。
神经网络做的事,其实和这个判断过程一样:输入“特征”(比如水温、水质),通过数学计算,输出“结论”(能喝/不能喝)。
而这个“计算过程”,就是神经网络的核心——我们先从最简单的“单个神经元”开始讲。
二、单个神经元:神经网络的“最小判断单元”
单个神经元是神经网络的基础,它的计算逻辑只有3步:加权求和 → 加偏置 → 激活函数。
我们用“判断水能不能喝”的案例,一步步拆解每个步骤的数学原理。
1. 第一步:加权求和(给特征“重要性”打分)
首先,不同特征的“重要性”不一样。比如“水质”比“水温”更关键——哪怕水温刚好,水质差也绝对不能喝。
为了体现这种重要性,我们给每个特征分配一个“权重”(用w表示,weight):
- 水质(x₂)权重w₂=0.8(重要);
- 水温(x₁)权重w₁=0.2(次要)。
“加权求和”就是把“特征值×对应权重”加起来,公式如下:
z1=x1×w1+x2×w2z_1 = x_1 \times w_1 + x_2 \times w_2 z1=x1×w1+x2×w2
数学案例1:计算加权和
假设现在有一杯水:
- 水温x₁=0.5(假设0=冰水,1=温水,0.5就是刚好的温度);
- 水质x₂=1(水质好)。
代入公式计算:
z1=0.5×0.2+1×0.8=0.1+0.8=0.9z_1 = 0.5×0.2 + 1×0.8 = 0.1 + 0.8 = 0.9 z1=0.5×0.2+1×0.8=0.1+0.8=0.9
2. 第二步:加偏置(调整“判断基准”)
加权和还不够——比如有些朋友对水温特别敏感,哪怕水质好,水温稍微偏一点就不想喝。这时候需要一个“偏置项”(用b表示,bias)来调整判断基准。
偏置的作用像“门槛”:b为正,降低门槛(更容易输出“能喝”);b为负,提高门槛(更难输出“能喝”)。
加上偏置后的公式变成:
z=z1+b=x1w1+x2w2+bz = z_1 + b = x_1w_1 + x_2w_2 + b z=z1+b=x1w1+x2w2+b
数学案例2:加入偏置
假设我们对水温敏感,设置偏置b=-0.1(提高一点门槛)。
代入之前的z₁=0.9:
z=0.9+(−0.1)=0.8z = 0.9 + (-0.1) = 0.8 z=0.9+(−0.1)=0.8
3. 第三步:激活函数(把“连续值”变成“明确结论”)
现在我们得到了z=0.8,但这个数字是什么意思?我们需要一个“激活函数”,把z转换成“能喝(1)”或“不能喝(0)”的明确结论。
最常用的激活函数是Sigmoid函数——它能把任何数字压缩到0~1之间:值越接近1,代表“能喝”的概率越高;越接近0,概率越低。
Sigmoid函数公式:
σ(z)=11+e−z\sigma(z) = \frac{1}{1 + e^{-z}} σ(z)=1+e−z1
(其中e是自然常数,约等于2.718)
数学案例3:用激活函数输出结论
我们把z=0.8代入Sigmoid函数:
σ(0.8)=11+e−0.8≈11+0.449≈0.69\sigma(0.8) = \frac{1}{1 + e^{-0.8}} ≈ \frac{1}{1 + 0.449} ≈ 0.69 σ(0.8)=1+e−0.81≈1+0.4491≈0.69
0.69接近1,所以我们可以判断:这杯水能喝(通常我们会设一个阈值,比如0.5,大于0.5输出1,小于0.5输出0)。
三、多个神经元:组成“神经网络”
单个神经元只能处理简单问题(比如判断水能不能喝),但现实中问题更复杂——比如“判断一部手机值不值得买”,需要考虑价格、性能、续航、拍照4个特征,这时候就需要多个神经元组成“层”,再把层连起来。
神经网络的结构通常分三层:
- 输入层:接收原始特征(比如价格、性能);
- 隐藏层:对特征做复杂计算(多个神经元并行处理);
- 输出层:输出最终结论(比如“值得买”“一般”“不值得买”)。
举个例子:简单的两层神经网络
假设我们要判断手机,输入层有2个特征(x₁=性能,x₂=价格),隐藏层有2个神经元,输出层有1个神经元。
1. 输入层→隐藏层
每个输入特征会连接到隐藏层的所有神经元,且每个连接都有自己的权重和偏置:
- 神经元1:z1=x1w11+x2w21+b1z_1 = x_1w_{11} + x_2w_{21} + b_1z1=x1w11+x2w21+b1,输出a1=σ(z1)a_1 = \sigma(z_1)a1=σ(z1);
- 神经元2:z2=x1w12+x2w22+b2z_2 = x_1w_{12} + x_2w_{22} + b_2z2=x1w12+x2w22+b2,输出a2=σ(z2)a_2 = \sigma(z_2)a2=σ(z2)。
(w₁₁表示“输入x₁到神经元1的权重”,w₂₁表示“输入x₂到神经元1的权重”,以此类推)
2. 隐藏层→输出层
隐藏层的输出(a₁、a₂)会作为输入,传给输出层的神经元,再次计算:
zout=a1w31+a2w32+boutz_{out} = a_1w_{31} + a_2w_{32} + b_{out} zout=a1w31+a2w32+bout
yout=σ(zout)y_{out} = \sigma(z_{out}) yout=σ(zout)
数学案例4:两层神经网络计算
假设:
- 输入特征:性能x₁=0.9(满分1),价格x₂=0.6(越低越好,0.6代表价格适中);
- 隐藏层权重:w₁₁=0.7,w₂₁=0.3,w₁₂=0.4,w₂₂=0.6;
- 隐藏层偏置:b₁=-0.2,b₂=-0.1;
- 输出层权重:w₃₁=0.8,w₃₂=0.2;
- 输出层偏置:b_out=-0.1。
第一步:计算隐藏层输出
神经元1:
z1=0.9×0.7+0.6×0.3−0.2=0.63+0.18−0.2=0.61z_1 = 0.9×0.7 + 0.6×0.3 - 0.2 = 0.63 + 0.18 - 0.2 = 0.61 z1=0.9×0.7+0.6×0.3−0.2=0.63+0.18−0.2=0.61
a1=11+e−0.61≈0.65a_1 = \frac{1}{1 + e^{-0.61}} ≈ 0.65 a1=1+e−0.611≈0.65
神经元2:
z2=0.9×0.4+0.6×0.6−0.1=0.36+0.36−0.1=0.62z_2 = 0.9×0.4 + 0.6×0.6 - 0.1 = 0.36 + 0.36 - 0.1 = 0.62 z2=0.9×0.4+0.6×0.6−0.1=0.36+0.36−0.1=0.62
a2=11+e−0.62≈0.65a_2 = \frac{1}{1 + e^{-0.62}} ≈ 0.65 a2=1+e−0.621≈0.65
第二步:计算输出层结论
zout=0.65×0.8+0.65×0.2−0.1=0.52+0.13−0.1=0.55z_{out} = 0.65×0.8 + 0.65×0.2 - 0.1 = 0.52 + 0.13 - 0.1 = 0.55 zout=0.65×0.8+0.65×0.2−0.1=0.52+0.13−0.1=0.55
yout=11+e−0.55≈0.63y_{out} = \frac{1}{1 + e^{-0.55}} ≈ 0.63 yout=1+e−0.551≈0.63
0.63>0.5,所以结论是:这部手机值得买。
四、神经网络如何求权重和偏置?用梯度下降做“精准修正”(含公式推导+案例)
前面我们讲了神经元的计算逻辑和交叉熵损失函数——但还有个关键问题:初始的权重(w)和偏置(b)是“瞎猜”的,怎么通过“学习”调整到正确值?
答案是 梯度下降(Gradient Descent):它的核心逻辑是“沿着损失函数下降最快的方向,一步步修正权重和偏置”,直到损失最小(预测最准)。
我们依然用“判断水能不能喝”的案例,从“数学推导”到“数值计算”,完整拆解权重和偏置的求解过程。
4.1 先明确:我们要优化的目标
首先,回顾案例的核心设定:
- 输入特征:水温x₁(0=冰水,1=温水)、水质x₂(0=差,1=好);
- 神经元输出:y_pred = σ(x₁w₁ + x₂w₂ + b)(σ是Sigmoid函数,输出“能喝”的概率);
- 损失函数:交叉熵损失L = -[y_true×ln(y_pred) + (1-y_true)×ln(1-y_pred)](二分类问题简化版,y_true=1代表“能喝”,y_true=0代表“不能喝”);
- 初始参数(瞎猜的):w₁=0.1(水温权重)、w₂=0.5(水质权重)、b=0(偏置);
- 训练数据(1条样本):x₁=0.5(水温刚好)、x₂=1(水质好)、y_true=1(实际能喝)。
我们的目标是:调整w₁、w₂、b,让损失L变小。
4.2 核心原理:梯度下降的“三步法”
梯度下降的本质是“用导数找修正方向”,步骤如下:
- 算损失:用当前参数(w₁、w₂、b)计算损失L;
- 求梯度:计算损失L对每个参数的偏导数(∂L/∂w₁、∂L/∂w₂、∂L/∂b),偏导数的符号代表“修正方向”,绝对值代表“修正幅度参考”;
- 更新参数:按“新参数=旧参数-学习率×偏导数”调整,学习率η(通常取0.1~0.01)控制每次修正的步长(避免步子太大“踩空”)。
4.3 关键步骤1:推导偏导数(最核心的数学环节)
偏导数是“参数变化1单位时,损失L的变化量”——我们需要分别推导L对w₁、w₂、b的偏导数。
首先,先回顾两个基础公式的导数(后续会用到):
- Sigmoid函数的导数:σ’(z) = σ(z)×(1-σ(z)),其中z = x₁w₁ + x₂w₂ + b;可参考之前写的逻辑回归算法原理与案例解析这篇文章 。
- 对数函数的导数:d[ln(u)]/du = 1/u。
4.3.1 第一步:求L对y_pred的导数(dL/dy_pred)
由交叉熵损失公式(二分类简化版):
L=−[ytrue×ln(ypred)+(1−ytrue)×ln(1−ypred)]L = -[y_{true}×\ln(y_{pred}) + (1-y_{true})×\ln(1-y_{pred})] L=−[ytrue×ln(ypred)+(1−ytrue)×ln(1−ypred)]
对y_pred求导(按导数的四则运算法则展开):
dLdypred=−[ytrue×1ypred+(1−ytrue)×−11−ypred]\frac{dL}{dy_{pred}} = -\left[ y_{true}×\frac{1}{y_{pred}} + (1-y_{true})×\frac{-1}{1-y_{pred}} \right] dypreddL=−[ytrue×ypred1+(1−ytrue)×1−ypred−1]
化简后:
dLdypred=ypred−ytrueypred(1−ypred)\frac{dL}{dy_{pred}} = \frac{y_{pred} - y_{true}}{y_{pred}(1 - y_{pred})} dypreddL=ypred(1−ypred)ypred−ytrue
4.3.2 第二步:求y_pred对z的导数(dy_pred/dz)
因为y_pred = σ(z),而σ(z)的导数是σ(z)(1-σ(z)),所以:
dypreddz=σ(z)×(1−σ(z))=ypred×(1−ypred)\frac{dy_{pred}}{dz} = σ(z)×(1 - σ(z)) = y_{pred}×(1 - y_{pred}) dzdypred=σ(z)×(1−σ(z))=ypred×(1−ypred)
4.3.3 第三步:求z对参数的导数(dz/dw₁、dz/dw₂、dz/db)
z = x₁w₁ + x₂w₂ + b,按导数的基本规则(变量求导,常数导数为0):
- z对w₁的导数:dz/dw₁ = x₁(w₁是变量,x₁是输入常数);
- z对w₂的导数:dz/dw₂ = x₂;
- z对b的导数:dz/db = 1(b是变量,常数项导数为1)。
4.3.4 第四步:链式法则求L对参数的偏导数
因为L→y_pred→z→参数(w₁/w₂/b),所以用链式法则(导数相乘)求偏导数:
∂L∂参数=dLdypred×dypreddz×dz∂参数\frac{\partial L}{\partial 参数} = \frac{dL}{dy_{pred}} × \frac{dy_{pred}}{dz} × \frac{dz}{\partial 参数} ∂参数∂L=dypreddL×dzdypred×∂参数dz
(1)推导L对w₁的偏导数(∂L/∂w₁)
将前面的导数结果代入链式法则:
∂L∂w1=ypred−ytrueypred(1−ypred)×ypred(1−ypred)×x1\frac{\partial L}{\partial w_1} = \frac{y_{pred} - y_{true}}{y_{pred}(1 - y_{pred})} × y_{pred}(1 - y_{pred}) × x_1 ∂w1∂L=ypred(1−ypred)ypred−ytrue×ypred(1−ypred)×x1
中间的y_pred(1-y_pred)可以约掉,最终简化为:
∂L∂w1=(ypred−ytrue)×x1\frac{\partial L}{\partial w_1} = (y_{pred} - y_{true}) × x_1 ∂w1∂L=(ypred−ytrue)×x1
(2)推导L对w₂的偏导数(∂L/∂w₂)
同理,只是将dz/dw₁换成x₂,结果为:
∂L∂w2=(ypred−ytrue)×x2\frac{\partial L}{\partial w_2} = (y_{pred} - y_{true}) × x_2 ∂w2∂L=(ypred−ytrue)×x2
(3)推导L对b的偏导数(∂L/∂b)
dz/db=1,代入链式法则后:
∂L∂b=(ypred−ytrue)×1=ypred−ytrue\frac{\partial L}{\partial b} = (y_{pred} - y_{true}) × 1 = y_{pred} - y_{true} ∂b∂L=(ypred−ytrue)×1=ypred−ytrue
4.3.5 最终结论:偏导数公式(超简洁!)
通过推导,我们得到了非常简单的偏导数公式(这也是交叉熵+Sigmoid组合的优势——导数简化后计算量小):
参数 | 偏导数公式(∂L/∂参数) |
---|---|
w₁ | (y_pred - y_true) × x₁ |
w₂ | (y_pred - y_true) × x₂ |
b | y_pred - y_true |
4.4 关键步骤2:用案例做“参数更新”(数值计算)
有了偏导数公式,我们就可以按“梯度下降”的步骤更新参数了。
首先明确已知条件:
- 训练样本:x₁=0.5(水温)、x₂=1(水质)、y_true=1(能喝);
- 初始参数:w₁=0.1、w₂=0.5、b=0;
- 学习率η=0.1(步长适中,避免震荡);
- 参数更新公式:新参数=旧参数−η×偏导数新参数 = 旧参数 - η × 偏导数 新参数=旧参数−η×偏导数
第一步:计算当前的y_pred(用初始参数)
先算z = x₁w₁ + x₂w₂ + b:
z=0.5×0.1+1×0.5+0=0.05+0.5=0.55z = 0.5×0.1 + 1×0.5 + 0 = 0.05 + 0.5 = 0.55 z=0.5×0.1+1×0.5+0=0.05+0.5=0.55
再用Sigmoid函数算y_pred(“能喝”的概率):
ypred=σ(z)=11+e−0.55≈11+0.577≈0.637y_{pred} = σ(z) = \frac{1}{1 + e^{-0.55}} ≈ \frac{1}{1 + 0.577} ≈ 0.637 ypred=σ(z)=1+e−0.551≈1+0.5771≈0.637
第二步:计算各参数的偏导数
根据前面推导的公式,代入y_pred=0.637、y_true=1、x₁=0.5、x₂=1:
- ∂L/∂w₁ = (0.637 - 1) × 0.5 = (-0.363) × 0.5 = -0.1815;
- ∂L/∂w₂ = (0.637 - 1) × 1 = (-0.363) × 1 = -0.363;
- ∂L/∂b = 0.637 - 1 = -0.363。
第三步:更新参数(第一次迭代)
按更新公式计算新参数:
- 新w₁ = 旧w₁ - η×∂L/∂w₁ = 0.1 - 0.1×(-0.1815) = 0.1 + 0.01815 = 0.11815;
- 新w₂ = 旧w₂ - η×∂L/∂w₂ = 0.5 - 0.1×(-0.363) = 0.5 + 0.0363 = 0.5363;
- 新b = 旧b - η×∂L/∂b = 0 - 0.1×(-0.363) = 0 + 0.0363 = 0.0363。
第四步:验证更新效果(损失是否变小)
用新参数重新计算y_pred和损失L,看是否优化:
- 新z = 0.5×0.11815 + 1×0.5363 + 0.0363 ≈ 0.059 + 0.5363 + 0.0363 ≈ 0.6316;
- 新y_pred = σ(0.6316) ≈ 1/(1+e^-0.6316) ≈ 1/(1+0.532) ≈ 0.653(比之前的0.637更接近y_true=1);
- 新损失L = -[1×ln(0.653) + 0×…] ≈ -(-0.426) ≈ 0.426(比初始损失0.449更小,优化有效!)。
第五步:多次迭代后的结果(趋势)
如果我们重复上述步骤(迭代10次),参数和损失会持续优化:
迭代次数 | w₁(水温权重) | w₂(水质权重) | b(偏置) | y_pred(能喝概率) | 损失L |
---|---|---|---|---|---|
初始 | 0.1 | 0.5 | 0 | 0.637 | 0.449 |
1次 | 0.118 | 0.536 | 0.036 | 0.653 | 0.426 |
5次 | 0.172 | 0.643 | 0.143 | 0.698 | 0.369 |
10次 | 0.225 | 0.745 | 0.245 | 0.735 | 0.319 |
可以看到:随着迭代次数增加,y_pred越来越接近1(正确答案),损失L越来越小——这就是梯度下降的“优化效果”。最终当损失L趋近于0时,w₁、w₂、b就达到了“最优值”。
4.5 通俗总结:权重和偏置的“学习逻辑”
其实整个过程就像“调收音机”:
- 初始参数=“随便拧的频率”,杂音大(损失L大);
- 偏导数=“杂音的方向”(往左拧杂音变小,还是往右拧);
- 学习率=“每次拧的幅度”(太小调得慢,太大容易跳过清晰频率);
- 迭代更新=“一次次微调”,直到杂音最小(损失最小)。
而我们推导的偏导数公式,就是帮我们精准判断“该往哪个方向调、调多少”的核心工具。
通过这个案例可以发现:神经网络求权重和偏置,不是“一步到位”,而是“通过梯度下降逐步修正”——关键在于用链式法则求出偏导数,再按学习率迭代更新。后续学习复杂网络(比如多层神经网络)时,逻辑是一样的,只是参数更多、偏导数推导更繁琐(但框架会帮我们自动计算)。