深度学习入门学习笔记--感知机、神经网络
第二章 感知机
感知机是神经网络与深度学习的基础算法,是一种接收多个输入、输出单个二值信号的简单模型。
1. 感知机的基本原理
感知机的核心单元是神经元(节点):输入信号 x1,x2 会被赋予对应的权重 w1,w2(也叫参数),神经元对加权后的输入求和,当求和结果超过某个阈值 θ 时,输出 1(神经元被激活),否则输出 0。
原始数学表达式:
引入偏置 b:将阈值 θ 移项并替换为 −b,公式改写为更通用的形式:
权重 w:控制输入信号的重要性,权重越大,对应输入对结果的影响越强。
偏置 b:控制神经元被激活的难易程度,b 越大,神经元越容易输出 1。
2. 单层感知机实现基础逻辑门
通过调整权重和偏置,单层感知机可以实现与门(AND)、与非门(NAND)、或门(OR)等线性可分的逻辑电路。
import numpy as np # 与门 def AND(x1, x2): x = np.array([x1, x2]) w = np.array([0.5, 0.5]) b = -0.7 tmp = np.sum(w * x) + b return 1 if tmp > 0 else 0 # 与非门 def NAND(x1, x2): x = np.array([x1, x2]) w = np.array([-0.5, -0.5]) b = 0.7 tmp = np.sum(w * x) + b return 1 if tmp > 0 else 0 # 或门 def OR(x1, x2): x = np.array([x1, x2]) w = np.array([0.5, 0.5]) b = -0.2 tmp = np.sum(w * x) + b return 1 if tmp > 0 else 03. 感知机的局限性:无法实现异或门
异或门(XOR)属于非线性可分问题,单层感知机无法处理:
与门、或门的决策边界是一条直线,可以把二维空间分为两个线性区域,属于线性可分问题。
当w1=w2=1,b=-0.5,感知机会生成由直线−0.5 + x1 + x2 = 0分割开的两个空 间。其中一个空间输出1,另一个空间输出0,可表示或门
异或门的正负样本无法用一条直线分割,需要曲线 / 折线作为决策边界,属于非线性空间问题。单层感知机只能表示线性分割,因此无法单独实现异或门。
4. 多层感知机解决非线性问题
通过叠加感知机层(构建多层结构),可以实现非线性分割,解决异或门问题。
原理:组合与非门、或门、与门,通过「输入层 → 隐藏层 → 输出层」的 2 层感知机结构实现异或。
真值表:
def XOR(x1, x2): s1 = NAND(x1, x2) s2 = OR(x1, x2) y = AND(s1, s2) return y结论:多层感知机可以表示复杂的非线性空间,理论上 2 层感知机就能够拟合任意函数。
第三章 神经网络
神经网络在感知机的基础上,引入平滑可导的激活函数与多层结构,支持通过梯度法自动学习参数,是深度学习的核心载体。
1. 神经网络的基本概念
神经网络由输入层、隐藏层、输出层构成,信号从输入向输出单向传递(前向传播)。
和感知机的核心差异:感知机使用阶跃函数(二值离散输出),神经网络使用连续可导的激活函数,支持通过梯度更新参数完成学习。
核心能力:通过叠加层与非线性激活函数,拟合任意复杂的非线性关系。
2. 激活函数
激活函数会将输入信号的总和转换为输出信号,比如感知机实现的与门x1,x2均为1,输出y为1
激活函数的作用是为神经网络引入非线性。如果没有激活函数,无论叠加多少层网络,都等价于单层线性变换,无法拟合复杂模式。
(1) 阶跃函数
感知机使用的激活函数,输入大于 0 时输出 1,否则输出 0。
def step_function(x): return np.array(x > 0, dtype=np.int32)特点:输出离散、存在突变点,几乎处处导数为 0,无法用于梯度学习。
(2) sigmoid 函数
经典的平滑激活函数,将输入压缩到 (0,1) 区间。
公式:
代码实现:
def sigmoid(x): return 1 / (1 + np.exp(-x))sigmoid 与 阶跃函数的异同:
| 对比维度 | 阶跃函数 | sigmoid 函数 |
|---|---|---|
| 输出形式 | 0/1 离散二值 | 0~1 之间的连续值 |
| 平滑性 | 存在突变跳变,不光滑 | 曲线平滑,处处可导 |
| 梯度可用性 | 几乎处处导数为 0,无法支持梯度学习 | 导数连续,可用于反向传播更新参数 |
| 共性 | 都是 S 型曲线,输入越大输出越接近 1,输入越小越接近 0,都具备非线性 |
(3) ReLU 函数
目前深度学习最常用的激活函数,输入为正时原样输出,负时输出 0。
公式:
代码实现:
def relu(x): return np.maximum(0, x)特点:计算简单高效,能有效缓解深层网络的梯度消失问题。
3. 多维数组的矩阵运算
神经网络的前向传播可以通过矩阵乘积(点积)高效实现,避免逐元素循环。
矩阵乘法要求:第一个矩阵的列数 = 第二个矩阵的行数。
简单示例(输入层到隐藏层的加权计算):
X = np.array([1.0, 0.5]) # 输入,形状(2,) W = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]]) # 权重,形状(2,3) B = np.array([0.1, 0.2, 0.3]) # 偏置,形状(3,) A = np.dot(X, W) + B # 加权和,形状(3,) Z = sigmoid(A) # 激活后输出4. 三层神经网络的前向传播实现
以「输入层 (2 神经元)→隐藏层 1 (3 神经元)→隐藏层 2 (2 神经元)→输出层 (2 神经元)」为例,完整前向传播代码:
def init_network(): network = {} network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]]) network['b1'] = np.array([0.1, 0.2, 0.3]) network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]]) network['b2'] = np.array([0.1, 0.2]) network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]]) network['b3'] = np.array([0.1, 0.2]) return network def forward(network, x): W1, W2, W3 = network['W1'], network['W2'], network['W3'] b1, b2, b3 = network['b1'], network['b2'], network['b3'] a1 = np.dot(x, W1) + b1 z1 = sigmoid(a1) a2 = np.dot(z1, W2) + b2 z2 = sigmoid(a2) a3 = np.dot(z2, W3) + b3 y = identity_function(a3) return y5. 输出层的设计
输出层的激活函数根据任务类型选择:
(1) 恒等函数
适用场景:回归问题(预测连续数值,如房价、温度)。
定义:输入原样输出,h(x)=x。
def identity_function(x): return x(2) softmax 函数
适用场景:分类问题(输出每个类别的概率,所有类别概率和为 1)。
公式:
溢出问题:当输入数值很大时,ex^x会指数级增长,导致数值溢出。
优化方案:减去输入中的最大值,不改变计算结果但避免溢出。下图的C取ai的最大值
优化后代码:
def softmax(a): c = np.max(a) exp_a = np.exp(a - c) # 减去最大值防止溢出 sum_exp_a = np.sum(exp_a) y = exp_a / sum_exp_a return y性质:输出值都在 0~1 之间,并且所有输出的和为 1,可以直接解释为每个类别的概率。
