单层感知机#

定义#

单层感知机(Single-Layer Perceptron) 是最简单的神经网络,由Frank Rosenblatt在1957年提出。

结构#

数学表示#

对于输入向量 $\mathbf{x} = [x_1, x_2, \ldots, x_n]$ :

$$ y = f(w_1 x_1 + w_2 x_2 + \cdots + w_n x_n + b) $$ $$ y = f(\mathbf{w} \cdot \mathbf{x} + b) $$

其中:

  • $\mathbf{w} = [w_1, w_2, \ldots, w_n]$ :权重向量
  • $b$ :偏置(bias)
  • $f$ :激活函数

仿生学根源#

单层感知机模拟了生物神经元的工作方式:

  • 输入:树突接收信号
  • 权重:突触强度
  • 求和:细胞体整合信号
  • 激活:轴突输出信号

局限性#

单层感知机只能解决线性可分 问题,无法处理异或(XOR)等非线性问题。


多层感知机#

定义#

多层感知机(Multi-Layer Perceptron, MLP) 通过堆叠多个隐藏层,可以学习非线性关系。

结构#

输入层 → 隐藏层1 → 隐藏层2 → ... → 隐藏层N → 输出层

为什么需要多层?#

万能逼近定理(Universal Approximation Theorem)

  • 一个足够大的单隐藏层神经网络可以逼近任意连续函数
  • 但深度网络(多层)通常更高效,参数更少

深度 vs 宽度#

  • 深度网络:层数多,每层神经元少
  • 宽度网络:层数少,每层神经元多
  • 深度网络优势:层次化特征学习,参数效率更高

神经网络结构#

基本组件#

1. 输入层(Input Layer)#

  • 接收原始数据
  • 不进行任何计算
  • 维度由数据决定

2. 隐藏层(Hidden Layer)#

  • 学习数据的特征表示
  • 浅层:学习低级特征(边缘、纹理)
  • 深层:学习高级特征(形状、语义)

3. 输出层(Output Layer)#

  • 输出最终结果
  • 维度由任务决定(分类:类别数;回归:1)

神经网络的表达能力#

线性变换的局限性#

单层网络只能学习线性关系:

$$ y = W \cdot \mathbf{x} + b $$

激活函数的作用#

激活函数引入非线性,使网络能够学习复杂模式:

$$ y = f(W \cdot \mathbf{x} + b) \quad \text{($f$ 是非线性函数)} $$

深度网络的优势#

  1. 层次化特征学习

    • 第1层:边缘、纹理
    • 第2层:形状、模式
    • 第3层:对象部分
    • 第4层:完整对象
  2. 参数效率

    • 深度网络用更少的参数表达复杂函数
    • 浅层网络需要指数级参数
  3. 组合性

    • 深层特征由浅层特征组合而成
    • 实现特征的复用

网络参数#

权重(Weights)#

  • 连接不同层神经元的参数
  • 形状:[输入维度, 输出维度]
  • 初始化:通常随机初始化

偏置(Bias)#

  • 每个神经元的偏移量
  • 形状:[输出维度]
  • 作用:增加模型的灵活性

参数数量计算#

对于全连接层:

$$ \text{参数数量} = (\text{输入维度} + 1) \times \text{输出维度} $$

示例

  • 输入维度:784($28 \times 28$ 图像)
  • 输出维度:128
  • 参数数量:$(784 + 1) \times 128 = 100,480$

前向传播#

定义#

前向传播(Forward Propagation) 是数据从输入层流向输出层的过程。

计算步骤#

对于第 $l$ 层:

$$ z^{(l)} = W^{(l)} \cdot a^{(l-1)} + b^{(l)} \quad \text{(线性变换)} $$ $$ a^{(l)} = f(z^{(l)}) \quad \text{(激活函数)} $$

其中:

  • $z^{(l)}$ :第 $l$ 层的线性输出(logits)
  • $a^{(l)}$ :第 $l$ 层的激活输出 [输入维度,1]
  • $W^{(l)}$ :第 $l$ 层的权重矩阵 [输出维度,输入维度]
  • $b^{(l)}$ :第 $l$ 层的偏置向量
  • $f$ :激活函数

矩阵形式#

对于批量数据(batch size = $m$ ),计算形式不必深究:

$$ Z^{(l)} = A^{(l-1)} \cdot W^{(l)} + B^{(l)} $$ $$ A^{(l)} = f(Z^{(l)}) $$

其中:

  • $A^{(l-1)}$ :$[m, \text{输入维度}]$
  • $W^{(l)}$ :$[\text{输入维度}, \text{输出维度}]$
  • $Z^{(l)}$ :$[m, \text{输出维度}]$

线性回归#

问题引入#

房价预测 问题为例:

假设影响房价的属性有:

  • $x_1$ :面积(平方米)
  • $x_2$ :楼层
  • $x_3$ :卧室数量

价格是这些属性的线性函数:

$$ y = w_1 x_1 + w_2 x_2 + w_3 x_3 + b $$

其中:

  • $w_1, w_2, w_3$ :权重(weights),表示每个属性的重要性
  • $b$ :偏置(bias),表示基础价格

目标:确定 $w_1$ 、$w_2$ 、$w_3$ 和 $b$ 的值,使得预测价格尽可能接近真实价格。

矩阵形式表示#

将输入属性用向量表示:

$$ \mathbf{x} = [x_1, x_2, x_3] $$

参数用向量和标量表示:

$$ \mathbf{w} = [w_1, w_2, w_3]^T, \quad b = b $$

公式可写成:

$$ \hat{y} = \mathbf{x} \cdot \mathbf{w} + b $$

这可以理解为单层感知机,有仿生学根源(模拟神经元的工作方式)。

一般形式#

对于 $n$ 个特征:

$$ \hat{y} = w_1 x_1 + w_2 x_2 + \cdots + w_n x_n + b $$

矩阵形式:

$$ \hat{y} = \mathbf{x}\mathbf{w} + b $$

其中 $\mathbf{x}$ 是 $1 \times n$ 的行向量,$\mathbf{w}$ 是 $n \times 1$ 的列向量。


损失函数#

定义#

损失函数(Loss Function) 用于评判预测结果的准确性,是人为选择的函数。

一般原则

  • 比较预测值 $\hat{y}$ 和真实值 $y$
  • 越接近,损失越小
  • 目标:最小化损失函数

均方误差损失函数(MSE)#

公式

$$ L = (y - \hat{y})^2 $$

特点

  • 预测值与真实值差距越大,损失越大
  • 平方项使得大误差被放大,小误差被缩小
  • 通过调整 $\mathbf{w}$ 和 $b$ 来降低损失

多个样本的平均损失#

对于 $m$ 个样本:

$$ L = \frac{1}{m} \sum_{i=1}^{m} (y_i - \hat{y}_i)^2 $$

这是均方误差(Mean Squared Error, MSE)


梯度下降#

原理#

梯度下降(Gradient Descent) 是寻找损失函数极小值点的方法。

核心思想

  • 损失函数 $L$ 是关于参数 $\theta$ (包括 $\mathbf{w}$ 和 $b$ )的函数
  • 通过迭代更新参数,使损失函数不断减小
  • 沿着损失函数下降最快的方向(负梯度方向)更新参数

更新公式#

$$ \theta_{i+1} = \theta_i - \eta \cdot \frac{\partial L}{\partial \theta} $$

其中:

  • $\theta_i$ :当前参数值
  • $\theta_{i+1}$ :更新后的参数值
  • $\eta$ :学习率(learning rate)
  • $\frac{\partial L}{\partial \theta}$ :损失函数对参数的梯度(偏导数)

一维情况#

以一维参数 $\theta$ 为例:

$$ L(\theta) = (y - (\theta \cdot x + b))^2 $$

更新过程

  1. 计算梯度:$\frac{\partial L}{\partial \theta}$ (对自身变量求偏导)
  2. 如果梯度 $> 0$ :减小 $\theta$
  3. 如果梯度 $< 0$ :增大 $\theta$
  4. 更新:$\theta = \theta - \eta \cdot \frac{\partial L}{\partial \theta}$

多维情况#

将 $b$ 合并到 $\mathbf{w}$ 中:

$$ \hat{y} = \mathbf{x}\mathbf{w} + b = [\mathbf{x}, 1] \cdot [\mathbf{w}, b]^T = \mathbf{x}'\mathbf{w}' $$

梯度

  • 梯度是损失函数在当前点增加速度最大的方向
  • 更新参数时,减去梯度乘以学习率
  • 对于多个参数,分别计算每个参数的梯度

向量形式

$$ \mathbf{w}_{i+1} = \mathbf{w}_i - \eta \cdot \nabla L(\mathbf{w}_i) $$

其中 $\nabla L(\mathbf{w}_i)$ 是损失函数在 $\mathbf{w}_i$ 处的梯度向量。

学习率的影响#

学习率过小#

  • 问题:更新步长太小
  • 后果
    • 浪费算力
    • 学习速度慢
    • 可能陷入局部最优

学习率过大#

  • 问题:更新步长太大
  • 后果
    • 导致震荡(在最优值附近来回跳动)
    • 甚至溢出(参数值变得非常大)
    • 无法收敛

学习率调度#

学习率是经验值,可以在更新过程中逐步调整:

  • 学习率调度器(Learning Rate Scheduler)
    • 初始学习率较大,快速接近最优值
    • 逐渐减小学习率,精细调整
    • 常见策略:阶梯衰减、指数衰减、余弦退火等

示例

# 每10个epoch将学习率乘以0.1
scheduler = StepLR(optimizer, step_size=10, gamma=0.1)

代码实现#

PyTorch实现#

1. 手动实现单层感知机#

import torch
import torch.nn as nn

# 定义单层感知机
class SingleLayerPerceptron(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(SingleLayerPerceptron, self).__init__()
        self.linear = nn.Linear(input_dim, output_dim)
        self.activation = nn.Sigmoid()  # 激活函数
    
    def forward(self, x):
        z = self.linear(x) # x为张量,经过全连接层赋值给z
        a = self.activation(z)
        return a

# 使用示例
model = SingleLayerPerceptron(input_dim=10, output_dim=1)
x = torch.randn(32, 10)  # batch_size=32
output = model(x) 

2. 多层感知机#

class MultiLayerPerceptron(nn.Module):
    def __init__(self, input_dim, hidden_dims, output_dim):
        super(MultiLayerPerceptron, self).__init__()
        
        layers = []
        prev_dim = input_dim
        
        # 构建隐藏层
        for hidden_dim in hidden_dims:
            layers.append(nn.Linear(prev_dim, hidden_dim))
            layers.append(nn.ReLU())  # 激活函数
            prev_dim = hidden_dim
        
        # 输出层
        layers.append(nn.Linear(prev_dim, output_dim))
        
        self.network = nn.Sequential(*layers)
    
    def forward(self, x):
        return self.network(x)

# 使用示例
model = MultiLayerPerceptron(
    input_dim=784,
    hidden_dims=[128, 64],
    output_dim=10
)

x = torch.randn(32, 784)
output = model(x)  # [32, 10]

3. 使用Sequential简化#

model = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 64),
    nn.ReLU(),
    nn.Linear(64, 10)
)

参数初始化#

def init_weights(m):
    if isinstance(m, nn.Linear):
        # Xavier初始化
        nn.init.xavier_uniform_(m.weight)
        nn.init.zeros_(m.bias)

model.apply(init_weights)

参数统计#

def count_parameters(model):
    return sum(p.numel() for p in model.parameters() if p.requires_grad)

print(f"参数数量: {count_parameters(model):,}")

总结#

  1. 单层感知机:最简单的神经网络,只能处理线性问题
  2. 多层感知机:通过堆叠层,可以学习非线性关系
  3. 前向传播:数据从输入到输出的流动过程
  4. 激活函数:引入非线性,增强表达能力
  5. 深度网络:层次化特征学习,参数效率更高

关键要点

  • 神经网络通过多层变换学习复杂模式
  • 每层提取不同抽象级别的特征
  • 深度网络通常比浅层网络更高效

下一步:学习反向传播算法,了解如何训练神经网络。