Python工具链与LaTeX排版:把兵器配齐

专栏导语 :本专栏系统讲解数学建模的经典方法与 AI 智能方法,并打通两者之间的联系。上一篇我们拿到了两张地图(常用模型地图与算法地图:数模知识全局导航),知道了"遇到哪类问题该用哪类模型"。但地图只解决"用什么",不解决"怎么算出来"------AHP 的权重要算特征向量,微分方程要求数值解,数据要先清洗再建模。这一篇把兵器配齐:六件 Python 兵器各管一段,再加上 LaTeX 把结果排版成论文,让"从题目到论文"真正落地。

文章目录

  • 一、为什么需要"工具链"
    • [1.1 环境安装:装好 Python,一条命令配齐](#1.1 环境安装:装好 Python,一条命令配齐)
  • 二、NumPy:数值计算的基座
    • [2.1 定位:所有工具的地基](#2.1 定位:所有工具的地基)
    • [2.2 核心操作速查](#2.2 核心操作速查)
    • [2.3 建模实例:AHP 判断矩阵求权重](#2.3 建模实例:AHP 判断矩阵求权重)
    • [2.4 广播机制:不同形状也能算](#2.4 广播机制:不同形状也能算)
    • [2.5 建模高频场景与常见坑](#2.5 建模高频场景与常见坑)
  • 三、Pandas:数据处理的第一站
    • [3.1 定位:赛题附件的"第一站"](#3.1 定位:赛题附件的"第一站")
    • [3.2 核心操作速查](#3.2 核心操作速查)
    • [3.3 建模实例:赛题数据预处理](#3.3 建模实例:赛题数据预处理)
    • [3.4 常见坑](#3.4 常见坑)
  • 四、SciPy:现成的算法库
    • [4.1 定位:算法地图的"实体版"](#4.1 定位:算法地图的"实体版")
    • [4.2 实例一:curve\_fit 拟合 Logistic](#4.2 实例一:curve_fit 拟合 Logistic)
    • [4.3 实例二:solve\_ivp 解 SIR------微分方程类落地](#4.3 实例二:solve_ivp 解 SIR——微分方程类落地)
    • [4.4 实例三:linprog 解线性规划------优化类落地](#4.4 实例三:linprog 解线性规划——优化类落地)
  • 五、Matplotlib:论文级可视化
    • [5.1 定位:评委第一眼看图](#5.1 定位:评委第一眼看图)
    • [5.2 图类型选型表](#5.2 图类型选型表)
    • [5.3 论文级图表的四个要素 + 中文显示模板](#5.3 论文级图表的四个要素 + 中文显示模板)
    • [5.4 常见坑](#5.4 常见坑)
  • 六、scikit-learn:机器学习的统一入口
    • [6.1 定位:分类聚类的"总仓库"](#6.1 定位:分类聚类的"总仓库")
    • [6.2 建模实例一:聚类](#6.2 建模实例一:聚类)
    • [6.3 建模实例二:分类](#6.3 建模实例二:分类)
    • [6.4 建模实例三:回归(预测类的最小入口)](#6.4 建模实例三:回归(预测类的最小入口))
    • [6.5 与传统数模怎么选](#6.5 与传统数模怎么选)
  • 七、PyTorch:什么时候才轮到它
    • [7.1 定位:先简后繁,别为了用而用](#7.1 定位:先简后繁,别为了用而用)
    • [7.2 核心概念:每个都对应你已经会的东西](#7.2 核心概念:每个都对应你已经会的东西)
    • [7.3 最小示例:亲眼看梯度下降跑起来](#7.3 最小示例:亲眼看梯度下降跑起来)
    • [7.4 该不该上 PyTorch:一张判断表](#7.4 该不该上 PyTorch:一张判断表)
  • 八、LaTeX:论文排版的最后一公里
    • [8.1 为什么不用 Word](#8.1 为什么不用 Word)
    • [8.2 论文骨架模板](#8.2 论文骨架模板)
    • [8.3 数学公式速查](#8.3 数学公式速查)
    • [8.4 三线表:论文表格的标准格式](#8.4 三线表:论文表格的标准格式)
    • [8.5 插图、交叉引用与参考文献](#8.5 插图、交叉引用与参考文献)
    • [8.6 避坑清单与协作方式](#8.6 避坑清单与协作方式)
  • 九、全链路速查表:从题目到论文
  • 十、学习路径建议
  • 十一、小结

📌本文是专栏「数学建模 × AI:从经典模型到智能方法」的第 4 篇文章。

一、为什么需要"工具链"

上一篇的模型-算法-工具对照表里,最后一列写的就是 Python 工具------NumPy、Pandas、SciPy、scikit-learn......但只给了名字,没讲怎么用。这一篇就干一件事:把这张表的最后一列展开。

先把分工说清楚。六件兵器各管一段,谁也不抢谁的活:

兵器 一句话定位 管什么 不管什么
NumPy 数值计算的基座 矩阵、向量、各种数学运算 读表格、画图
Pandas 数据处理的第一站 读数据、清洗、统计、变形 高性能数值计算
SciPy 现成的算法库 拟合、规划、积分、统计检验 神经网络
Matplotlib 可视化 论文里的每一张图 数据处理
scikit-learn 机器学习统一入口 分类、聚类、回归、降维 深度学习
PyTorch 深度学习框架 神经网络、GPU 加速、自动求导 传统模型(没必要用它)

最后还有一件"排版兵器"------LaTeX 。它不属于 Python 工具链,但没有它,前面六件兵器的成果就交不出去:竞赛的最终交付物是一篇 PDF 论文,公式、三线表、插图、参考文献,LaTeX 都是业界标准。

为什么反复强调"落地":上一篇说过,地图的价值是帮你定位,但"路还得自己走"。评委不看你脑子里装了多少模型,只看论文里跑出了什么结果。工具链就是从"我懂这个模型"到"我跑出了结果"的那座桥。


1.1 环境安装:装好 Python,一条命令配齐

先到 Python 官网 下载安装 Python(3.9 及以上版本均可;别装刚发布的最新版 ,用发布一年以上的成熟版本,避免部分科学计算库还没适配)。Windows 安装时务必勾选 "Add Python to PATH" ------不勾的话命令行认不出 python 和 pip,这是新手第一大坑。

装好后打开命令行(Win+R 输入 cmd 回车),一条命令装齐五件兵器:

bash 复制代码
pip install numpy pandas scipy matplotlib scikit-learn

下载慢的话,在命令末尾加上清华镜像参数 -i https://pypi.tuna.tsinghua.edu.cn/simple 即可。最后补上 PyTorch:

bash 复制代码
pip install torch          # CPU 版,建模够用
# 显卡好的去 PyTorch 官网选好自己的环境,复制官方给出的安装命令

写代码用什么?推荐 VS Code + 官方 Python 插件:打开任意文件夹写 .py 文件,补全、调试、运行一键到位;而且 8.6 节写 LaTeX 还要再用它(装 LaTeX Workshop 插件),一个编辑器管到底 。喜欢网页交互风格的,pip install jupyter 后运行 jupyter notebook 也可以------逐格运行、图表内嵌,探索数据阶段很好用。

进阶方法 :想给不同比赛配不同的库版本(一个装新版、一个装旧版保证复现),用 Python 自带的 venv:python -m venv modeling 创建独立环境,Windows 下执行 modeling\Scripts\activate 激活(Mac/Linux 用 source modeling/bin/activate),之后 pip 装的包只影响这个环境。比赛时团队统一环境,避免"我电脑上能跑"的悲剧。


二、NumPy:数值计算的基座

2.1 定位:所有工具的地基

NumPy 的核心是 ndarray(n 维数组)------一个装数字的多维容器,底层用 C 实现,整块内存连续存储,所以快 。Pandas 建在它上面,scikit-learn 的输入也是它。可以这么记:NumPy 管"数",Pandas 管"表",表也是数构成的。

它的快来自向量化------把"对每个元素做运算"的循环压成一条数学式子,交给底层 C 一次算完:

python 复制代码
import numpy as np

# 不推荐:Python 循环算一万个点的平方,慢
result = [x ** 2 for x in range(10000)]

# 推荐:向量化,一行搞定,快几十倍
x = np.arange(10000)
result = x ** 2

2.2 核心操作速查

操作 代码 建模用途
创建数组 np.array([1, 2, 3])、np.zeros(5) 存放数据、初始化
索引切片 a[0]、a[1:3]、a[:, 1] 取某一列、某一段数据
矩阵乘法 A @ B AHP 判断矩阵、状态转移
转置/逆 A.T、np.linalg.inv(A) 解线性方程组
特征值/特征向量 np.linalg.eig(A) AHP 求权重(判断矩阵是正互反矩阵,用通用求解器)
解方程组 np.linalg.solve(A, b) 线性模型参数求解
聚合 a.sum()、a.mean(axis=0) 按列求均值做标准化
随机数 np.random.rand(1000) 蒙特卡洛仿真

2.3 建模实例:AHP 判断矩阵求权重

上一篇评价类讲过 AHP 的三步:构造判断矩阵 → 一致性检验 → 算权重。其中"算权重"的特征值法,用 NumPy 就是几行:

python 复制代码
import numpy as np

# 3个准则两两比较的判断矩阵(1-9标度法)
A = np.array([
    [1,   3,   5],
    [1/3, 1,   3],
    [1/5, 1/3, 1]
])

eigval, eigvec = np.linalg.eig(A)       # 判断矩阵是正互反矩阵(一般不对称),用通用求解器
k = np.argmax(eigval.real)              # 最大实部对应主特征值λmax(Perron-Frobenius定理保证其为唯一正实主特征值)
lam_max = eigval.real[k]                # 最大特征值
weights = eigvec[:, k].real
weights = weights / weights.sum()       # 归一化后就是权重
print(weights)                          # 例如 [0.633, 0.260, 0.106]

# 一致性检验
n = A.shape[0]
CI = (lam_max - n) / (n - 1)            # 一致性指标
RI = {1: 0, 2: 0, 3: 0.58, 4: 0.90,     # 随机一致性指标RI(1-9阶常用值)
      5: 1.12, 6: 1.24, 7: 1.32, 8: 1.41, 9: 1.45}   # 更高阶需另查表
CR = CI / RI[n]
print(f"CR = {CR:.4f}")                 # CR < 0.1 才通过

其中,np.linalg.eig 为通用特征值求解器------判断矩阵 A A A 满足 a i j ⋅ a j i = 1 a_{ij} \cdot a_{ji} = 1 aij⋅aji=1(正互反矩阵),一般不对称 ,不能用实对称专用的 eigh(它只读矩阵的一个三角部分,对非对称输入不报错但结果全错);由 Perron-Frobenius 定理,正互反矩阵的最大特征值 λ max ⁡ \lambda_{\max} λmax 必为正实数且唯一,对应特征向量为正向量,故取 .real 即可, w i = v i ∑ j v j w_i = \frac{v_i}{\sum_j v_j} wi=∑jvjvi 为归一化后的权重向量( v v v 为 λ max ⁡ \lambda_{\max} λmax 对应的特征向量), C I = λ max ⁡ − n n − 1 CI = \frac{\lambda_{\max} - n}{n - 1} CI=n−1λmax−n 衡量判断矩阵偏离一致性的程度, C R < 0.1 CR < 0.1 CR<0.1 时认为一致性可以接受。

对照上一篇 :这段代码就是评价类"三件套"里 AHP 的最后两步。判断矩阵哪里来?靠两两比较打分(主观);想要客观权重,就用熵权法------同样只用 NumPy 循环外的一点点代码。后续模型专文会把熵权法、TOPSIS 的代码逐一给全。

2.4 广播机制:不同形状也能算

NumPy 最"魔法"也最容易懵的一点是广播(broadcasting):形状不同的数组运算时,自动把小的"补"成大的再算。

python 复制代码
# 3个班级、4门课的分数矩阵,想给每门课减去一个基准分
scores = np.array([[80, 85, 90, 78],
                   [75, 82, 88, 91],
                   [92, 78, 84, 80]])
base = np.array([5, 3, 2, 4])           # 形状(4,)
adjusted = scores - base                # 形状(3,4)减(4,),自动广播

规则一句话:从最后一个维度往前对齐,维度相等或其中一个是 1 就能广播。记住它,后面写标准化、距离计算(每行减去均值再除以标准差)时会反复用到。

2.5 建模高频场景与常见坑

高频场景:

  • 2024 国赛 A 题「板凳龙闹元宵」:两百多块板凳沿螺旋线运动,每个时刻都要算所有板凳的位置------向量化一次算完,比逐点循环快几个数量级;
  • 2025 国赛 A 题「烟幕干扰弹投放策略」:三维运动学 + 大量蒙特卡洛仿真,全是 NumPy 数组运算;
  • 任何优化模型的约束矩阵、评价模型的指标矩阵 ,底层数据都是 ndarray。

常见坑:

坑 现象 正确做法
视图不是拷贝 b = a[1:3] 改 b 连 a 也变了 需要独立副本时用 a[1:3].copy()
整数除法精度 np.array([1, 2]) / 2 结果是 float64 没问题,但 np.int32 溢出会静默环绕 大数运算前转 dtype=np.float64
行向量/列向量 (3,) 既不是行也不是列 明确需要行列时用 reshape(-1, 1) 或 reshape(1, -1)
eigh 误用于非对称矩阵 AHP 判断矩阵喂给 eigh 不报错,但权重结果全错(它只读一个三角部分) 判断矩阵是正互反 而非对称,特征值问题必须用 eig

三、Pandas:数据处理的第一站

3.1 定位:赛题附件的"第一站"

比赛发的附件十有八九是 Excel/CSV 表格------销售记录、监测数据、指标统计。Pandas 就是为表格而生的 :它的 DataFrame 是一个带行标签、列标签的二维表,读进来、洗干净、统计出规律,全靠它。

近年趋势 :数据分析型题目越来越多。2023 国赛 C 题「蔬菜类商品的自动定价与补货决策」给了三年多的批发/零售流水,第一步必须把原始流水按品类、按时间聚合出销量和定价------这道"开胃菜"完全靠 Pandas。2018 国赛 C 题的零售数据同理。数据洗不干净,后面模型再漂亮都是空中楼阁。

3.2 核心操作速查

操作 代码 说明
读取 pd.read_csv('a.csv') / pd.read_excel('a.xlsx') 中文乱码就加 encoding='gbk'
概览 df.head()、df.info()、df.describe() 拿到数据先跑这三句
选列/筛行 df['销量']、df[df['销量'] > 100] 布尔筛选最高频
缺失值 df.isna().sum()、df.dropna()、df.fillna(0) 先统计再决定删还是补
分组聚合 df.groupby('品类')['销量'].sum() 流水变汇总的核心操作
透视表 df.pivot_table(index=..., columns=..., values=...) 行列两个维度的交叉统计
合并 pd.merge(df1, df2, on='ID') 多表按主键拼接
时间处理 pd.to_datetime(df['日期']) 按月/季重采样必用

3.3 建模实例:赛题数据预处理

模拟一下 2023 国赛 C 题那类流水数据的标准预处理流程:

python 复制代码
import pandas as pd

# 1. 读入流水数据(中文乱码常见,两种编码都试)
df = pd.read_csv('sales.csv', encoding='utf-8')   # 不行就换 'gbk'

# 2. 概览:多少行、哪些列有缺失、类型对不对
print(df.info())

# 3. 清洗:日期转标准格式,关键列缺失的行丢弃,退货记录剔除
df['销售日期'] = pd.to_datetime(df['销售日期'])
df = df.dropna(subset=['销量', '销售单价'])
df = df[df['销量'] > 0]

# 4. 聚合:按品类按月汇总销量,得到定价模型要用的输入
df['月份'] = df['销售日期'].dt.to_period('M')
monthly = df.groupby(['品类', '月份']).agg(
    总销量=('销量', 'sum'),
    均价=('销售单价', 'mean')
).reset_index()

# 5. 透视:换个视角看品类×月份的销量矩阵
pivot = df.pivot_table(index='品类', columns='月份',
                       values='销量', aggfunc='sum')

注意 :groupby + agg 这套组合拳是数据分析题的"标准起手式"。写论文时,这一节对应论文的"数据处理"部分------把缺失值多少、剔除了什么、按什么口径聚合,写清楚,评委才认为你的结果可信。

3.4 常见坑

坑 现象 正确做法
链式赋值警告 df[df['a']>1]['b'] = 0 不生效 用 df.loc[df['a']>1, 'b'] = 0
编码 read_csv 报 UnicodeDecodeError 依次试 utf-8、gbk、gb18030
日期被读成字符串 按月聚合时直接报错 读入后立刻 pd.to_datetime
隐式索引混乱 删过行后 df.loc[0] 报错 loc 按标签、iloc 按位置,删行后想按位置取用 iloc

四、SciPy:现成的算法库

4.1 定位:算法地图的"实体版"

上一篇的算法地图里,梯度类、精确算法、采样类那么多算法,大部分不用自己写 ------SciPy 已经实现了。它的定位一句话:NumPy 管"存数算数",SciPy 管"算法"------拟合、规划、积分、统计检验,全是现成的。

子模块 管什么 建模高频函数
scipy.optimize 拟合与优化 curve_fit(曲线拟合)、linprog(线性规划)、minimize(非线性)
scipy.integrate 积分与微分方程 solve_ivp(常微分方程组数值解)
scipy.stats 统计分布与检验 各种分布的概率计算、假设检验、相关系数
scipy.interpolate 插值 interp1d(缺失数据补全、曲线光滑)

4.2 实例一:curve_fit 拟合 Logistic

本专栏的下一篇将用人口增长问题演示了完整建模闭环,其中"模型求解"用的正是 curve_fit:给出模型形式,让 SciPy 自动找出最贴合真实数据的参数。

python 复制代码
import numpy as np
from scipy.optimize import curve_fit

# Logistic模型:K承载量,r增长率,t0拐点时间
def logistic(t, K, r, t0):
    return K / (1 + np.exp(-r * (t - t0)))

# years、population 是真实人口数据(第0篇用美国1790-2020年普查数据)
popt, pcov = curve_fit(logistic, years, population, p0=[400, 0.03, 1900])
K, r, t0 = popt                      # 拟合出的三个参数

其中,logistic 为 Logistic 模型的解析形式,p0 为参数初值(给个量级正确的初值能显著提升收敛速度),popt 为拟合出的最优参数数组,pcov 为参数的协方差矩阵(对角线开方即参数的标准误差,论文里写参数估计的置信区间要用它)。

原理一句话 :curve_fit 的本质就是最小二乘 ------找一组参数让"模型预测值与真实值之差的平方和"最小,底层调用的是 MINPACK 的梯度类算法。第 0 篇说过"最小二乘=损失函数",机器学习训练神经网络玩的也是同一个游戏------这条线后续 AI 文章会正式接上。

4.3 实例二:solve_ivp 解 SIR------微分方程类落地

上一篇仿真/微分方程类讲过 SIR 传染病模型。微分方程 d S d t = − β S I , d I d t = β S I − γ I , d R d t = γ I \frac{dS}{dt} = -\beta S I,\quad \frac{dI}{dt} = \beta S I - \gamma I,\quad \frac{dR}{dt} = \gamma I dtdS=−βSI,dtdI=βSI−γI,dtdR=γI 一般没有解析解,数值解一行搞定:

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp

def sir(t, y, beta, gamma):
    S, I, R = y
    return [-beta*S*I, beta*S*I - gamma*I, gamma*I]

sol = solve_ivp(sir, [0, 100], [0.99, 0.01, 0.0],   # 时间范围与初值
                args=(0.3, 0.1),                     # beta=0.3, gamma=0.1
                t_eval=np.linspace(0, 100, 1000))

plt.plot(sol.t, sol.y[0], label='S 易感者')
plt.plot(sol.t, sol.y[1], label='I 感染者')
plt.plot(sol.t, sol.y[2], label='R 康复者')
plt.legend()

其中, S S S、 I I I、 R R R 分别为易感者、感染者、康复者占总人口的比例, β \beta β 为感染率系数, γ \gamma γ 为康复率系数,solve_ivp 默认采用自适应步长的 RK45 方法(Runge-Kutta 家族,上一篇算法地图里提到的 RK4 的自适应升级版),t_eval 指定输出解的时间点。

对照上一篇 :微分方程类选型口诀说"单变量、连续时间 → ODE(用 odeint 求解)",solve_ivp 是它的新一代替代品,接口更统一。注意 SIR 的假设边界(均匀混合、无潜伏期)------上一篇限制条件速查表里写明了,实际疫情要用 SEIR 放宽。

4.4 实例三:linprog 解线性规划------优化类落地

优化类是数模第一大类。标准形式 min ⁡ c T x , s.t. A u b x ≤ b u b , x ≥ 0 \min c^T x,\quad \text{s.t. } A_{ub}x \le b_{ub},\quad x \ge 0 mincTx,s.t. Aubx≤bub,x≥0 用 linprog 直接解:

python 复制代码
from scipy.optimize import linprog

# 例:max 10x + 8y,s.t. x+y≤40, x+2y≤60, x,y≥0
c = [-10, -8]                     # linprog只做min,目标取负号
A = [[1, 1], [1, 2]]
b = [40, 60]
res = linprog(c, A_ub=A, b_ub=b, bounds=[(0, None), (0, None)])
if not res.success:               # 先判成功再取解,否则拿到的是无效结果
    raise ValueError(res.message) # 无可行解/目标无界时,message会说明原因
print(res.x, -res.fun)            # 最优解 [20, 20],最优值 360

其中, c c c 为目标函数系数向量(求最大值时取负、结果再取负), A u b , b u b A_{ub}, b_{ub} Aub,bub 为不等式约束的系数矩阵与右端项,bounds 为变量的取值范围,res.success 为求解状态标志(务必先判成功再取解 ),res.x 为最优解向量,res.fun 为最小化的目标值。

什么时候升级 :变量是整数(0-1 决策、排班、选址)时,linprog 不行,用 PuLP(上一篇优化类表里给过的工具,语法更接近建模语言)。变量上千且非线性,转启发式------还是上一篇地图的路标。工具是按地图层级升级的,不是瞎选的。


五、Matplotlib:论文级可视化

5.1 定位:评委第一眼看图

论文评阅时间极短,图表是评委最先看的部分------一张信息清晰、坐标规范、有图例的图,胜过三段文字。Matplotlib 是 Python 画图的底座,其他可视化库(seaborn 等)都是它的封装。

5.2 图类型选型表

想表达什么 用什么图 建模场景
趋势随时间变化 折线图 plt.plot 人口预测曲线、销量走势
两组量的相关关系 散点图 plt.scatter 价格与销量的弹性关系
多类别数量对比 柱状图 plt.bar 各品类销量对比
矩阵/相关系数 热力图 plt.imshow 指标相关性矩阵
三维曲面 Axes3D.plot_surface 优化目标函数地形、二维概率密度
分布形态 直方图 plt.hist 蒙特卡洛仿真结果的分布

5.3 论文级图表的四个要素 + 中文显示模板

一张合格的论文图要有:坐标轴含义与单位、图例、足够的分辨率、可复现的绘图代码。中文显示和负号显示的坑,用下面这个模板一次解决:

python 复制代码
import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.sans-serif'] = ['SimHei']     # 中文显示(Windows)
plt.rcParams['axes.unicode_minus'] = False       # 负号正常显示

t = np.linspace(0, 100, 500)
plt.figure(figsize=(8, 5), dpi=120)              # 尺寸与分辨率
plt.plot(t, 400/(1+np.exp(-0.05*(t-40))), label='r=0.05')
plt.plot(t, 400/(1+np.exp(-0.10*(t-40))), label='r=0.10')
plt.xlabel('时间 t / 年')                         # 轴含义+单位
plt.ylabel('人口 P(t)')
plt.title('不同增长率下的 Logistic 曲线')
plt.legend()                                     # 图例
plt.grid(alpha=0.3)
plt.savefig('logistic.png', dpi=300, bbox_inches='tight')  # 论文用300dpi

其中,figsize 与 dpi 共同决定图片分辨率(论文插图建议 dpi=300 以上),rcParams 两行设置解决中文与负号的乱码问题,bbox_inches='tight' 让保存的图片裁掉周围空白。

进阶方法 :plt.subplot(2, 2, i) 可在一张图里排多幅子图(敏感性分析时一图四变特别好用);seaborn 库一行 sns.set_theme() 就能把默认样式美化到论文水准。图的风格全文要统一------所有图的字体、线宽、配色保持一致,这是很多队伍忽略的细节分。

5.4 常见坑

坑 现象 正确做法
中文变方框 图里中文全显示成 □ 设置 font.sans-serif(Mac 用 Arial Unicode MS)
负号变乱码 坐标轴负号显示异常 axes.unicode_minus = False
图太糊 插到 PDF 里模糊 dpi=300 且用 savefig 而不是截图
线堆在一起认不出 多条曲线难区分 加 label + legend(),或用不同 linestyle

六、scikit-learn:机器学习的统一入口

6.1 定位:分类聚类的"总仓库"

上一篇分类聚类类的模型------逻辑回归、KMeans、判别分析、DBSCAN------全部在 scikit-learn 里,而且 API 完全统一 :所有模型都是三步,fit(学习)→ predict(预测)→ score(评估)。学会一个,就学会了全部,这是它作为"统一入口"的含义。

模块 管什么 建模场景
cluster 聚类 KMeans、层次聚类、DBSCAN
linear_model 线性/逻辑回归 回归预测、二分类
tree / ensemble 树与集成 决策树、随机森林(要特征重要性时用)
preprocessing 预处理 标准化、归一化、编码
model_selection 模型评估 训练测试集划分、交叉验证
decomposition 降维 PCA 主成分分析

6.2 建模实例一:聚类

python 复制代码
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler

# df 为第三章预处理好的数据表;X 为特征矩阵(每行一个样本)
X = df[['指标1', '指标2', '指标3']].values
X_std = StandardScaler().fit_transform(X)        # 标准化,消除量纲

km = KMeans(n_clusters=3, n_init=50, random_state=42)
labels = km.fit_predict(X_std)                   # 一行得到聚类结果
df['类别'] = labels

其中,StandardScaler 把每列变为均值 0、标准差 1(不做的话量纲大的指标会主导距离计算,聚类结果失真),n_clusters 为簇数(结合肘部法/轮廓系数确定,不是拍脑袋),n_init 为换不同初始中心重复运行的次数(KMeans 对初始点敏感,上一篇限制条件表里写过),random_state 固定随机种子保证结果可复现。

6.3 建模实例二:分类

python 复制代码
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# X_std 承接 6.2;y 为标签列------每个样本的真实类别(如玻璃的"高钾/铅钡"类型)
y = df['类型'].values

X_train, X_test, y_train, y_test = train_test_split(
    X_std, y, test_size=0.3, random_state=42, stratify=y)

clf = LogisticRegression(max_iter=1000).fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(accuracy_score(y_test, y_pred))            # 测试集准确率

其中,test_size=0.3 表示 30% 数据留作测试、70% 用于训练,stratify=y 保证划分后两集合中各类别比例一致(类别不平衡时必须加),fit 在训练集上学习参数,accuracy_score 在测试集上评估------在测试集上评估而不是训练集,是机器学习的第一纪律。

**2022 国赛 C 题「古代玻璃制品的成分分析与鉴别」**就是典型的分类题:根据成分数据判断玻璃类型,用逻辑回归/决策树 + 交叉验证是标准打法。分类聚类在传统数模里偏配角,在 AI 路线上是主角------本专栏 AI 子专栏的 SVM、随机森林、神经网络全部基于这套 API 展开,现在学的就是以后的地基。

6.4 建模实例三:回归(预测类的最小入口)

预测类题目最常用的线性回归,同样是三步:

python 复制代码
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

# 回归的目标是连续量(销量、价格等),与分类的类别标签是两回事,故记作 y_reg
y_reg = df['销量'].values

X_train, X_test, y_train, y_test = train_test_split(
    X_std, y_reg, test_size=0.3, random_state=42)

reg = LinearRegression().fit(X_train, y_train)  # 在训练集上拟合
print(reg.coef_, reg.intercept_)                # 回归系数与截距,可直接写进论文
print(reg.score(X_test, y_test))                # 测试集 R²

其中,y_reg 为从数据表中取出的目标列------回归要预测的连续量(销量、价格等),注意它与分类任务里的类别标签 y y y 不是一回事 ;fit 用最小二乘法估计系数(与 4.2 节 curve_fit 的底层思想一致),reg.coef_ 为各自变量的回归系数(含义是"其他变量不变时,该指标每增加一个单位,因变量的平均变化量",可解释性好),reg.score 返回决定系数 R 2 R^2 R2。当特征间多重共线、系数估计不稳时,换成 Ridge / Lasso,接口一字不改------这正是统一 API 的好处。

6.5 与传统数模怎么选

一句话判断:有标签走分类,没标签走聚类;数据少、要解释,传统模型优先;数据多、要精度,机器学习上。 这正是上一篇"模型选择三原则"(先简后繁、数据说话、可解释优先)在工具层的体现。


七、PyTorch:什么时候才轮到它

7.1 定位:先简后繁,别为了用而用

上一篇模型选择原则一就是"先简后繁"------大部分数模题用不到 PyTorch。数据量小(几百行)、要求可解释、传统模型效果够用时,上神经网络属于"为了炫技而复杂",评委不买账。

真正需要 PyTorch 的三种情况:

  1. 数据量大的深度预测:长时序、高维特征,传统模型精度明显不够(LSTM、Transformer 预测);
  2. 非结构化数据:图像、文本类题目,卷积/预训练模型是标配;
  3. 研究 AI 本身:本专栏"用数模研究 AI"那条线,必须能操作模型的内部梯度。

7.2 核心概念:每个都对应你已经会的东西

PyTorch 没有想象中神秘,四个核心概念都能在前面的内容里找到影子:

PyTorch 概念 相当于 说明
张量 Tensor NumPy 的 ndarray 多维数组,还能搬上 GPU
自动求导 autograd 梯度类算法的"发动机" 自动算出损失函数对每个参数的梯度
nn.Module 模型地图里的"模型" 把网络结构封装成类
优化器 Optimizer 梯度下降的"步长控制" SGD、Adam 等更新参数的策略

其中,张量(Tensor)与 ndarray 的区别在于两点:可放入 GPU 并行计算、可自动求导;自动求导机制依据链式法则逐层反向计算梯度(即"反向传播"),这正是上一篇算法地图里梯度类算法的底层实现。

7.3 最小示例:亲眼看梯度下降跑起来

不用任何神经网络模块,只用自动求导拟合一元线性回归 y = w x + b y = wx + b y=wx+b,把上一篇 3.2 节"沿负梯度方向迭代"的文字变成看得见的代码:

python 复制代码
import torch

x = torch.tensor([1., 2., 3., 4.])
y = 2 * x + 1                          # 真实规律
w = torch.tensor([0.], requires_grad=True)
b = torch.tensor([0.], requires_grad=True)

for step in range(200):
    pred = w * x + b
    loss = ((pred - y) ** 2).mean()    # 均方误差=损失函数
    loss.backward()                    # 自动求 dL/dw, dL/db
    with torch.no_grad():
        w -= 0.01 * w.grad             # 沿负梯度走一步
        b -= 0.01 * b.grad
    w.grad.zero_()                     # 梯度清零,准备下一步
    b.grad.zero_()

print(w.item(), b.item())              # 输出约 2.0 和 1.0

其中, L = 1 n ∑ i = 1 n ( w x i + b − y i ) 2 L = \frac{1}{n}\sum_{i=1}^{n}(wx_i + b - y_i)^2 L=n1∑i=1n(wxi+b−yi)2 为均方误差损失函数, w w w、 b b b 为待学习参数(requires_grad=True 表示要对其求梯度),backward() 调用自动求导机制计算 ∂ L ∂ w \frac{\partial L}{\partial w} ∂w∂L 与 ∂ L ∂ b \frac{\partial L}{\partial b} ∂b∂L;with torch.no_grad() 让参数更新这一步脱离自动求导追踪(否则更新操作本身会被记入计算图,下一轮 backward() 会报错);学习率 0.01 控制每步沿负梯度方向移动的距离。

AI 联系 :这十几行代码就是所有深度学习训练的骨架 ------把 w*x+b 换成亿级参数的网络、把数据换大、把优化器换成 Adam,本质流程一字不改。第 0 篇说"最小二乘=损失函数",上一篇说"梯度下降是神经网络训练的核心",到这里两条伏笔正式会师。AI 子专栏讲神经网络时,就从这个例子出发往上盖楼。

7.4 该不该上 PyTorch:一张判断表

情况 决策
数据几百行、关系简单 线性回归/逻辑回归(sklearn),不上深度学习
要向评委解释每个参数的含义 树模型 + 特征重要性,不上深度学习
时序长、维度高、传统方法精度瓶颈 LSTM/Transformer(PyTorch)
图像/文本/语音数据 卷积网络/预训练模型(PyTorch)
题目研究 AI 模型自身(对抗攻击、鲁棒性) 必须掌握自动求导(PyTorch)

量化参考:经验上,样本量在千行以内、特征只有几十个、且存在明确机理模型时,一般用不上深度学习;数据量到万级以上、或传统方法精度明显见顶时,再考虑 PyTorch。这个参考不是硬边界,但足以帮你挡掉大多数"为了用而用"。
规范提醒 :近年大赛对 AI 工具的使用已有官方规范(上一篇趋势七结合 2026 国赛 B 题详细讲过)。把工具链练熟,最大的底气是"自己能实现"------无论规范怎么变,能自己写代码复现模型的人永远不慌。


八、LaTeX:论文排版的最后一公里

8.1 为什么不用 Word

建模论文公式密集、图表众多、三人协作、频频改版。Word 在交叉引用、公式编号、参考文献、多人协作上全都吃力,LaTeX 全都省心。一句话:公式和交叉引用一多,LaTeX 的效率就是碾压性的。国内外竞赛官方都提供 LaTeX 模板,评委看到的漂亮论文大多是它排的。

8.2 论文骨架模板

下面是一个通用的论文骨架(国赛/美赛结构大同小异),保存为 main.tex 直接可编译:

latex 复制代码
\documentclass[12pt]{article}
\usepackage{ctex}            % 中文支持(需用 XeLaTeX 编译)
\usepackage{amsmath,amssymb} % 公式
\usepackage{booktabs}        % 三线表
\usepackage{graphicx}        % 插图
\usepackage{float}           % 提供 [H] 图片强制定位
\usepackage{geometry}
\geometry{a4paper, margin=2.5cm}

\title{基于Logistic增长模型的XX问题研究}
\author{}
\date{}
\begin{document}
\maketitle
\begin{abstract}
针对问题一,本文建立了......模型,求解得到......。针对问题二......\\
\textbf{关键词}:Logistic模型;最小二乘;蒙特卡洛仿真
\end{abstract}

\section{问题重述}
\section{模型假设}
\begin{itemize}
  \item 假设人口增长满足Logistic方程刻画的光滑性要求;
  \item 假设研究期内环境承载量 $K$ 保持不变。
\end{itemize}
\section{符号说明}
\section{模型的建立与求解}
\section{模型的评价与推广}
\end{document}

其中,documentclass 声明文档类型与正文字号,ctex 宏包提供中文支持(必须用 XeLaTeX 编译器),abstract 环境是摘要------数模论文的摘要决定第一印象,评委初选基本只看摘要 ,section 自动生成章节编号,不用手打。

现成模板 :Overleaf 上搜索国赛模板 cumcmthesis 或美赛模板 mcmthesis,格式(页眉、承诺书、编号规则)都已按官方要求调好,比赛时直接在模板里填内容,不要比赛当天才第一次打开模板。

8.3 数学公式速查

想写什么 LaTeX 代码 效果
行内公式 $r > 0$ r > 0 r > 0 r>0
行间公式(带编号) \begin{equation} ... \end{equation} 居中单独成行
分数 \frac{dP}{dt} d P d t \frac{dP}{dt} dtdP
求和 \sum_{i=1}^{n} x_i ∑ i = 1 n x i \sum_{i=1}^{n} x_i ∑i=1nxi
积分 \int_0^T f(t)\,dt ∫ 0 T f ( t )   d t \int_0^T f(t)\,dt ∫0Tf(t)dt
矩阵 bmatrix 环境 方括号矩阵
多行推导对齐 align 环境 + & 对齐 逐步推导不跳步
条件定义 cases 环境 分段函数

建模里最常用的多行推导长这样("推导不跳步"的排版载体):

latex 复制代码
\begin{align}
\frac{dP}{dt} &= rP\left(1 - \frac{P}{K}\right) \\
\frac{d^2P}{dt^2} &= r\left(1 - \frac{2P}{K}\right)\frac{dP}{dt}
\end{align}
其中,$P(t)$ 为第 $t$ 年的人口数量,$r$ 为固有增长率,$K$ 为环境最大承载量;
第二个式子对增长速度 $\frac{dP}{dt}$ 再求导,用于判断拐点位置。

写作约定 :本专栏的每条公式后面都会跟一句"其中,......"解释全部新符号------写论文时请保持这个习惯,评委没有义务猜你符号的含义。

8.4 三线表:论文表格的标准格式

论文里的表格用三线表 (只有顶线、栏目线、底线三条横线,无竖线),booktabs 宏包三行搞定:

latex 复制代码
\begin{table}[H]
\centering
\caption{符号说明}
\begin{tabular}{cl}
\toprule
符号 & 含义 \\
\midrule
$P(t)$ & 第 $t$ 年的人口数量 \\
$r$ & 人口固有增长率 \\
$K$ & 环境最大承载量 \\
\bottomrule
\end{tabular}
\end{table}

其中,table 环境是浮动表格容器,[H](需 float 宏包)强制表格出现在代码书写位置而不是"漂"到别处,\caption 生成表题,\toprule / \midrule / \bottomrule 分别画顶线、栏目线、底线,{cl} 表示第一列居中、第二列左对齐。

写作约定 :本专栏所有表格都用三线表格式、表下配说明文字,论文同理------每个表格下面必须有一段"表 X 展示了......"的文字解读,绝不让表格裸奔。

8.5 插图、交叉引用与参考文献

插图 (图片文件放同目录,或用 \graphicspath{``{images/}} 统一指定路径):

latex 复制代码
\begin{figure}[H]
\centering
\includegraphics[width=0.8\textwidth]{logistic.png}
\caption{不同增长率下的 Logistic 曲线}
\end{figure}

其中,[H] 强制图在原位,width=0.8\textwidth 控制图宽为版心的 80%(用相对宽度,避免图片溢出页面),\caption 放在 \includegraphics 之后即生成图下方的图注(表注在表上方、图注在图下方,这是通用排版规范)。

交叉引用 :给公式、图、表打 \label{eq:logistic}、\label{fig:curve},正文用 \eqref{eq:logistic}、\ref{fig:curve} 引用。改版重排时编号自动更新------这是 LaTeX 对 Word 的最大优势,也是多人协作时"图 3 到底是哪张"的终结者。

参考文献:

latex 复制代码
\begin{thebibliography}{9}
\bibitem{jiang2021} 司守奎, 孙兆亮. 数学建模算法与应用[M]. 第3版. 国防工业出版社, 2021.
\end{thebibliography}

正文里 \cite{jiang2021} 即生成上标引用,编号自动管理。

8.6 避坑清单与协作方式

坑 现象/正确做法
中文编译报错 必须用 XeLaTeX 编译器(配合 ctex 宏包),不是 pdfLaTeX
图片不浮动 H 报错 忘了 \usepackage{float}
% $ & # _ { } 消失或报错 这些是特殊字符,需加反斜杠转义,尤其是百分号
图片找不到 图片与 .tex 同目录,或用 \graphicspath 指定
编译总不过 先注释掉一半内容二分定位错误;看报错行号往上翻几行找真凶

编辑器怎么选 :本地两件套------TeXStudio(开箱即用,适合第一次接触)或 VS Code + LaTeX Workshop 插件(适合已在用 VS Code 的人);在线就是 Overleaf。取舍很简单:本地编译快、断网能写,但环境配置费劲;在线零配置、协作强,但依赖网络。比赛三人协作建议直接用 Overleaf,平时练习本地和在线各跑一遍找手感。
协作神器 :Overleaf 在线 LaTeX,三人同时编辑、实时预览、自动云同步,还内置了各大竞赛模板。比赛期间把项目链接分享给队友即可,彻底告别"论文最新版到底在谁电脑上"。


九、全链路速查表:从题目到论文

六件兵器 + LaTeX 各就各位后,整条流水线是这样的:

复制代码
 Excel/CSV 附件数据
        │
        ▼
 ┌─────────────┐      清洗、筛选、聚合、透视
 │   Pandas    │ ────────────────────────────►  规整的数据表
 └─────────────┘                                        │
                                                        ▼
                                          ┌─────────────────────────┐
                                          │        NumPy            │
                                          │  矩阵运算 / 向量化计算    │
                                          └─────────────────────────┘
                                                        │
              ┌─────────────────────────┬───────────────┼───────────────┐
              ▼                         ▼               ▼               ▼
       ┌────────────┐          ┌────────────┐  ┌────────────┐  ┌────────────┐
       │   SciPy    │          │ sklearn    │  │  PyTorch   │  │   PuLP     │
       │ 拟合/规划/  │          │ 分类/聚类/ │  │ 深度学习   │  │ 整数规划   │
       │ 微分方程    │          │ 回归/降维  │  │ (必要时)   │  │ (必要时)   │
       └────────────┘          └────────────┘  └────────────┘  └────────────┘
              │                         │               │               │
              └─────────────────────────┴───────────────┼───────────────┘
                                                        ▼
                                          ┌─────────────────────────┐
                                          │      Matplotlib         │
                                          │   结果可视化(300dpi)    │
                                          └─────────────────────────┘
                                                        │
                                                        ▼
                                          ┌─────────────────────────┐
                                          │        LaTeX            │
                                          │   公式/三线表/引用成文    │
                                          └─────────────────────────┘

把上一篇的"问题类型"和这一篇的"兵器入口"合到一张表,就是你要贴在工位上的那张纸:

问题类型(上一篇) 兵器 核心入口 记忆锚点
评价 NumPy + Pandas np.linalg.eig(AHP)、归一化(熵权/TOPSIS) 特征向量=权重
预测 SciPy(+ statsmodels) curve_fit、statsmodels.tsa(ARIMA) 最小二乘=损失函数
优化 SciPy / PuLP linprog、minimize、整数规划用 PuLP max 先取负号
分类聚类 scikit-learn fit / predict / score 统一三步走
仿真 NumPy + SciPy np.random 蒙特卡洛、solve_ivp 大数定律兜底
图论 networkx(补充兵器) nx.shortest_path 等 一行装,按需查文档
微分方程 SciPy solve_ivp RK 自适应步长
任何题 Matplotlib + LaTeX savefig(dpi=300)、\begin{figure}[H] 图表=论文的脸面

networkx 补充一句 :图论题(最短路、网络流、PageRank)用它,也是一行 pip install networkx。上一篇对照表里出现过,这里归队------它算"第七件小兵器",按需取用即可。
环境固化(收个尾) :1.1 节说过"团队统一环境",这里补上落地动作------比赛第一天就导出环境清单:pip freeze > requirements.txt。队友拿到清单后 pip install -r requirements.txt 一键复现。统一靠清单,不靠口头。


十、学习路径建议

兵器配齐不等于都要练到精通。按优先级分三阶段:

第一阶段(数据基本功,赛前必须形成肌肉记忆):

  1. Pandas:读入 → info/describe → 清洗 → groupby 聚合,整条流程盲打;
  2. NumPy:数组运算、广播、linalg 常用函数;
  3. Matplotlib:折线/散点/柱状 + 中文显示模板 + 300dpi 保存。
    练法:随便找一篇历年赛题的附件数据,做一次完整的探索性分析(EDA),产出 3 张论文级图表。

第二阶段(模型落地) :

  1. SciPy 三大件:curve_fit、solve_ivp、linprog;

  2. scikit-learn:标准化 + KMeans + 逻辑回归 + 训练测试集划分。

练法 :把上一篇学习路径第一阶段的模型(AHP 三件套、线性规划、回归、蒙特卡洛)每个都跑通一个最小例子------地图上的每个格子都要用代码踩一遍。

第三阶段(论文与进阶) :

  1. LaTeX:在 Overleaf 上用竞赛模板把一篇做过的题写成完整论文(摘要 → 三线表 → 公式推导 → 插图 → 参考文献);

  2. PyTorch:跑通 7.3 节的梯度下降例子,理解自动求导;等 AI 子专栏讲神经网络时再深入。

记住 :工具是给模型打工的。先用第一阶段把数据处理练熟,再按需取用第二阶段;LaTeX 别拖到比赛前才学,第一次用模板排完一篇论文,你就知道流程图里"问题重述到参考文献"每一步长什么样了。


十一、小结

到这里,专栏的导读地图集齐了四块拼图:

  • 第 1 篇 给了流程:七步建模闭环,问题重述到论文成稿;
  • 第 2 篇给了方向:七个出题趋势,知道该往哪使劲;
  • 第 3 篇给了地图:七类问题的模型工具箱、六类求解算法,以及模型-算法-工具对照表;
  • 本篇配齐了兵器:NumPy 管数、Pandas 管表、SciPy 管算法、Matplotlib 管图、scikit-learn 管学习、PyTorch 管深度学习,LaTeX 把这一切排版成论文。

其实下一篇的人口增长问题,就是这套工具链的一次预演------curve_fit 做最小二乘拟合、Matplotlib 画"解析解、数值解与真实数据三线重合"的验证图,只不过当时你看到的是故事,现在你看懂的是每一行代码背后"哪个兵器在出力"。

下一篇是专栏前面内容的收束篇 :用一个完整的小例子,把"流程 → 趋势 → 地图 → 兵器"四篇串成一条线------从拿到题目那一刻的定位,到选模型、写代码、画图,最后落成论文。导读篇到此收口,实战篇正式开始。


📌 本文是专栏「数学建模 × AI:从经典模型到智能方法」的第 4 篇文章。

如果你在阅读过程中有任何疑问,欢迎在评论区留言交流。😊

相关推荐
海盗123442 分钟前
AI 新闻日报 2026-10-03:编排写进代码、领域知识打包成技能、具身智能回到班次与价格
人工智能·机器人·人工智能aigc
沐言人生43 分钟前
牛逼!Github上有人开源了,让AI帮你生成数学物理解题视频
人工智能
言乐61 小时前
JavaScript概括前端原理
开发语言·前端·javascript·python·ecmascript
liulilittle1 小时前
短期内不存在通用 AI 工作流魔法
大数据·开发语言·c++·人工智能·llm·agent·tools
别动我齐刘海1 小时前
简历技术栈全面复习总结
c++·人工智能·深度学习·学习·tcp/ip·算法·rpc
AIUCE1 小时前
都说Muse开源了,其实开源的是 gadget SDK,不是 Muse
人工智能
lucas_AI1 小时前
100 个 AI 组队做数学,27 分钟集体沦陷:DeepMind 记录了一场教科书级多智能体事故
人工智能
hetao17338371 小时前
2026-10-03 hetao1733837 的刷题记录
c++·算法
七七安1 小时前
标准卷积和转置卷积
人工智能