第三章:深度学习实战

14 阅读6分钟

第三章:深度学习实战

 

3.1 神经网络基础

 

深度学习是机器学习的一个重要分支,而神经网络是深度学习的核心。本章将带您深入了解神经网络的基本原理,从简单的感知机到复杂的深度网络,通过实际案例帮助您掌握深度学习的核心技术。

 

3.1.1 什么是神经网络?

 

神经网络是一种受人脑神经系统启发的计算模型,它由大量的相互连接的处理单元(神经元)组成,能够学习和模拟复杂的非线性关系。

 

神经元的基本结构

 

每个神经元可以看作是一个简单的计算单元,它接收多个输入信号,进行加权求和,然后通过激活函数产生输出:

 

数学表示:


output = activation(∑(input_i * weight_i) + bias)

 

组成部分:

  • 输入: 来自其他神经元或外部数据

  • 权重: 连接的强度,通过学习调整

  • 偏置: 调整神经元激活的阈值

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

 

神经网络的基本架构

 

单层神经网络:

  • 只有一个输入层和一个输出层

  • 可以解决线性可分的问题

  • 计算简单但表达能力有限

 

多层神经网络:

  • 包含输入层、隐藏层和输出层

  • 隐藏层越多,网络越深

  • 能够学习更复杂的非线性关系

 

3.1.2 激活函数

 

激活函数是神经网络中非常重要的组成部分,它为网络引入非线性特性,使网络能够学习复杂的模式。

 

常用激活函数

 

Sigmoid函数:


f(x) = 1 / (1 + exp(-x))

特点:

  • 输出范围:0到1

  • 适用于二分类问题

  • 存在梯度消失问题

 

Tanh函数:


f(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))

特点:

  • 输出范围:-1到1

  • 零中心化

  • 仍然存在梯度消失问题

 

ReLU函数:


f(x) = max(0, x)

特点:

  • 计算简单

  • 缓解梯度消失问题

  • 存在神经元死亡问题

 

Leaky ReLU函数:


f(x) = max(0.01x, x)

特点:

  • 解决ReLU的神经元死亡问题

  • 保持简单计算

 

3.1.3 神经网络的前向传播

 

前向传播是神经网络的基本计算过程,信号从输入层经过隐藏层最终到达输出层。

 

前向传播步骤

 

步骤1: 输入层到隐藏层


hidden = activation(input * W1 + b1)

 

步骤2: 隐藏层到输出层


output = activation(hidden * W2 + b2)

 

步骤3: 计算损失


loss = loss_function(output, target)

 

示例代码

 


import numpy as np

import matplotlib.pyplot as plt

 

# 定义激活函数

def sigmoid(x):

    return 1 / (1 + np.exp(-x))

 

def relu(x):

    return np.maximum(0, x)

 

# 神经网络参数

input_size = 2

hidden_size = 4

output_size = 1

 

# 初始化权重和偏置

np.random.seed(42)

W1 = np.random.randn(input_size, hidden_size) * 0.01

b1 = np.zeros((1, hidden_size))

W2 = np.random.randn(hidden_size, output_size) * 0.01

b2 = np.zeros((1, output_size))

 

# 前向传播函数

def forward_propagation(X):

    # 输入层到隐藏层

    Z1 = np.dot(X, W1) + b1

    A1 = relu(Z1)

    

    # 隐藏层到输出层

    Z2 = np.dot(A1, W2) + b2

    A2 = sigmoid(Z2)

    

    return Z1, A1, Z2, A2

 

# 示例数据

X = np.array([[0.5, 0.3], [0.2, 0.8], [0.9, 0.1], [0.4, 0.6]])

 

# 前向传播

Z1, A1, Z2, A2 = forward_propagation(X)

 

print("输入数据:")

print(X)

print("\n隐藏层输出:")

print(A1)

print("\n输出层结果:")

print(A2)

 

3.1.4 神经网络的反向传播

 

反向传播是神经网络训练的核心算法,它通过计算损失函数对各个参数的梯度来更新网络的权重。

 

反向传播原理

 

梯度计算:

  • 从输出层开始,逐层计算梯度

  • 使用链式法则传播误差

  • 更新权重和偏置

 

反向传播步骤

 

步骤1: 计算输出层梯度


dZ2 = A2 - target

dW2 = (1/m) * np.dot(A1.T, dZ2)

db2 = (1/m) * np.sum(dZ2, axis=0, keepdims=True)

 

步骤2: 计算隐藏层梯度


dA1 = np.dot(dZ2, W2.T)

dZ1 = dA1 * (Z1 > 0)  # ReLU的导数

dW1 = (1/m) * np.dot(X.T, dZ1)

db1 = (1/m) * np.sum(dZ1, axis=0, keepdims=True)

 

步骤3: 参数更新


W1 = W1 - learning_rate * dW1

b1 = b1 - learning_rate * db1

W2 = W2 - learning_rate * dW2

b2 = b2 - learning_rate * db2

 

3.1.5 实战案例:手写数字识别

 

让我们通过一个经典的案例来理解神经网络的实际应用 - 手写数字识别。

 

项目概述

 

我们将使用MNIST数据集来训练一个简单的神经网络,实现手写数字的0-9识别。

 

数据加载和预处理

 


import tensorflow as tf

from tensorflow.keras.datasets import mnist

import numpy as np

 

# 加载数据集

(X_train, y_train), (X_test, y_test) = mnist.load_data()

 

# 数据预处理

X_train = X_train.reshape(-1, 28*28) / 255.0

X_test = X_test.reshape(-1, 28*28) / 255.0

 

# 标准化

X_train = X_train.astype(np.float32)

X_test = X_test.astype(np.float32)

 

# 标签转换为one-hot编码

y_train = tf.keras.utils.to_categorical(y_train, 10)

y_test = tf.keras.utils.to_categorical(y_test, 10)

 

print(f"训练数据形状: {X_train.shape}")

print(f"测试数据形状: {X_test.shape}")

print(f"标签形状: {y_train.shape}")

 

构建神经网络模型

 


from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Dense, Dropout

 

# 构建模型

model = Sequential([

    Dense(512, activation='relu', input_shape=(784,)),

    Dropout(0.2),

    Dense(256, activation='relu'),

    Dropout(0.2),

    Dense(128, activation='relu'),

    Dense(10, activation='softmax')

])

 

# 编译模型

model.compile(optimizer='adam',

              loss='categorical_crossentropy',

              metrics=['accuracy'])

 

# 显示模型结构

model.summary()

 

训练模型

 


# 训练模型

history = model.fit(X_train, y_train,

                    batch_size=128,

                    epochs=10,

                    validation_split=0.2,

                    verbose=1)

 

# 评估模型

test_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)

print(f"测试准确率: {test_acc:.4f}")

 

模型预测和可视化

 


import matplotlib.pyplot as plt

 

# 选择测试集中的前10个样本

sample_images = X_test[:10]

sample_labels = np.argmax(y_test[:10], axis=1)

 

# 预测

predictions = model.predict(sample_images)

predicted_labels = np.argmax(predictions, axis=1)

 

# 显示结果

plt.figure(figsize=(12, 6))

for i in range(10):

    plt.subplot(2, 5, i+1)

    plt.imshow(sample_images[i].reshape(28, 28), cmap='gray')

    plt.title(f"True: {sample_labels[i]}\nPred: {predicted_labels[i]}")

    plt.axis('off')

plt.tight_layout()

plt.show()

 

# 显示训练过程

plt.figure(figsize=(12, 4))

plt.subplot(1, 2, 1)

plt.plot(history.history['accuracy'], label='Training Accuracy')

plt.plot(history.history['val_accuracy'], label='Validation Accuracy')

plt.title('Accuracy')

plt.legend()

 

plt.subplot(1, 2, 2)

plt.plot(history.history['loss'], label='Training Loss')

plt.plot(history.history['val_loss'], label='Validation Loss')

plt.title('Loss')

plt.legend()

plt.show()

 

3.1.6 神经网络调优技巧

 

在实际应用中,神经网络的调优是非常重要的。以下是一些常用的调优技巧:

 

超参数调优

 

学习率:

  • 太小:收敛慢

  • 太大:震荡不收敛

  • 建议:从0.001开始,尝试0.01、0.0001等

 

批量大小:

  • 太小:梯度估计不稳定

  • 太大:收敛速度慢

  • 建议:32、64、128、256等

 

网络深度:

  • 太浅:表达能力不足

  • 太深:梯度消失/爆炸

  • 建议:从2-3层开始,逐步增加

 

正则化技术

 

Dropout:

  • 随机丢弃一些神经元

  • 防止过拟合

  • 建议:0.2-0.5之间

 

L2正则化:

  • 惩罚大权重

  • 防止过拟合

  • 建议:0.001-0.01之间

 

激活函数选择

 

输出层:

  • 二分类:Sigmoid

  • 多分类:Softmax

  • 回归:Linear

 

隐藏层:

  • 默认:ReLU

  • 特殊情况:Leaky ReLU、ELU、Swish等

 


 

通过本节的学习,您应该已经掌握了神经网络的基本原理和实现方法。在下一节中,我们将介绍深度学习的主要框架,帮助您选择合适的工具进行深度学习开发。