神经网络框架代码详细讲解

神经网络框架代码详细讲解

本文分部分详细讲解这个神经网络框架的代码,方便理解每个组件的原理和作用。

完整代码如下:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons, make_circles, make_blobs
import tkinter as tk
from tkinter import ttk
import matplotlib

matplotlib.use('TkAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans', 'Arial Unicode MS', 'Microsoft YaHei']
# matplotlib.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

class NeuralNetwork:
    """一个简单但完整的神经网络框架"""

    def __init__(self, layers, learning_rate=0.1):
        """
        初始化神经网络

        参数:
        layers: 列表,如[2, 4, 4, 1]表示2个输入,两个4个神经元的隐藏层,1个输出
        learning_rate: 学习率
        """
        self.layers = layers
        self.lr = learning_rate
        self.params = {}
        self.history = {'loss': [], 'accuracy': []}

        # 初始化权重和偏置
        np.random.seed(42)
        for i in range(1, len(layers)):
            # Xavier/Glorot初始化
            scale = np.sqrt(2.0 / layers[i - 1])
            self.params[f'W{i}'] = np.random.randn(layers[i - 1], layers[i]) * scale
            self.params[f'b{i}'] = np.zeros((1, layers[i]))

    def relu(self, x):
        """ReLU激活函数"""
        return np.maximum(0, x)

    def relu_derivative(self, x):
        """ReLU的导数"""
        return (x > 0).astype(float)

    def sigmoid(self, x):
        """Sigmoid激活函数"""
        return 1 / (1 + np.exp(-np.clip(x, -500, 500)))

    def sigmoid_derivative(self, x):
        """Sigmoid的导数"""
        sig = self.sigmoid(x)
        return sig * (1 - sig)

    def tanh(self, x):
        """Tanh激活函数"""
        return np.tanh(x)

    def tanh_derivative(self, x):
        """Tanh的导数"""
        return 1 - np.tanh(x) ** 2

    def softmax(self, x):
        """Softmax激活函数"""
        exp_x = np.exp(x - np.max(x, axis=1, keepdims=True))
        return exp_x / np.sum(exp_x, axis=1, keepdims=True)

    def forward(self, X, activation='relu'):
        """前向传播"""
        cache = {'A0': X}
        L = len(self.layers) - 1

        # 隐藏层的前向传播
        for i in range(1, L):
            W = self.params[f'W{i}']
            b = self.params[f'b{i}']
            Z = np.dot(cache[f'A{i - 1}'], W) + b

            # 选择激活函数
            if activation == 'relu':
                cache[f'Z{i}'] = Z
                cache[f'A{i}'] = self.relu(Z)
            elif activation == 'sigmoid':
                cache[f'Z{i}'] = Z
                cache[f'A{i}'] = self.sigmoid(Z)
            elif activation == 'tanh':
                cache[f'Z{i}'] = Z
                cache[f'A{i}'] = self.tanh(Z)

        # 输出层(使用sigmoid进行二分类)
        W_out = self.params[f'W{L}']
        b_out = self.params[f'b{L}']
        Z_out = np.dot(cache[f'A{L - 1}'], W_out) + b_out
        cache[f'Z{L}'] = Z_out
        cache[f'A{L}'] = self.sigmoid(Z_out)

        return cache

    def compute_loss(self, y_pred, y_true):
        """计算二元交叉熵损失"""
        m = y_true.shape[0]
        # 添加小值防止log(0)
        loss = -np.mean(y_true * np.log(y_pred + 1e-8) +
                        (1 - y_true) * np.log(1 - y_pred + 1e-8))
        return loss

    def backward(self, cache, y, activation='relu'):
        """反向传播"""
        grads = {}
        m = y.shape[0]
        L = len(self.layers) - 1

        # 输出层的梯度
        dA = cache[f'A{L}'] - y
        grads[f'dW{L}'] = np.dot(cache[f'A{L - 1}'].T, dA) / m
        grads[f'db{L}'] = np.sum(dA, axis=0, keepdims=True) / m

        # 隐藏层的梯度(反向传播)
        for i in reversed(range(1, L)):
            # 计算dZ
            if activation == 'relu':
                dZ = np.dot(dA, self.params[f'W{i + 1}'].T) * self.relu_derivative(cache[f'Z{i}'])
            elif activation == 'sigmoid':
                dZ = np.dot(dA, self.params[f'W{i + 1}'].T) * self.sigmoid_derivative(cache[f'Z{i}'])
            elif activation == 'tanh':
                dZ = np.dot(dA, self.params[f'W{i + 1}'].T) * self.tanh_derivative(cache[f'Z{i}'])

            # 计算dW和db
            grads[f'dW{i}'] = np.dot(cache[f'A{i - 1}'].T, dZ) / m
            grads[f'db{i}'] = np.sum(dZ, axis=0, keepdims=True) / m
            dA = dZ

        return grads

    def update_params(self, grads):
        """更新参数(梯度下降)"""
        L = len(self.layers) - 1
        for i in range(1, L + 1):
            self.params[f'W{i}'] -= self.lr * grads[f'dW{i}']
            self.params[f'b{i}'] -= self.lr * grads[f'db{i}']

    def train(self, X, y, epochs=1000, activation='relu', batch_size=32):
        """训练神经网络"""
        n_samples = X.shape[0]
        L = len(self.layers) - 1  # 输出层的索引

        for epoch in range(epochs):
            # 随机打乱数据
            indices = np.random.permutation(n_samples)
            X_shuffled = X[indices]
            y_shuffled = y[indices]

            # 小批量训练
            for start in range(0, n_samples, batch_size):
                end = min(start + batch_size, n_samples)
                X_batch = X_shuffled[start:end]
                y_batch = y_shuffled[start:end]

                # 前向传播
                cache = self.forward(X_batch, activation)

                # 反向传播
                grads = self.backward(cache, y_batch, activation)

                # 更新参数
                self.update_params(grads)

            # 每100个epoch记录一次损失和准确率
            if epoch % 100 == 0 or epoch == epochs - 1:
                cache = self.forward(X, activation)
                y_pred = cache[f'A{L}']  # 修复这里:使用正确的键名
                loss = self.compute_loss(y_pred, y)
                accuracy = np.mean((y_pred > 0.5) == y)

                self.history['loss'].append(loss)
                self.history['accuracy'].append(accuracy)

                if epoch % 500 == 0:
                    print(f"Epoch {epoch}: Loss = {loss:.4f}, Accuracy = {accuracy:.4f}")

        print(f"训练完成!最终准确率: {self.history['accuracy'][-1]:.4f}")

    def predict(self, X, activation='relu'):
        """预测"""
        cache = self.forward(X, activation)
        L = len(self.layers) - 1
        return (cache[f'A{L}'] > 0.5).astype(int), cache[f'A{L}']

    def visualize_decision_boundary(self, X, y, resolution=100):
        """可视化决策边界"""
        # 创建网格
        x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
        y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
        xx, yy = np.meshgrid(np.linspace(x_min, x_max, resolution),
                             np.linspace(y_min, y_max, resolution))

        # 预测整个网格
        grid_points = np.c_[xx.ravel(), yy.ravel()]
        _, probs = self.predict(grid_points)

        # 创建图形
        fig, axes = plt.subplots(2, 2, figsize=(12, 10))

        # 1. 决策边界
        ax = axes[0, 0]
        probs_grid = probs.reshape(xx.shape)
        contour = ax.contourf(xx, yy, probs_grid, levels=20, cmap='RdBu_r', alpha=0.8)
        ax.scatter(X[:, 0], X[:, 1], c=y.flatten(), cmap='bwr', edgecolors='k', s=50)
        ax.set_xlabel('特征1')
        ax.set_ylabel('特征2')
        ax.set_title('神经网络决策边界')
        plt.colorbar(contour, ax=ax)

        # 2. 损失曲线
        ax = axes[0, 1]
        ax.plot(self.history['loss'], 'b-', linewidth=2)
        ax.set_xlabel('Epoch (每100个)')
        ax.set_ylabel('损失')
        ax.set_title('训练损失曲线')
        ax.grid(True, alpha=0.3)

        # 3. 准确率曲线
        ax = axes[1, 0]
        ax.plot(self.history['accuracy'], 'g-', linewidth=2)
        ax.set_xlabel('Epoch (每100个)')
        ax.set_ylabel('准确率')
        ax.set_title('训练准确率曲线')
        ax.grid(True, alpha=0.3)
        ax.set_ylim([0, 1.1])

        # 4. 网络结构示意图
        ax = axes[1, 1]
        ax.axis('off')

        # 绘制网络结构
        layer_sizes = self.layers
        v_spacing = 1.0 / max(layer_sizes)
        h_spacing = 1.0 / len(layer_sizes)

        # 绘制神经元
        for i, layer_size in enumerate(layer_sizes):
            layer_top = v_spacing * (layer_size - 1) / 2.0
            for j in range(layer_size):
                x = i * h_spacing + 0.1
                y = layer_top - j * v_spacing + 0.5
                circle = plt.Circle((x, y), radius=0.03, color='blue', alpha=0.6)
                ax.add_patch(circle)

                # 添加层标签
                if j == 0:
                    layer_name = ['输入层', '隐藏层', '输出层'][min(i, 2)]
                    if i == len(layer_sizes) - 1 and len(layer_sizes) > 3:
                        layer_name = '输出层'
                    ax.text(x, 0.9, f'{layer_name}\n{layer_size}个神经元',
                            ha='center', fontsize=10)

        # 绘制连接线(示例)
        for i in range(len(layer_sizes) - 1):
            for j in range(layer_sizes[i]):
                for k in range(layer_sizes[i + 1]):
                    x1 = i * h_spacing + 0.1 + 0.03
                    y1 = (v_spacing * (layer_sizes[i] - 1) / 2.0) - j * v_spacing + 0.5
                    x2 = (i + 1) * h_spacing + 0.1 - 0.03
                    y2 = (v_spacing * (layer_sizes[i + 1] - 1) / 2.0) - k * v_spacing + 0.5
                    ax.plot([x1, x2], [y1, y2], 'gray', alpha=0.2)

        ax.set_xlim(0, 1)
        ax.set_ylim(0, 1)
        ax.set_title('网络结构示意图')

        plt.tight_layout()
        plt.show()

    def get_weights_visualization(self):
        """可视化权重分布"""
        num_layers = len(self.layers) - 1
        if num_layers == 0:
            return

        if num_layers == 1:
            fig, ax = plt.subplots(figsize=(8, 4))
            axes = [ax]
        else:
            fig, axes = plt.subplots(1, num_layers, figsize=(15, 4))

        for i in range(1, num_layers + 1):
            ax = axes[i - 1] if num_layers > 1 else axes
            weights = self.params[f'W{i}']

            # 绘制权重热力图
            im = ax.imshow(weights, cmap='coolwarm', aspect='auto')
            ax.set_xlabel(f'层{i}输出')
            ax.set_ylabel(f'层{i - 1}输入')
            ax.set_title(f'权重矩阵 W{i} ({weights.shape[0]}×{weights.shape[1]})')
            plt.colorbar(im, ax=ax)

        plt.tight_layout()
        plt.show()


def simple_demo():
    """简单的演示示例"""
    print("=" * 50)
    print("神经网络框架演示")
    print("=" * 50)

    # 1. 创建数据集
    print("\n1. 创建月亮数据集...")
    X, y = make_moons(n_samples=300, noise=0.2, random_state=42)
    y = y.reshape(-1, 1)  # 重塑为列向量

    # 2. 创建神经网络
    print("2. 初始化神经网络...")
    nn = NeuralNetwork(layers=[2, 8, 8, 1], learning_rate=0.1)

    print(f"   网络结构: {nn.layers}")
    print(
        f"   总参数数量: {sum([np.prod(nn.params[f'W{i}'].shape) + np.prod(nn.params[f'b{i}'].shape) for i in range(1, len(nn.layers))])}")

    # 3. 训练网络
    print("\n3. 训练神经网络...")
    nn.train(X, y, epochs=2000, activation='relu')

    # 4. 预测和评估
    predictions, probs = nn.predict(X)
    accuracy = np.mean(predictions.flatten() == y.flatten())
    print(f"\n4. 模型性能:")
    print(f"   训练准确率: {accuracy:.2%}")

    # 5. 可视化
    print("\n5. 生成可视化...")
    nn.visualize_decision_boundary(X, y)

    # 6. 显示权重
    print("6. 显示权重分布...")
    nn.get_weights_visualization()

    # 7. 演示前向传播过程
    print("\n7. 前向传播示例:")
    sample = X[:5]  # 前5个样本
    print(f"   输入样本形状: {sample.shape}")

    cache = nn.forward(sample)
    L = len(nn.layers) - 1
    print(f"   输出预测值: {cache[f'A{L}'][:5].flatten()}")
    print(f"   真实标签: {y[:5].flatten()}")

    return nn


# 运行演示
if __name__ == "__main__":
    # 方式1: 运行简单演示
    print("运行简单演示...")
    model = simple_demo()

    # 方式2: 运行GUI应用 (取消注释以下行)
    # print("\n\n启动GUI应用...")
    # app = NeuralNetworkGUI()
    # app.run()

一、整体架构概览

这个神经网络框架实现了:

  1. 完整的前向传播
  2. 完整的反向传播(自动微分)
  3. 多种激活函数
  4. 梯度下降优化
  5. 可视化工具

框架的核心是 通过数学公式(矩阵运算)实现数据变换,通过梯度下降最小化损失函数

二、核心数学原理

2.1 神经网络基本公式

神经网络的核心是线性变换 + 非线性激活:

复制代码
Z[l] = W[l] · A[l-1] + b[l]    # 线性变换
A[l] = g(Z[l])                  # 非线性激活

其中:

  • W 是权重矩阵
  • b 是偏置向量
  • g() 是激活函数

2.2 损失函数(Loss Function)

我们使用二元交叉熵损失,用于二分类问题:

复制代码
Loss = -1/m * Σ[y*log(ŷ) + (1-y)*log(1-ŷ)]
  • y:真实标签(0或1)
  • :预测概率(0到1之间)
  • m:样本数量

三、代码逐部分详解

3.1 神经网络类初始化

python 复制代码
class NeuralNetwork:
    def __init__(self, layers, learning_rate=0.1):
        self.layers = layers  # 网络结构,如[2, 8, 8, 1]
        self.lr = learning_rate  # 学习率
        self.params = {}  # 存储权重和偏置
        self.history = {'loss': [], 'accuracy': []}  # 训练历史

关键点

  • layers 定义了网络的架构
  • 输入层:layers[0] 个神经元(对应特征数量)
  • 输出层:layers[-1] 个神经元(二分类问题为1)
  • 隐藏层:中间的数字表示神经元数量

3.2 权重初始化(Xavier初始化)

python 复制代码
# Xavier/Glorot初始化
scale = np.sqrt(2.0 / layers[i-1])
self.params[f'W{i}'] = np.random.randn(layers[i-1], layers[i]) * scale
self.params[f'b{i}'] = np.zeros((1, layers[i]))

数学原理

  • 权重不能全为0,也不能太大或太小
  • Xavier初始化:从均值为0、方差为 sqrt(2/n_input) 的正态分布中采样
  • 这有助于避免梯度消失/爆炸问题

为什么需要随机初始化

  • 如果所有权重相同,所有神经元会学到相同的特征
  • 随机性打破对称性,让不同神经元学习不同的特征

3.3 激活函数

ReLU(修正线性单元)
python 复制代码
def relu(self, x):
    return np.maximum(0, x)  # 小于0的部分变为0,大于0的部分保持不变

特点

  • 计算简单,速度快
  • 解决梯度消失问题(在正区间梯度为1)
  • 缺点:负数部分完全失活("死亡ReLU"问题)
Sigmoid
python 复制代码
def sigmoid(self, x):
    return 1 / (1 + np.exp(-np.clip(x, -500, 500)))

数学公式σ(x) = 1 / (1 + e^(-x))

特点

  • 将输出压缩到(0, 1)之间
  • 常用于二分类问题的输出层
  • 缺点:容易导致梯度消失(两端梯度接近0)
Tanh(双曲正切)
python 复制代码
def tanh(self, x):
    return np.tanh(x)  # (e^x - e^(-x)) / (e^x + e^(-x))

特点

  • 输出范围(-1, 1),均值为0
  • 相比sigmoid,收敛更快
  • 同样存在梯度消失问题

3.4 前向传播(Forward Propagation)

python 复制代码
def forward(self, X, activation='relu'):
    cache = {'A0': X}  # 缓存每一层的输出
    L = len(self.layers) - 1  # 总层数
    
    # 隐藏层的前向传播
    for i in range(1, L):
        W = self.params[f'W{i}']
        b = self.params[f'b{i}']
        Z = np.dot(cache[f'A{i-1}'], W) + b  # 线性变换
        
        # 激活函数
        if activation == 'relu':
            cache[f'Z{i}'] = Z
            cache[f'A{i}'] = self.relu(Z)
    
    # 输出层(使用sigmoid)
    W_out = self.params[f'W{L}']
    b_out = self.params[f'b{L}']
    Z_out = np.dot(cache[f'A{L-1}'], W_out) + b_out
    cache[f'Z{L}'] = Z_out
    cache[f'A{L}'] = self.sigmoid(Z_out)  # 输出概率
    
    return cache

前向传播流程

复制代码
输入X → 线性变换 → 激活 → 线性变换 → 激活 → ... → 输出ŷ

为什么需要缓存

  • 反向传播需要用到前向传播的中间结果
  • cache 存储了每一层的 Z(线性输出)和 A(激活输出)

3.5 损失计算

python 复制代码
def compute_loss(self, y_pred, y_true):
    m = y_true.shape[0]
    # 添加小值防止log(0)
    loss = -np.mean(y_true * np.log(y_pred + 1e-8) + 
                   (1 - y_true) * np.log(1 - y_pred + 1e-8))
    return loss

为什么加 1e-8

  • 防止 log(0) 导致数值错误(无穷大)
  • 这是一个数值稳定性的技巧

3.6 反向传播(Backpropagation) - 核心!

反向传播是神经网络学习的核心机制 ,它使用链式法则计算梯度。

python 复制代码
def backward(self, cache, y, activation='relu'):
    grads = {}
    m = y.shape[0]
    L = len(self.layers) - 1
    
    # 1. 输出层的梯度(最关键的一步!)
    dA = cache[f'A{L}'] - y  # 损失对输出的导数
    
    # 权重和偏置的梯度
    grads[f'dW{L}'] = np.dot(cache[f'A{L-1}'].T, dA) / m
    grads[f'db{L}'] = np.sum(dA, axis=0, keepdims=True) / m
    
    # 2. 隐藏层的梯度(反向传播)
    for i in reversed(range(1, L)):
        # 计算dZ(链式法则的关键)
        if activation == 'relu':
            dZ = np.dot(dA, self.params[f'W{i+1}'].T) * self.relu_derivative(cache[f'Z{i}'])
        
        # 计算dW和db
        grads[f'dW{i}'] = np.dot(cache[f'A{i-1}'].T, dZ) / m
        grads[f'db{i}'] = np.sum(dZ, axis=0, keepdims=True) / m
        dA = dZ  # 传递给下一层
    
    return grads

反向传播的数学原理

对于输出层:

复制代码
dL/dW[L] = (A[L] - y) · A[L-1].T / m
dL/db[L] = sum(A[L] - y) / m

对于隐藏层(链式法则):

复制代码
dL/dZ[l] = (dL/dA[l]) * g'(Z[l])  # g'是激活函数的导数
dL/dW[l] = dL/dZ[l] · A[l-1].T / m
dL/db[l] = sum(dL/dZ[l]) / m

链式法则的直观理解

  • 将误差从输出层"反向传播"到输入层
  • 每层的梯度 = 后一层的梯度 × 当前层的激活函数导数

3.7 参数更新(梯度下降)

python 复制代码
def update_params(self, grads):
    L = len(self.layers) - 1
    for i in range(1, L + 1):
        self.params[f'W{i}'] -= self.lr * grads[f'dW{i}']
        self.params[f'b{i}'] -= self.lr * grads[f'db{i}']

梯度下降公式

复制代码
W = W - η * ∂L/∂W
b = b - η * ∂L/∂b

其中 η 是学习率,控制每次更新的步长。

3.8 训练循环

python 复制代码
def train(self, X, y, epochs=1000, activation='relu', batch_size=32):
    n_samples = X.shape[0]
    L = len(self.layers) - 1
    
    for epoch in range(epochs):
        # 随机打乱数据
        indices = np.random.permutation(n_samples)
        X_shuffled = X[indices]
        y_shuffled = y[indices]
        
        # 小批量训练(Mini-batch)
        for start in range(0, n_samples, batch_size):
            end = min(start + batch_size, n_samples)
            X_batch = X_shuffled[start:end]
            y_batch = y_shuffled[start:end]
            
            # 前向传播
            cache = self.forward(X_batch, activation)
            
            # 反向传播
            grads = self.backward(cache, y_batch, activation)
            
            # 更新参数
            self.update_params(grads)

训练的关键要素

  1. 随机打乱(Shuffling)

    • 防止模型学习到数据的顺序信息
    • 提高训练稳定性
  2. 小批量梯度下降(Mini-batch Gradient Descent)

    • 批量大小(batch_size)是超参数
    • 太大:内存需求高,收敛慢但稳定
    • 太小:噪声大,收敛快但不稳定
    • 常用值:32, 64, 128
  3. 学习率(Learning Rate)

    • 控制参数更新的步长
    • 太大:可能跳过最优解,甚至发散
    • 太小:收敛太慢,可能陷入局部最优

3.9 预测函数

python 复制代码
def predict(self, X, activation='relu'):
    cache = self.forward(X, activation)
    L = len(self.layers) - 1
    return (cache[f'A{L}'] > 0.5).astype(int), cache[f'A{L}']

为什么阈值是0.5

  • 对于二分类问题,sigmoid输出在0-1之间
  • 大于0.5预测为正类(1),否则为负类(0)

3.10 可视化工具

决策边界可视化
python 复制代码
def visualize_decision_boundary(self, X, y, resolution=100):
    # 创建网格点
    xx, yy = np.meshgrid(np.linspace(x_min, x_max, resolution),
                        np.linspace(y_min, y_max, resolution))
    
    # 预测整个网格
    grid_points = np.c_[xx.ravel(), yy.ravel()]
    _, probs = self.predict(grid_points)

原理

  1. 在特征空间创建密集的网格点
  2. 用训练好的模型预测每个点的类别
  3. 用颜色表示预测概率,形成决策边界
网络结构可视化
python 复制代码
# 绘制神经元连接
for i in range(len(layer_sizes) - 1):
    for j in range(layer_sizes[i]):
        for k in range(layer_sizes[i + 1]):
            ax.plot([x1, x2], [y1, y2], 'gray', alpha=0.2)

这展示了神经网络实际上是一个复杂的加权连接图

四、神经网络学习过程的直观解释

4.1 训练过程的三个阶段

  1. 初始化阶段

    python 复制代码
    # 随机初始化权重
    np.random.randn(layers[i-1], layers[i]) * scale
    • 决策边界是随机的
    • 准确率接近50%(随机猜测)
  2. 学习阶段

    复制代码
    Epoch 0: Loss = 0.6931, Accuracy = 0.5000
    Epoch 500: Loss = 0.4521, Accuracy = 0.7867
    Epoch 1000: Loss = 0.2103, Accuracy = 0.9100
    • 损失逐渐下降
    • 准确率逐渐上升
    • 决策边界逐渐拟合数据分布
  3. 收敛阶段

    复制代码
    Epoch 2000: Loss = 0.1205, Accuracy = 0.9533
    • 损失基本不再下降
    • 准确率趋于稳定
    • 决策边界基本确定

4.2 神经网络如何"学习"

  1. 前向传播:计算预测值
  2. 计算损失:比较预测值和真实值
  3. 反向传播:计算每个参数的梯度(误差贡献)
  4. 梯度下降:沿着梯度反方向更新参数

类比

  • 像一个人蒙着眼睛爬山(寻找最高点)
  • 每次用小棍子探周围的地面(计算梯度)
  • 向最陡的方向走一步(梯度下降)
  • 重复直到山顶(最小化损失)

五、关键概念总结

5.1 神经网络的核心思想

python 复制代码
# 整个神经网络可以简化为:
def neural_network(X):
    # 多层变换
    for layer in layers:
        X = activation(dot(X, W) + b)
    return X

本质:通过多层非线性变换,将输入数据映射到目标输出。

5.2 为什么需要深度?

  1. 特征层次结构

    • 浅层学习简单特征(边缘、颜色)
    • 深层组合简单特征为复杂特征(形状、物体)
  2. 表示能力

    • 理论证明:深层网络比浅层网络有更强的表示能力
    • 可以用更少的参数表示更复杂的函数

5.3 超参数的选择

python 复制代码
# 常见的超参数
layers = [2, 16, 16, 1]  # 网络结构
learning_rate = 0.1      # 学习率
epochs = 2000            # 训练轮数
batch_size = 32          # 批量大小
activation = 'relu'      # 激活函数

调参经验

  1. 先从简单网络开始
  2. 学习率通常尝试0.1, 0.01, 0.001
  3. 增加网络深度/宽度可以提高性能,但也可能过拟合
  4. 使用验证集选择最佳超参数

六、与Transformer的联系

虽然这个框架比Transformer简单得多,但核心思想相通:

  1. 都是参数化函数:通过权重矩阵实现数据变换
  2. 都使用梯度下降:通过反向传播优化参数
  3. 都有前向传播:输入→变换→输出
  4. 目标都是最小化损失函数

主要区别

  • 这个框架使用全连接层,Transformer使用自注意力层
  • 这个框架用于简单分类,Transformer用于序列任务
  • Transformer有更复杂的架构(编码器-解码器、多头注意力等)

七、扩展思考

7.1 如何改进这个框架?

  1. 添加优化器

    python 复制代码
    # 目前使用普通梯度下降
    # 可以添加Adam、RMSprop等
  2. 添加正则化

    python 复制代码
    # L2正则化:防止过拟合
    loss += lambda * sum(W**2)
  3. 添加批归一化

    python 复制代码
    # 加速训练,提高稳定性
    X_normalized = (X - mean) / sqrt(var + epsilon)

7.2 从框架到深度学习库

现代深度学习库(PyTorch、TensorFlow)的核心组件:

  1. 张量(Tensor):多维数组,支持GPU加速
  2. 自动微分(Autograd):自动计算梯度
  3. 计算图(Computation Graph):记录运算过程
  4. 优化器(Optimizer):各种梯度下降变体
  5. 层(Layer):预定义的网络组件

我们这个简单框架包含了所有这些核心概念的简化版本。

八、实践建议

  1. 自己动手修改

    • 尝试不同的激活函数
    • 调整网络结构
    • 可视化权重变化
  2. 观察训练过程

    • 注意损失曲线的变化
    • 观察决策边界的形成过程
    • 理解梯度下降的实际效果
  3. 思考深度学习本质

    • 神经网络只是复杂的数学函数
    • 训练就是寻找函数的最佳参数
    • 所有深度学习模型都遵循这个基本范式

这个框架虽然简单,但包含了深度学习的核心思想。通过理解和修改这个代码,你可以真正掌握神经网络的工作原理,而不仅仅是调用库函数。

相关推荐
空山新雨后、1 小时前
小数据集训练 300 epoch 夸张吗?(讲清epoch step batch )
人工智能·深度学习·机器学习·batch
国际期刊-秋秋1 小时前
[SPIE] 2026年 物联网、智慧交通与智慧城市建设国际学术会议 (SCSD 2026)
人工智能·物联网·智慧城市·国际会议
DS随心转小程序1 小时前
【技术前瞻】Edge 浏览器深度集成 DS随心转:AI 搜索与笔记流转的一站式生产力革命
人工智能·笔记·edge·deepseek·ds随心转
雍凉明月夜1 小时前
⭐深度学习之目标检测yolo算法Ⅲ-YOLOv5(1)
深度学习·yolo·目标检测
无代码专家1 小时前
制造业设备巡检智能化转型:系统适配与降本增效方案
大数据·人工智能
天天讯通1 小时前
告别等待焦虑!AI Agent重构呼叫中心:从成本中心到价值引擎
人工智能·重构
说私域1 小时前
AI智能名片S2B2C商城小程序品牌诞生原因与发展历程分析
人工智能·小程序·流量运营
来两个炸鸡腿1 小时前
【Datawhale组队学习202601】Base-NLP task03 深入大模型架构
人工智能·学习·自然语言处理
大模型实验室Lab4AI2 小时前
AAAI 2026 | 西北工业大学提出 YOLO-IOD,实时增量目标检测新框架
人工智能·计算机视觉·目标跟踪