建议看尚硅谷深度学习视频
-
-
- 一、深度学习基本概念和结构
- 二、感知机和激活函数的由来
- 三、激活函数作用
-
- [作用一: 没有激活函数,一万层网络也只等于一层线性回归,啥复杂问题都解决不了](#作用一: 没有激活函数,一万层网络也只等于一层线性回归,啥复杂问题都解决不了)
- [作用二: 决定神经元是否"放电"(特征过滤)](#作用二: 决定神经元是否“放电”(特征过滤))
- [作用三: 压缩数值范围,防止"梯度爆炸"](#作用三: 压缩数值范围,防止“梯度爆炸”)
- [思考:激活函数算出来是 0 这个数值,就不会被下一层加入计算吗?(是的,完全不会)](#思考:激活函数算出来是 0 这个数值,就不会被下一层加入计算吗?(是的,完全不会))
- [插曲一些知识: 偏置 b 和激活函数真正放在一起,看看它们到底是怎么配合的。](#插曲一些知识: 偏置 b 和激活函数真正放在一起,看看它们到底是怎么配合的。)
- 四、阶跃函数
- 五、sigmoid
- 六、Tanh函数
-
笔记来自尚硅谷 深度学习 截图
一、深度学习基本概念和结构
人工神经网络(Artificial Neural Network,ANN)简称 神经网络(NN),是一种模仿生物神经网络结构和功能的计算模型。大多数情况下人工神经网络能在外界信息的基础上改变内部结构,是一种自适应系统(adaptive system),通俗地讲就是具备学习功能。


相邻层的神经元相互连接(图中下一层每个神经元都与上一层所有神经元连接,称为 全连接),每个连接都会有一个 权重。
神经元中的信息逐层传递(一般称为 前向传播 forward),上一层神经元的输出作为下一层神经元的输入
二、感知机和激活函数的由来
感知器(perceptron)是二分类模型,接受多个信号,输出一个信号.感知机的信号只有0,1两种取值。




重要的事,打一遍字:不用一直线性下去吧
h(x)可以将输入信号的加权总和转换为输出信号,起到"激活神经元"的作用,所以被称为 激活函数

三、激活函数作用
激活函数是连接感知机和神经网络的桥梁,在神经网络中起着至关重要的作用。
作用一: 没有激活函数,一万层网络也只等于一层线性回归,啥复杂问题都解决不了
如果没有激活函数,整个神经网络就等效于单层线性变换,不论如何加深层数,总是存在与之等效的"无隐藏层的神经网络"。激活函数必须是非线性函数,也正是激活函数的存在为神经网络引入了非线性,使得神经网络能够学习和表示复杂的非线性关系。
作用二: 决定神经元是否"放电"(特征过滤)
现实中大脑的神经元,只有当接收到的刺激超过一定阈值时,才会"放电"把信号传给下一个神经元。激活函数就是模拟这个机制。它把前一层的加权求和( a a a),映射成一个"激活程度"。比如大于某个值,才把信号传给下一层。
作用三: 压缩数值范围,防止"梯度爆炸"
你看图里的 a = w 1 x 1 + w 2 x 2 + b a = w_1x_1 + w_2x_2 + b a=w1x1+w2x2+b。如果在深层网络里,每层算出来的值都越来越大(比如变成 1000、10000),计算机的浮点数会溢出,模型直接崩溃(这叫梯度爆炸)。
激活函数可以把这些无限大的数字"挤压"回一个安全范围(比如 − 1 , 1 -1, 1 −1,1 或 [ 0 , ∞ ) [0, \infty) [0,∞)),让网络能稳定训练。
思考:激活函数算出来是 0 这个数值,就不会被下一层加入计算吗?(是的,完全不会)
我们以最经典的激活函数 ReLU (Rectified Linear Unit, 线性整流函数) 为例。它的公式极简单:
f ( x ) = m a x ( 0 , x ) f(x) = max(0, x) f(x)=max(0,x)。
- 如果输入 x > 0 x > 0 x>0,输出还是 x x x。
- 如果输入 x ≤ 0 x \le 0 x≤0,输出直接强行变成 0。
"变成 0"在下一层计算时意味着什么?
假设下一层的计算是 y = w 1 ⋅ a 1 + w 2 ⋅ a 2 + b y = w_1 \cdot a_1 + w_2 \cdot a_2 + b y=w1⋅a1+w2⋅a2+b。
如果上一层传过来的 a 1 a_1 a1 经过激活函数变成了 0。那么:
y = w 1 ⋅ 0 + w 2 ⋅ a 2 + b = w 2 ⋅ a 2 + b y = w_1 \cdot 0 + w_2 \cdot a_2 + b = w_2 \cdot a_2 + b y=w1⋅0+w2⋅a2+b=w2⋅a2+b
你看, w 1 w_1 w1 和 a 1 a_1 a1 直接从公式里消失了。
在神经网络和矩阵运算中,0 就代表"此路不通"。这就引出了深度学习中极其重要的一种现象:
1. 产生"稀疏性 (Sparsity)"(极度省算力)
图片里有大量的像素点、一句话里有大量无用的介词,它们对最终结果没贡献。ReLU 让这些无用特征直接变成 0。下一层遇到 0 就不用算了,大大节省了 GPU 的算力。这种"断舍离"不仅省算力,还是让神经网络变得聪明和高效的秘诀
2. 强迫网络只关注"重点"(抗噪)
如果输入的是无用的噪声,算出来的值大概率小于 0,被 ReLU 激活成 0 后,等于告诉后面的网络:"这全是废话,不用管它了"。这极大地提高了模型提取核心特征的效率。
3. 避免梯度消失(ReLU 的绝活)
早期的激活函数(比如 Sigmoid)在输入极大或极小时,曲线是平的。曲线平 = 导数为 0 = 训练时权重无法更新(这叫梯度消失)。
而 ReLU 只要输入大于 0,它的导数永远是 1。这意味着误差可以畅通无阻地传回前面的层,极大加速了深层网络的训练。(早期的 Transformer 和现在的很多 CNN,中间层都在疯狂使用 ReLU 或者它的变体 GELU)。
那为 0 有啥坏处吗?
有。如果输入永远小于 0,输出永远为 0,导数也为 0。那个神经元就"死"了(Dead Neuron),参数永远无法更新。
为了防这个,工程师后来发明了 Leaky ReLU ,让小于 0 的部分不是 0,而是 0.01 x 0.01x 0.01x(保留一点点微弱信号,不让它彻底死掉)。
插曲一些知识: 偏置 b 和激活函数真正放在一起,看看它们到底是怎么配合的。
真相:偏置 b b b 的作用,就是用来"控制"激活函数的!
结合公式,我们把流程排好:
- 第一步(线性计算): a = w 1 x 1 + w 2 x 2 + b a = w_1x_1 + w_2x_2 + b a=w1x1+w2x2+b (这一步把输入加权求和,并加上偏置 b b b)
- 第二步(激活函数): y = f ( a ) y = f(a) y=f(a) (把算出来的 a a a 塞进激活函数)
为什么非要在进激活函数之前,加一个 b b b 呢?
你想,如果没有偏置 b b b。那么输入信号 x 1 x_1 x1 和 x 2 x_2 x2 哪怕全等于 0,算出来的 a a a 也是 0。这就意味着,当没有输入信号时,这个神经元绝对不可能被激活,它永远死气沉沉。
加了偏置 b b b,就相当于给神经元设定了一个"门槛(或基础活跃度)"。
我们以 ReLU 激活函数(公式是 f ( a ) = m a x ( 0 , a ) f(a) = max(0, a) f(a)=max(0,a),即负数变0,正数保留) 为例,来看看 b b b 的魔法:
-
情况 1:假设 b b b 是一个负数(比如 b = − 5 b = -5 b=−5)
哪怕你给了输入信号(比如 w 1 x 1 + w 2 x 2 = 3 w_1x_1 + w_2x_2 = 3 w1x1+w2x2=3),算出来的 a = 3 − 5 = − 2 a = 3 - 5 = -2 a=3−5=−2。
然后 a = − 2 a = -2 a=−2 进了激活函数,ReLU 一看是负数,直接把它变成 0。
- 结果: 这个神经元非常"高冷",它觉得信号太弱了,不值得兴奋,所以不激活(输出 0,后面的层就不计算它了)。
-
情况 2:假设 b b b 是一个正数(比如 b = 5 b = 5 b=5)
哪怕你根本没给任何输入信号(输入全是 0),算出来的 a = 0 + 5 = 5 a = 0 + 5 = 5 a=0+5=5。
然后 a = 5 a = 5 a=5 进了激活函数,ReLU 一看是正数,原样输出 5。
- 结果: 这个神经元非常"敏感",一点点风吹草动(或者没动静)它也会被激活。
-
情况 3:训练过程中,网络在调整 b b b
网络在"学习"时,如果发现某个神经元太容易激活了(老是输出非 0 值,导致模型预测错误),反向传播算法就会把它的 b b b 调小一点(往负数方向调),让它冷静一下;如果发现它太死板了(总是输出 0,啥特征也学不到),就会把 b b b 调大一点,让它更容易被激活。
记住一句话:b 是给激活函数打辅助的,它决定了神经元被激活的难易程度
四、阶跃函数


python
#阶跃函数(输入是一个标量)
import numpy as np
def step_function0(x):
if x > 0:
return 1
else:
return 0
def step_function(x):
return np.array(x > 0,dtype=int)
if __name__ == '__main__':
x = np.array([0,1,2,3,4,5,-1,-2,-3,-4,-5])
print(step_function(x))
五、sigmoid
下面是函数和导函数图片,从第二张导函数能看出来再等0是到了拐点
靠近0是开始急剧增大,过了拐点开始慢慢增大减速
导函数下降,不代表原函数就会下降。只要导函数的值(也就是斜率)还是正数,原函数就一直在上升。
核心概念:导函数的"正负"决定原函数的"升降"
- 导函数 (f'(x) > 0)(在 x 轴上方):原函数 f(x) 就在上升。
- 导函数 (f'(x) < 0)(在 x 轴下方):原函数 f(x) 就在下降。
你看右图(Sigmoid 的导函数图像),它在 x=0之后确实开始下降了(从最高点 0.25 往下掉)。但是,它下降归下降,它依然在 x 轴的上方,数值依然是正数! 所以原函数 f(x) 依然在增加,只是增加的速度变慢了。

S i g m o i d Sigmoid Sigmoid(也叫 Logistic 函数)是平滑的、可微的,能将任意输入映射到区间(0,1),常用于二分类的输出层。但因其涉及指数运算,计算量相对较高。
S i g m o i d Sigmoid Sigmoid 的输入在-6,6之外时,其输出值变化很小,可能导致信息丢失。
S i g m o i d Sigmoid Sigmoid 的输出并非以 0 为中心,其输出值均>0,导致后续层的输入始终为正,可能影响后续梯度更新方向。
S i g m o i d Sigmoid Sigmoid 的导数范围为(0,0.25),梯度较小。当输入在-6,6之外时,导数接近 0,此时网络参数的更新将会极其缓慢。使用 Sigmoid 作为激活函数,可能出现梯度消失(在逐层反向传播时,梯度会呈指数级衰减)。
别的不说 ,先搞定求导回忆基础复合求导

s i g m o i d sigmoid sigmoid求导过程 σ ( x ) \sigma(x) σ(x) 和 f(x) 一个意思,所以下面ai用 σ ( x ) \sigma(x) σ(x)计算求导
σ ( x ) \sigma(x) σ(x) = 1 1 + e − x \frac{1}{1 + e^{-x}} 1+e−x1


代码(包含测试阶跃函数)
python
# Sigmoid函数
def sigmoid(x):
return 1/(1+np.exp(-x))
if __name__ == '__main__':
x = np.array([0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5])
print(step_function(x))
print(sigmoid(x))
六、Tanh函数
Tanh函数就是sigmoid的平移和缩放
原来sigmoid 的值是 0到1
这里2 sigmoid(2x) 的值是 0到2
又减去1 所以值变成-1 到 1


python
import numpy as np
x = np.array([0,1,2,3,4,5,-1,-2,-3,-4,-5])
np.tanh(x)