当前位置: 首页 > java >正文

【大模型微调系列-03】 大模型数学基础直观入门

【大模型微调系列-03】 大模型数学基础直观入门

🎯 本章目标:不要害怕数学!我们将通过可视化和简单代码,让你像"看电影"一样理解深度学习的数学原理。记住,深度学习的数学其实就是"让计算机学会调整参数"的艺术。

3.1 理论讲解:深度学习的数学"积木块"

3.1.1 张量与矩阵——数据的"容器"

想象一下,你在整理衣柜。标量就像一件衣服,向量就像一排衣服,矩阵就像一个衣柜的所有衣服,而张量就像整个房间所有衣柜的衣服。在深度学习中,张量就是我们存储和处理数据的"多维容器"。

为什么需要张量?

假设你要处理一张彩色图片:

  • 一个像素的亮度值 → 标量(0维)
  • 一行像素 → 向量(1维)
  • 一张灰度图 → 矩阵(2维)
  • 一张彩色图(RGB三通道)→ 3维张量
  • 100张彩色图一起处理 → 4维张量
标量
单个数字
温度: 25度C
向量
一维数组
一周温度
矩阵
二维表格
多城市温度表
3D张量
立体数据
RGB图像
4D张量
批量数据
100张图片
张量的关键属性
属性含义生活类比
形状(shape)各维度的大小衣柜的长×宽×高
数据类型(dtype)存储的数字类型整数价格 vs 小数重量
设备(device)存储位置仓库(CPU) vs 快递站(GPU)
import torch
import numpy as np# 从熟悉的Python列表开始
temperature = 25.5  # 标量
week_temps = [25.5, 26.1, 24.8, 25.9, 26.5, 27.0, 26.2]  # 向量# 转换为PyTorch张量
tensor_scalar = torch.tensor(temperature)
tensor_vector = torch.tensor(week_temps)print(f"标量张量: {tensor_scalar}, 形状: {tensor_scalar.shape}")
print(f"向量张量: {tensor_vector}, 形状: {tensor_vector.shape}")# 创建一个矩阵(多个城市的周温度)
cities_temps = torch.tensor([[25.5, 26.1, 24.8, 25.9, 26.5, 27.0, 26.2],  # 北京[28.5, 29.1, 28.8, 29.9, 30.5, 31.0, 30.2],  # 上海[22.5, 23.1, 22.8, 23.9, 24.5, 25.0, 24.2],  # 成都
])
print(f"矩阵形状: {cities_temps.shape}")  # [3, 7] = 3个城市,7天
张量操作的直观理解
原始张量
shape: 2,3,4
reshape操作
新张量
shape: 6,4
新张量
shape: 2,12
新张量
shape: 24
为什么能变形?
总元素数不变
2*3*4 = 24

关键概念:张量就像橡皮泥,只要总体积(元素总数)不变,就可以揉成不同形状。这在神经网络中非常重要,因为不同层需要不同形状的输入。

3.1.2 线性变换与权重矩阵——神经网络的"调味配方"

想象你在调制鸡尾酒。每种基酒的比例(权重)决定了最终的口味。神经网络中的权重矩阵就像这个配方,它决定了输入如何变成输出。

矩阵乘法的几何意义

矩阵乘法本质上是对空间的变换。想象你有一张照片,矩阵乘法可以:

  • 缩放:让照片变大或变小
  • 旋转:让照片转动角度
  • 投影:把3D物体投影到2D平面
输出空间
变换矩阵
输入空间
矩阵乘法
y = Wx
输出向量
-1,4
权重矩阵W
旋转+缩放
输入向量
2,3
神经网络中的线性变换

在神经网络中,每一层都在做这样的事情:

输出 = 权重矩阵 × 输入 + 偏置
y = Wx + b

这就像:

  • W(权重):每个特征的重要程度
  • x(输入):原始数据
  • b(偏置):基础分数(即使输入为0也有的输出)
import torch
import matplotlib.pyplot as plt# 创建一个简单的线性变换
input_features = 3  # 输入特征数(如:房屋面积、卧室数、位置评分)
output_features = 2  # 输出特征数(如:价格预测、投资价值)# 权重矩阵:决定每个输入特征如何影响输出
W = torch.tensor([[0.5, 2.0, -1.0],   # 第一个输出的权重[1.0, -0.5, 3.0]    # 第二个输出的权重
])# 输入数据
x = torch.tensor([100.0, 3.0, 8.0])  # [面积, 卧室数, 位置评分]# 线性变换
y = torch.matmul(W, x)
print(f"输入: {x}")
print(f"输出: {y}")
print(f"解释: 第一个输出 = 0.5×100 + 2.0×3 + (-1.0)×8 = {y[0]}")

3.1.3 导数与梯度——找到"下山"的方向

想象你蒙着眼睛站在山坡上,想要走到山谷(最低点)。你能做的就是:

  1. 感受脚下的坡度(导数)
  2. 判断哪个方向最陡(梯度)
  3. 朝着下坡方向走一小步(梯度下降)
导数:变化率的度量

导数告诉我们"如果参数变化一点点,结果会变化多少"。

当前位置
参数w=2
损失L=4
计算导数
导数=4
意味着:
w增加1
L约增加4
w减少1
L约减少4
所以应该
减小w!
梯度:多维空间的"指南针"

当有多个参数时,梯度就像一个指南针,指向函数增长最快的方向。我们要朝相反方向走(负梯度方向)才能找到最小值。

# 可视化梯度下降过程
import numpy as np
import matplotlib.pyplot as plt# 定义一个简单的损失函数(碗状)
def loss_function(w):return w**2# 计算导数
def gradient(w):return 2*w# 梯度下降过程
w = 5.0  # 初始位置
learning_rate = 0.1
history = [w]for step in range(20):grad = gradient(w)w = w - learning_rate * grad  # 更新规则history.append(w)if step % 5 == 0:print(f"步骤 {step}: w={w:.3f}, 梯度={grad:.3f}, 损失={loss_function(w):.3f}")
链式法则:复合函数的"多米诺骨牌"

深度网络就像多层嵌套的函数。链式法则告诉我们如何计算最内层参数对最终输出的影响。

dL/dy
dL/dz2
dL/da1
dL/dz1
dL/dW1
输入x
第一层
z1=W1x
激活
a1=ReLU z1
第二层
z2=W2a1
输出
y=softmax z2
损失L

就像推倒多米诺骨牌,每一块倒下都会影响下一块。链式法则让我们能够计算第一块骨牌(输入层参数)对最后一块(损失函数)的影响。

3.1.4 损失函数与优化——模型的"成绩单"

损失函数就像考试分数,告诉模型"你错了多少"。不同类型的问题需要不同的评分标准。

常见损失函数对比
损失函数类型
回归问题
分类问题
MSE均方误差
预测值与真实值
差距的平方
MAE平均绝对误差
预测值与真实值
差距的绝对值
交叉熵
预测概率分布与
真实分布的差异
Hinge Loss
SVM分类
间隔最大化
MSE vs 交叉熵的直观理解

MSE(均方误差):适合连续值预测

  • 预测房价:预测30万,实际32万 → 误差=(32-30)²=4
  • 特点:对大误差惩罚更重(平方放大)

交叉熵:适合分类问题

  • 预测是猫的概率:0.9,实际是猫 → 损失=-log(0.9)≈0.1(很小)
  • 预测是猫的概率:0.1,实际是猫 → 损失=-log(0.1)≈2.3(很大)
  • 特点:对错误但很自信的预测惩罚极重
import torch
import torch.nn.functional as F# MSE示例:预测温度
predicted_temp = torch.tensor([25.0, 26.5, 24.8])
actual_temp = torch.tensor([24.5, 27.0, 24.0])
mse_loss = F.mse_loss(predicted_temp, actual_temp)
print(f"MSE损失: {mse_loss:.4f}")# 交叉熵示例:分类动物(猫、狗、鸟)
# 模型输出的原始分数(logits)
logits = torch.tensor([[2.0, 1.0, 0.1]])  # 认为是猫的可能性最大
target = torch.tensor([0])  # 真实标签:0代表猫
ce_loss = F.cross_entropy(logits, target)
print(f"交叉熵损失: {ce_loss:.4f}")# 转换为概率看看
probs = F.softmax(logits, dim=1)
print(f"预测概率: 猫={probs[0,0]:.2f}, 狗={probs[0,1]:.2f}, 鸟={probs[0,2]:.2f}")
优化器:如何"下山"

优化器决定了我们如何利用梯度来更新参数。就像下山有不同策略:

SGD
随机梯度下降
最简单
沿梯度方向走
Momentum
动量
考虑惯性
像滚雪球
Adam
自适应
自动调节步长
智能导航
  • SGD:老老实实按梯度走,可能很慢
  • Momentum:考虑之前的运动方向,能冲过小坑
  • Adam:自适应调整每个参数的学习率,通常是最佳选择

3.1.5 Softmax与概率——把分数变成概率

Softmax就像"分蛋糕"——把模型的原始输出分数转换成和为1的概率分布。

为什么需要Softmax?

模型的原始输出可能是任意数字:

  • 猫:5.2
  • 狗:2.1
  • 鸟:-1.3

这些数字没有直观含义。Softmax将它们转换为概率:

  • 猫:92%
  • 狗:7%
  • 鸟:1%

现在我们能清楚地说:“模型认为这92%是猫”。

原始分数
logits
指数化
e^x
归一化
除以总和
概率分布
和为1
5.2, 2.1, -1.3
181.3, 8.2, 0.3
181.3/189.8=0.955
8.2/189.8=0.043
0.3/189.8=0.002
95.5%, 4.3%, 0.2%
温度参数:控制模型的"自信度"

温度(Temperature)就像调节模型的"性格":

  • 低温(T<1):让模型更自信、更确定
  • 高温(T>1):让模型更保守、更均匀
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt# 原始分数
logits = torch.tensor([3.0, 1.0, 0.2])# 不同温度下的概率分布
temperatures = [0.5, 1.0, 2.0, 5.0]
fig, axes = plt.subplots(1, 4, figsize=(12, 3))for idx, temp in enumerate(temperatures):probs = F.softmax(logits / temp, dim=0)axes[idx].bar(['类别A', '类别B', '类别C'], probs.numpy())axes[idx].set_title(f'温度={temp}')axes[idx].set_ylim([0, 1])plt.suptitle('温度对Softmax概率分布的影响')
plt.tight_layout()
# plt.show()  # 如果在notebook中运行print("温度越低,分布越尖锐(更确定)")
print("温度越高,分布越平滑(更不确定)")

3.1.6 反向传播流程——误差的"责任追溯"

反向传播就像侦探破案,从犯罪现场(输出误差)开始,一步步追溯每个嫌疑人(参数)的责任。

完整的前向+反向流程
参数更新
反向传播
前向传播
W2 = W2 - lr*dL/dW2
W1 = W1 - lr*dL/dW1
损失对输出梯度
dL/dy
输出对h2梯度
dL/dh2
h2对W2梯度
dL/dW2
h2对a1梯度
dL/da1
a1对h1梯度
dL/dh1
h1对W1梯度
dL/dW1
第一层
h1 = W1*x + b1
输入数据 x
激活函数
a1 = ReLU h1
第二层
h2 = W2*a1 + b2
输出
y = Softmax h2
计算损失
L = CrossEntropy y,target
梯度的反向流动

想象水从山顶(损失函数)流下来:

  1. 水流分叉:遇到加法节点,梯度复制
  2. 水流汇聚:遇到乘法节点,梯度相乘
  3. 水流调节:遇到激活函数,梯度被调节

每个参数受到的"水压"(梯度)决定了它需要调整多少。

# 简单的反向传播示例
import torch# 构建一个简单的计算图
x = torch.tensor(2.0, requires_grad=True)
w = torch.tensor(3.0, requires_grad=True)
b = torch.tensor(1.0, requires_grad=True)# 前向传播
y = w * x + b  # y = 3*2 + 1 = 7
z = y ** 2     # z = 7^2 = 49
loss = z       # 损失就是z# 反向传播
loss.backward()print(f"前向计算: x={x.item()}, w={w.item()}, b={b.item()}")
print(f"中间结果: y={y.item()}, z={z.item()}")
print(f"\n梯度(责任分配):")
print(f"x的梯度: {x.grad.item()} (x改变1,loss改变{x.grad.item()})")
print(f"w的梯度: {w.grad.item()} (w改变1,loss改变{w.grad.item()})")
print(f"b的梯度: {b.grad.item()} (b改变1,loss改变{b.grad.item()})")
梯度消失和爆炸

在深层网络中,梯度可能会:

  • 消失:梯度越传越小,最后变成0(像电话传话,传到最后听不清)
  • 爆炸:梯度越传越大,最后变成无穷大(像雪崩,越滚越大)

解决方案:

  • 使用合适的激活函数(ReLU而非Sigmoid)
  • 批归一化(Batch Normalization)
  • 梯度裁剪(Gradient Clipping)
  • 残差连接(ResNet的核心思想)

3.2 实操案例

实操1:张量操作实战

import torch
import numpy as np# === 1. 创建张量的多种方式 ===
print("=== 张量创建方法 ===")# 从Python列表
tensor_from_list = torch.tensor([1, 2, 3, 4])
print(f"从列表: {tensor_from_list}")# 全零张量
zeros = torch.zeros(2, 3)
print(f"全零: \n{zeros}")# 全一张量
ones = torch.ones(2, 3)
print(f"全一: \n{ones}")# 随机张量
random = torch.randn(2, 3)  # 标准正态分布
print(f"随机: \n{random}")# 等差数列
arange = torch.arange(0, 10, 2)  # 0到10,步长2
print(f"等差: {arange}")# === 2. 张量形状操作 ===
print("\n=== 形状操作 ===")x = torch.randn(4, 3)
print(f"原始形状: {x.shape}")# reshape/view
x_reshaped = x.reshape(2, 6)
print(f"reshape后: {x_reshaped.shape}")# squeeze去除维度为1的轴
x_with_1 = torch.randn(1, 3, 1, 4)
x_squeezed = x_with_1.squeeze()
print(f"squeeze前: {x_with_1.shape}, squeeze后: {x_squeezed.shape}")# unsqueeze添加维度
x_expanded = x.unsqueeze(0)  # 在第0维添加
print(f"unsqueeze后: {x_expanded.shape}")# === 3. 张量运算 ===
print("\n=== 基本运算 ===")a = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
b = torch.tensor([[5, 6], [7, 8]], dtype=torch.float32)print(f"加法: \n{a + b}")
print(f"逐元素乘法: \n{a * b}")
print(f"矩阵乘法: \n{torch.matmul(a, b)}")# === 4. 自动微分预览 ===
print("\n=== 自动微分 ===")x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 + 3 * x + 1
y.backward()
print(f"y = x^2 + 3x + 1, 当x=2时")
print(f"y的值: {y.item()}")
print(f"dy/dx: {x.grad.item()}")

实操2:构建迷你神经网络

import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt# 定义一个简单的两层网络
class MiniNetwork(nn.Module):def __init__(self, input_size, hidden_size, output_size):super().__init__()self.layer1 = nn.Linear(input_size, hidden_size)self.layer2 = nn.Linear(hidden_size, output_size)def forward(self, x):# 前向传播x = self.layer1(x)x = F.relu(x)  # 激活函数x = self.layer2(x)return x# 创建网络
net = MiniNetwork(input_size=3, hidden_size=4, output_size=2)# 生成模拟数据
batch_size = 5
x = torch.randn(batch_size, 3)
target = torch.randint(0, 2, (batch_size,))# 前向传播
output = net(x)
print(f"输入形状: {x.shape}")
print(f"输出形状: {output.shape}")# 计算损失
loss = F.cross_entropy(output, target)
print(f"损失值: {loss.item():.4f}")# 反向传播
loss.backward()# 查看梯度
for name, param in net.named_parameters():if param.grad is not None:print(f"{name}的梯度形状: {param.grad.shape}")

实操3:可视化梯度下降

import numpy as np
import matplotlib.pyplot as plt# 定义一个简单的二次函数
def f(x):return (x - 3) ** 2 + 1def gradient_f(x):return 2 * (x - 3)# 梯度下降
x_history = []
loss_history = []x = -2.0  # 起始点
learning_rate = 0.1
n_steps = 30for i in range(n_steps):x_history.append(x)loss_history.append(f(x))# 计算梯度并更新grad = gradient_f(x)x = x - learning_rate * grad# 可视化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))# 左图:函数曲线和优化路径
x_range = np.linspace(-3, 8, 100)
y_range = f(x_range)ax1.plot(x_range, y_range, 'b-', label='f(x)=(x-3)²+1')
ax1.plot(x_history, loss_history, 'ro-', markersize=4, label='优化路径')
ax1.axvline(x=3, color='g', linestyle='--', label='最优解 x=3')
ax1.set_xlabel('参数 x')
ax1.set_ylabel('损失值')
ax1.set_title('梯度下降过程')
ax1.legend()
ax1.grid(True, alpha=0.3)# 右图:损失值变化
ax2.plot(range(n_steps), loss_history, 'b-o', markersize=4)
ax2.set_xlabel('迭代步数')
ax2.set_ylabel('损失值')
ax2.set_title('损失值随迭代下降')
ax2.grid(True, alpha=0.3)plt.tight_layout()
# plt.show()print(f"起始点: x={x_history[0]:.2f}, 损失={loss_history[0]:.2f}")
print(f"终止点: x={x_history[-1]:.2f}, 损失={loss_history[-1]:.2f}")
print(f"最优解: x=3.00, 损失=1.00")

实操4:Softmax温度实验

import torch
import torch.nn.functional as Fdef apply_temperature_softmax(logits, temperature):"""应用温度调节的softmax"""return F.softmax(logits / temperature, dim=0)# 模拟模型输出
logits = torch.tensor([4.0, 2.0, 1.0, 0.5, 0.1])
classes = ['猫', '狗', '鸟', '鱼', '兔']print("原始分数(logits):", logits.numpy())
print("\n不同温度下的概率分布:")
print("-" * 50)temperatures = [0.5, 1.0, 2.0, 5.0]for temp in temperatures:probs = apply_temperature_softmax(logits, temp)print(f"\n温度 T={temp}:")for cls, prob in zip(classes, probs):bar = '█' * int(prob * 50)print(f"  {cls}: {prob:.3f} {bar}")# 计算熵(不确定性度量)entropy = -torch.sum(probs * torch.log(probs + 1e-10))print(f"  熵值: {entropy:.3f} (越大越不确定)")

3.3 章节总结

核心要点思维导图

mindmaproot((深度学习数学基础))张量数据的容器多维数组形状操作线性变换矩阵乘法权重和偏置空间变换梯度导数方向导数链式法则优化损失函数梯度下降优化器选择概率Softmax温度调节概率分布反向传播误差传递参数更新梯度流动

与实际深度学习的联系

本章学习的数学概念在实际深度学习中的应用:

  1. 张量操作 → 数据预处理、批处理、特征工程
  2. 线性变换 → 全连接层、卷积层的基础
  3. 梯度计算 → 模型训练的核心机制
  4. 损失函数 → 评估模型性能、指导优化方向
  5. Softmax → 分类任务的概率输出
  6. 反向传播 → 自动计算所有参数的梯度

重要提示

必须掌握

  • 张量的基本概念和形状操作
  • 梯度下降的直观理解
  • 损失函数的作用
  • 前向传播和反向传播的流程

📚 了解即可

  • 具体的数学推导过程
  • 优化器的内部算法细节
  • 梯度消失/爆炸的数学原因

记住:深度学习的数学不是障碍,而是工具。就像开车不需要理解发动机的每个零件,使用深度学习也不需要证明每个数学定理。重要的是理解概念,知道什么时候用什么工具!

http://www.xdnf.cn/news/17951.html

相关文章:

  • PyInstaller打包Python应用操作备忘
  • 后端学习资料 持续更新中
  • PCA降维理论详解
  • 哈希表五大经典应用场景解析
  • 电脑开机几秒后就停止然后再循环是怎么回事
  • 如何在 FastAPI 中玩转 APScheduler,让任务定时自动执行?
  • get和post请求的区别
  • 【Redis】Redis典型应用——缓存
  • 模板引用(Template Refs)全解析2
  • 英文PDF翻译成中文怎么做?试试PDF翻译工具
  • Java 泛型类型擦除
  • Ceph CSI 镜像删除流程与 Trash 机制失效问题分析文档
  • TokenTextSplitter 详解:按 Token 分割文本的艺术与科学
  • pytorch学习笔记-模型的保存与加载(自定义模型、网络模型)
  • 【fwk基础】repo sync报错后如何快速修改更新
  • 图片滤镜处理(filters)
  • 戴永红×数图:重构零售空间价值,让陈列创造效益!
  • 机器翻译:模型微调(Fine-tuning)与调优详解
  • Comfyui进入python虚拟环境
  • 大数据系列之:设置CMS垃圾收集器
  • 如何在 Ubuntu 24.04 Noble LTS 上安装 Apache 服务器
  • 龙虎榜——20250815
  • 【网络】IP总结复盘
  • IDEA 清除 ctrl+shift+r 全局搜索记录
  • SAP ALV导出excel 报 XML 错误的 /xl/sharedStrings.xml
  • STM32在使用DMA发送和接收时的模式区别
  • 数据处理分析环境搭建+Numpy使用教程
  • 主流开源实时互动数字人大模型
  • 易道博识康铁钢:大小模型深度融合是现阶段OCR的最佳解决方案
  • imx6ull-驱动开发篇25——Linux 中断上半部/下半部