第1周 神经网络基石: 从零构建你的第一个模型
欢迎来到课程的第一周!本周我们将一起揭开神经网络的神秘面纱,从最基础的概念入手,逐步带你构建并训练你的第一个神经网络模型。无论你之前的背景如何,本周的学习都将为你后续深入探索科学计算中的深度学习应用打下坚实的基础。
1. 课程导览与期望 (Course Overview & Expectations)
1.1 课程核心目标
本课程旨在系统性地介绍深度学习在科学计算领域的核心技术与前沿应用。完成本课程后,你将能够:
- 理解并实现主流的深度学习模型,特别是针对物理信息神经网络 (PINNs) 和神经算子 (Neural Operators)。
- 掌握将这些模型应用于解决偏微分方程 (PDEs)、反问题、多尺度建模等科学计算问题的关键方法。
- 培养独立进行相关领域科研探索、文献阅读、实验设计与分析、以及初步论文撰写的能力。
- 最终,形成一个与你研究兴趣相关的初步研究项目。
1.2 学习路径概览
我们将遵循一条循序渐进的学习路径:
- 神经网络基础 (本周):从神经元到多层感知机,理解训练机制。
- PINN核心技术:学习如何将物理规律融入神经网络。
- PINN实战与高级技巧:动手实践并掌握提升模型性能的方法。
- 神经算子 (FNO, DeepONet):学习更高级的算子学习框架。
- 其他相关深度学习模型:拓展视野,了解CNN, RNN, Transformer等在科学计算中的应用。
1.3 主要学习模块
- 理论讲解与数学推导
- 代码实践与案例分析
- 文献阅读与前沿追踪
- 项目构思与逐步实现
- 学术交流与研讨
1.7 课程所需准备
- 数学基础: 微积分、线性代数、概率论基础。
- 编程基础: 熟练掌握Python编程。
- 软件环境:
- Python 3.x
- PyTorch (本课程将主要使用PyTorch进行演示)
- Jupyter Notebook 或其他Python IDE
- (可选) LaTeX 编辑器,用于报告和论文写作。
2. 机器学习与神经网络入门 (Introduction to Machine Learning & Neural Networks)
2.1 机器学习基本概念
-
什么是机器学习 (Machine Learning, ML)? 机器学习是人工智能的一个分支,其核心思想是让计算机系统利用数据进行“学习”,从而在没有被显式编程的情况下完成特定任务。它通过算法分析大量数据,识别模式,并基于这些模式做出预测或决策。
-
机器学习的类型:
- 监督学习 (Supervised Learning): 给定一组输入数据和对应的期望输出(标签),模型学习从输入到输出的映射关系。例如,图像分类、房价预测。这是神经网络最常用的学习方式。
- 无监督学习 (Unsupervised Learning): 给定一组输入数据,但没有对应的期望输出,模型学习数据本身的结构或模式。例如,聚类、降维。
- 强化学习 (Reinforcement Learning): 模型(智能体)通过与环境交互来学习,目标是最大化累积奖励。例如,机器人控制、棋类游戏。
-
核心术语:
- 特征 (Features): 描述输入数据的属性。例如,在房价预测中,房屋的面积、房间数量是特征。
- 标签 (Labels): 在监督学习中,与输入数据对应的期望输出。例如,房价。
- 模型 (Model): 从数据中学习到的映射函数或模式表示。
- 训练 (Training): 使用训练数据调整模型参数以使其能够准确预测的过程。
- 推理/预测 (Inference/Prediction): 使用训练好的模型对新数据进行预测。
- 过拟合 (Overfitting): 模型在训练数据上表现很好,但在未见过的测试数据上表现差。通常因为模型过于复杂或训练数据不足。
- 欠拟合 (Underfitting): 模型在训练数据上表现就不好,未能捕捉到数据的基本模式。通常因为模型过于简单。
2.2 神经网络入门 (Introduction to Neural Networks)
神经网络(Neural Networks, NNs),也称为人工神经网络(Artificial Neural Networks, ANNs),其灵感来源于生物神经系统处理信息的方式。
-
生物神经元与人工神经元:
- 生物神经元通过树突接收信号,在细胞体中处理,并通过轴突传递信号给其他神经元。
- 人工神经元(或称“节点”、“单元”)是这一过程的简化数学模型。它接收多个输入,对这些输入进行加权求和,然后通过一个激活函数产生输出。
图1: 一个简单的人工神经网络结构示意图
* 感知机 (Perceptron): 感知机是最早的、最简单的神经网络模型,由Frank Rosenblatt在1957年提出。它是一个单层神经网络,通常用于二分类问题。
* 输入:<span class="math-inline">x\\\_1, x\\\_2, \.\.\., x\\\_n</span>* 权重:<span class="math-inline">w\\\_1, w\\\_2, \.\.\., w\\\_n</span>* 偏置:<span class="math-inline">b</span>* 加权和:<span class="math-inline">z \= \\\\sum\\\_\{i\=1\}^\{n\} w\\\_i x\\\_i \+ b \= \\\\mathbf\{w\} \\\\cdot \\\\mathbf\{x\} \+ b</span>* 激活函数:通常是一个阶跃函数 (Step function),例如如果 <span class="math-inline">z \\\> 0</span> 输出1,否则输出0。感知机的局限性在于它只能解决线性可分的问题(例如,无法解决XOR异或问题)。
-
多层感知机 (Multi-Layer Perceptron, MLP): 为了克服感知机的局限性,引入了多层感知机。MLP至少包含三个层次:
- 输入层 (Input Layer): 接收原始输入数据。神经元数量通常等于输入数据的特征维度。
- 隐藏层 (Hidden Layer(s)): 位于输入层和输出层之间,可以有一层或多层。隐藏层使得网络能够学习更复杂的非线性关系。
- 输出层 (Output Layer): 产生最终的预测结果。神经元数量和激活函数取决于具体的任务(例如,回归任务通常是一个神经元,无激活或线性激活;二分类任务通常是一个神经元配合Sigmoid激活;多分类任务通常是N个神经元配合Softmax激活)。
-
-
-
-
-
-
常用优化算法简介: 除了标准的梯度下降 (Batch Gradient Descent),还有一些更高级的优化算法,它们通常能提供更快的收敛速度和更好的性能:
- 随机梯度下降 (Stochastic Gradient Descent, SGD): 每次更新只使用一个样本来计算梯度。速度快,但梯度估计噪声大。
- 小批量梯度下降 (Mini-batch Gradient Descent): 每次更新使用一小批样本 (e.g., 32, 64, 128 个样本) 计算梯度。是实践中最常用的方法,平衡了计算效率和梯度估计的准确性。
- 动量 (Momentum): 引入动量项,模拟物理中物体运动的惯性,帮助加速SGD在相关方向上的下降并抑制振荡。
- AdaGrad (Adaptive Gradient Algorithm): 对不同参数使用不同的学习率,对稀疏特征友好。
- RMSprop (Root Mean Square Propagation): 也是一种自适应学习率方法,解决了AdaGrad学习率急剧下降的问题。
- Adam (Adaptive Moment Estimation): 结合了动量和RMSprop的思想,是目前非常流行且效果通常较好的优化器。
-
-
训练周期 (Epochs) 和批次 (Batches):
- 批次大小 (Batch Size): 在一次训练迭代(即一次参数更新)中,用于计算梯度的样本数量。
- 迭代 (Iteration): 完成一次参数更新的过程。
- 周期 (Epoch): 整个训练数据集中的所有样本都参与了一次前向传播和反向传播的过程。 如果训练集有 N 个样本,批次大小为 B,那么一个周期包含 N/B 次迭代。
3. 基础网络架构与实践 (Basic Network Architectures & Practice)
3.2 代码实现步骤 (PyTorch)
Python
# 1. 导入必要的库
import torch
import torch.nn as nn # 神经网络模块
import torch.optim as optim # 优化器模块
import numpy as np
import matplotlib.pyplot as plt# 设置 matplotlib 样式以获得更美观的图像
plt.style.use('seaborn-v0_8-whitegrid')# 为了结果可复现,设置随机种子
torch.manual_seed(42)
np.random.seed(42)# 2. 准备数据
# 生成 x 值,例如在 [-10, 10] 区间内取100个点
X_numpy = np.linspace(-10, 10, 100).reshape(-1, 1) # (100, 1)
# 计算对应的 y 值
y_numpy = X_numpy * np.sin(X_numpy) # (100, 1)# 将 NumPy 数组转换为 PyTorch张量 (Tensor)
# PyTorch 默认使用 float32
X_train = torch.tensor(X_numpy, dtype=torch.float32)
y_train = torch.tensor(y_numpy, dtype=torch.float32)# 3. 定义网络模型
class SimpleMLP(nn.Module):def __init__(self, input_size, hidden_size1, hidden_size2, output_size):super(SimpleMLP, self).__init__() # 调用父类的构造函数# 定义网络层self.fc1 = nn.Linear(input_size, hidden_size1) # 第一个全连接层 (输入层 -> 隐藏层1)self.relu1 = nn.ReLU() # 第一个ReLU激活函数self.fc2 = nn.Linear(hidden_size1, hidden_size2) # 第二个全连接层 (隐藏层1 -> 隐藏层2)self.relu2 = nn.ReLU() # 第二个ReLU激活函数self.fc3 = nn.Linear(hidden_size2, output_size) # 第三个全连接层 (隐藏层2 -> 输出层)def forward(self, x):# 定义前向传播逻辑out = self.fc1(x)out = self.relu1(out)out = self.fc2(out)out = self.relu2(out)out = self.fc3(out)return out# 4. 实例化模型、损失函数、优化器
input_dim = 1 # 输入特征维度 (x)
hidden_dim1 = 64 # 第一个隐藏层神经元数量
hidden_dim2 = 32 # 第二个隐藏层神经元数量
output_dim = 1 # 输出维度 (y)model = SimpleMLP(input_dim, hidden_dim1, hidden_dim2, output_dim)
print("模型结构:")
print(model)# 定义损失函数 (均方误差损失)
criterion = nn.MSELoss()# 定义优化器 (Adam优化器)
learning_rate = 0.01
optimizer = optim.Adam(model.parameters(), lr=learning_rate)# 5. 训练循环
num_epochs = 2000 # 训练周期数
losses = [] # 用于记录每个周期的损失值for epoch in range(num_epochs):# 前向传播: 计算预测值y_pred = model(X_train)# 计算损失loss = criterion(y_pred, y_train)losses.append(loss.item()) # .item() 获取标量值# 清零梯度 (非常重要,否则梯度会累积)optimizer.zero_grad()# 反向传播: 计算梯度loss.backward()# 更新参数optimizer.step()if (epoch + 1) % 200 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.6f}')# 6. 模型评估/可视化
# 将模型设置为评估模式 (对于某些层如Dropout, BatchNorm是必要的,这里简单MLP影响不大)
model.eval()with torch.no_grad(): # 在评估时不需要计算梯度y_predicted_final = model(X_train)# 绘制结果
plt.figure(figsize=(10, 6))
plt.plot(X_numpy, y_numpy, 'b-', label='Actual Function: $x \sin(x)$')
plt.plot(X_numpy, y_predicted_final.numpy(), 'r--', label='MLP Prediction')
plt.title('Function Approximation using MLP')
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.legend()
plt.grid(True)
plt.show()# 绘制损失曲线
plt.figure(figsize=(10, 6))
plt.plot(losses)
plt.title('Training Loss over Epochs')
plt.xlabel('Epoch')
plt.ylabel('MSE Loss')
plt.grid(True)
plt.show()print(f"Final training loss: {losses[-1]:.6f}")
3.3 关键代码解读
torch.nn.Module
: PyTorch中所有神经网络模块的基类。自定义模型时需要继承它,并实现__init__
(定义网络层) 和forward
(定义数据如何通过网络) 方法。nn.Linear(in_features, out_features)
: 创建一个全连接层(也叫线性层)。in_features
是输入神经元数量,out_features
是输出神经元数量。它会自动初始化权重和偏置。nn.ReLU()
: 创建一个ReLU激活函数对象。model(X_train)
: 调用模型的forward
方法进行前向传播。nn.MSELoss()
: 均方误差损失函数。optim.Adam(model.parameters(), lr=learning_rate)
: Adam优化器。model.parameters()
会告诉优化器模型中所有需要训练的参数。lr
是学习率。optimizer.zero_grad()
: 在每次迭代开始时清除之前计算的梯度。因为PyTorch默认会累积梯度。loss.backward()
: 执行反向传播,计算当前损失关于所有可训练参数的梯度。optimizer.step()
: 根据loss.backward()
计算得到的梯度来更新模型的参数。model.eval()
和with torch.no_grad():
: 在评估或推理阶段,通常会将模型设置为评估模式,并关闭梯度计算,以节省内存和计算,并确保某些特定层(如Dropout, BatchNorm)的行为正确。
通过运行上述代码,你将看到一个MLP如何逐步学习拟合给定的函数,并且损失值如何随着训练周期的增加而降低。