核心知识点梳理
1. 神经网络(MLP)核心概念
表格
| 核心概念 | 作用与说明 |
|---|---|
| 梯度下降 | 优化核心:通过计算损失函数对参数的梯度,沿梯度负方向更新参数,最小化损失。衍生:批量梯度下降(BGD)、随机梯度下降(SGD)、小批量梯度下降(Mini-batch GD) |
| 激活函数 | 引入非线性:打破线性模型的局限性,让网络能拟合复杂关系。常用:ReLU(隐藏层)、Sigmoid(二分类输出)、Softmax(多分类输出) |
| 损失函数 | 评价模型预测误差:量化预测值与真实值的差距,是梯度下降的优化目标。常用:MSE(回归)、交叉熵损失(分类) |
| 优化器 | 梯度下降的工程实现:优化参数更新策略,加速收敛。常用:SGD、Adam(自适应学习率,最常用)、RMSprop |
| 神经网络结构 | MLP 核心:输入层→隐藏层(多层)→输出层,层与层之间全连接,隐藏层引入激活函数。 |
2. MLP 的核心特点
- 灵活封装:不同于机器学习模型的 "三行代码固定",MLP 可定制化维度多(层数、神经元数、激活函数、优化器、学习率等);
- 核心流程:定义网络结构→选择损失函数 / 优化器→训练(前向传播→计算损失→反向传播→参数更新)→评估。
python
pip install torch numpy scikit-learn matplotlib
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
# --------------------------
# 步骤1:数据准备与预处理
# --------------------------
# 加载乳腺癌分类数据集
data = load_breast_cancer()
X = data.data # 特征:30维
y = data.target # 标签:0/1(恶性/良性)
# 数据标准化(神经网络对特征尺度敏感,必须做)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 划分训练集/测试集
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42
)
# 转换为PyTorch张量(GPU/CPU兼容)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
X_train_tensor = torch.tensor(X_train, dtype=torch.float32).to(device)
y_train_tensor = torch.tensor(y_train, dtype=torch.float32).to(device)
X_test_tensor = torch.tensor(X_test, dtype=torch.float32).to(device)
y_test_tensor = torch.tensor(y_test, dtype=torch.float32).to(device)
# --------------------------
# 步骤2:定义MLP网络结构(核心:灵活定制)
# --------------------------
class MLPClassifier(nn.Module):
def __init__(self, input_dim=30, hidden_dims=[64, 32], output_dim=1):
super(MLPClassifier, self).__init__()
# 定义网络层(可灵活调整层数、神经元数)
layers = []
# 输入层→第一个隐藏层
layers.append(nn.Linear(input_dim, hidden_dims[0]))
layers.append(nn.ReLU()) # 激活函数(可替换为Sigmoid/Tanh)
layers.append(nn.Dropout(0.2)) # 正则化:防止过拟合(可选)
# 隐藏层之间(可灵活增加/减少隐藏层)
for i in range(1, len(hidden_dims)):
layers.append(nn.Linear(hidden_dims[i-1], hidden_dims[i]))
layers.append(nn.ReLU())
layers.append(nn.Dropout(0.2))
# 输出层(二分类:输出1维,搭配Sigmoid)
layers.append(nn.Linear(hidden_dims[-1], output_dim))
layers.append(nn.Sigmoid()) # 输出0-1概率
# 组合所有层
self.model = nn.Sequential(*layers)
def forward(self, x):
# 前向传播(核心:定义数据流动路径)
return self.model(x)
# --------------------------
# 步骤3:初始化模型/损失函数/优化器(灵活选择)
# --------------------------
# 1. 初始化模型(可调整隐藏层参数)
mlp = MLPClassifier(
input_dim=30,
hidden_dims=[128, 64, 32], # 灵活调整:比如改为[64](单隐藏层)
output_dim=1
).to(device)
# 2. 选择损失函数(二分类用BCELoss,多分类用CrossEntropyLoss,回归用MSELoss)
criterion = nn.BCELoss() # 二元交叉熵损失
# 3. 选择优化器(可替换为SGD/RMSprop,调整学习率)
optimizer = optim.Adam(
mlp.parameters(),
lr=0.001, # 学习率(核心超参数,可调整)
weight_decay=1e-5 # L2正则化(可选)
)
# --------------------------
# 步骤4:训练模型(核心:梯度下降流程)
# --------------------------
epochs = 100 # 训练轮数(可调整)
train_losses = []
test_losses = []
train_accs = []
test_accs = []
mlp.train() # 训练模式(启用Dropout)
for epoch in range(epochs):
# 前向传播
y_pred_train = mlp(X_train_tensor).squeeze() # 预测值
loss_train = criterion(y_pred_train, y_train_tensor) # 计算损失
# 反向传播 + 梯度下降(核心步骤)
optimizer.zero_grad() # 清空梯度(避免累积)
loss_train.backward() # 反向传播:计算梯度
optimizer.step() # 更新参数:梯度下降
# 验证阶段(无梯度计算)
mlp.eval() # 评估模式(关闭Dropout)
with torch.no_grad():
y_pred_test = mlp(X_test_tensor).squeeze()
loss_test = criterion(y_pred_test, y_test_tensor)
# 计算准确率(阈值0.5)
train_acc = accuracy_score(y_train, (y_pred_train.cpu().numpy() > 0.5).astype(int))
test_acc = accuracy_score(y_test, (y_pred_test.cpu().numpy() > 0.5).astype(int))
# 记录指标
train_losses.append(loss_train.item())
test_losses.append(loss_test.item())
train_accs.append(train_acc)
test_accs.append(test_acc)
# 打印进度
if (epoch + 1) % 10 == 0:
print(f"Epoch [{epoch+1}/{epochs}] | "
f"Train Loss: {loss_train.item():.4f} | "
f"Test Loss: {loss_test.item():.4f} | "
f"Train Acc: {train_acc:.4f} | "
f"Test Acc: {test_acc:.4f}")
# --------------------------
# 步骤5:结果可视化(分析训练过程)
# --------------------------
plt.figure(figsize=(12, 4))
# 损失曲线
plt.subplot(1, 2, 1)
plt.plot(train_losses, label="Train Loss")
plt.plot(test_losses, label="Test Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.title("Loss Curve")
plt.legend()
# 准确率曲线
plt.subplot(1, 2, 2)
plt.plot(train_accs, label="Train Acc")
plt.plot(test_accs, label="Test Acc")
plt.xlabel("Epoch")
plt.ylabel("Accuracy")
plt.title("Accuracy Curve")
plt.legend()
plt.tight_layout()
plt.show()
# --------------------------
# 步骤6:模型定制化演示(替换组件)
# --------------------------
print("\n=== 模型定制化演示 ===")
# 1. 替换激活函数(ReLU→Tanh)
class MLPWithTanh(nn.Module):
def __init__(self):
super().__init__()
self.model = nn.Sequential(
nn.Linear(30, 64),
nn.Tanh(), # 替换激活函数
nn.Linear(64, 1),
nn.Sigmoid()
)
def forward(self, x):
return self.model(x)
# 2. 替换优化器(Adam→SGD)
mlp_tanh = MLPWithTanh().to(device)
optimizer_sgd = optim.SGD(mlp_tanh.parameters(), lr=0.01, momentum=0.9) # SGD+动量
print("定制化模型初始化完成(激活函数Tanh + 优化器SGD)")
核心扩展(体现 MLP 的灵活性)
表格
| 定制维度 | 调整方式 |
|---|---|
| 网络深度 | 修改hidden_dims列表长度(如[64]→[128,64,32]) |
| 激活函数 | 替换nn.ReLU()为nn.Tanh()/nn.Sigmoid()/nn.LeakyReLU() |
| 优化器 | 替换optim.Adam()为optim.SGD()/optim.RMSprop() |
| 正则化 | 添加nn.Dropout()/ 调整weight_decay(L2 正则化) |
| 学习率 | 修改lr参数(Adam 常用 0.001,SGD 常用 0.01) |
| 训练轮数 | 调整epochs参数(需结合损失曲线判断是否过拟合) |
总结
- MLP 核心逻辑:前向传播(预测)→计算损失→反向传播(求梯度)→梯度下降(更新参数),四步构成训练闭环;
- 灵活性体现:可定制网络结构(层数 / 神经元数)、激活函数、损失函数、优化器、正则化手段,远多于传统机器学习模型;
- 关键技巧 :
- 特征标准化是神经网络训练的前提;
- Adam 优化器是默认首选,学习率需适配;
- 通过损失 / 准确率曲线判断模型收敛性和过拟合;
- Dropout / 正则化可缓解过拟合。