浅记Matlab知识点
参考资料
learning outcomes
记录一些 Matlab 常用语法与技巧
基础概念
数据类型
| 类型 | 说明 |
|---|---|
double |
默认浮点数,64 位 |
single |
单精度浮点数,32 位 |
logical |
布尔值 true/false |
char |
字符向量(单引号) |
string |
字符串数组(双引号) |
cell |
任意类型的容器(大括号) |
struct |
结构体,字段可任意命名 |
categorical |
类别型数据 |
datetime / duration |
时间/时间间隔 |
table / timetable |
表格数据 |
real(x) 与 imag(x) 用于提取复数的实部和虚部,它们不是数据类型
-
字符串
-
字符串比较
strcmp(s1, s2)比较字符串 s1 和 s2 是否相等
strncmp(s1, s2, n)比较字符串 s1 和 s2 的前 n 个字符是否相等
strcmpi(s1, s2)忽略大小写,比较字符串 s1 和 s2 是否相等
strncmpi(s1, s2, n)同理 -
字符串查找与替换
findstr(s1, s2)
strrep(s1, s2, s3)将字符串 s1 中的所有 s2 都替换成 s3
-
变量管理
| 命令 | 作用 |
|---|---|
who |
列出工作区变量名 |
whos |
列出变量名、大小、字节数、类等详细信息 |
clear |
删除全部变量 |
clear var1 var2 |
删除指定变量 |
clearvars -except varlist |
保留特定变量,清除其余 |
save filename var1 var2 |
将变量保存为 .mat 文件 |
load filename |
读取 .mat 文件到工作区 |
工作空间与路径
|
|
数组与矩阵
创建矩阵
| 方法 | 示例 | 说明 |
|---|---|---|
| 直接定义 | A = [1,2,3; 4,5,6]; |
用空格/逗号分列,分号换行 |
zeros, ones |
Z = zeros(3,4); |
全零 / 全一矩阵 |
eye |
I = eye(5); |
单位矩阵 |
rand, randn |
R = rand(2,3); |
均匀/正态随机数 |
linspace, logspace |
x = linspace(0,pi,100); |
等间距向量 |
repmat |
B = repmat(A,2,3); |
重复矩阵 |
meshgrid, ndgrid |
[X,Y] = meshgrid(-2:0.1:2); |
生成网格坐标 |
sparse |
S = sparse(A); |
转为稀疏矩阵 |
gallery |
M = gallery('poisson',5); |
生成常用测试矩阵 |
[A, B] 拼接矩阵时,行数必须相同
[A; B] 列数必须相同
-
常用矩阵函数
1 2 3 4 5 6% 生成特殊矩阵 M = magic(5); % 魔方矩阵 V = vander(1:5); % 范德蒙德矩阵 H = hilb(5); % 希尔伯特矩阵 C = pascal(5); % 帕斯卡矩阵 P = companion([1 -5 6]); % 伴随矩阵
索引与切片
| 索引方式 | 示例 | 说明 |
|---|---|---|
| 线性索引 | A(3) |
按列优先顺序的第 3 个元素 |
| 逻辑索引 | A(A>0) |
取所有正元素 |
: 省略 |
A(:,3) |
取第 3 列 |
end 关键字 |
A(end-1:end,:) |
取倒数第二行到最后一行 |
| 子矩阵 | A(1:2, 3:end) |
取前两行、从第 3 列到末尾 |
A(:,[2,4]) = [] 删除第 2、4 列
矩阵变形与运算
| 操作 | 示例 | 说明 |
|---|---|---|
reshape |
B = reshape(A,4,3); |
改变尺寸(元素不变) |
transpose |
A.' |
转置(不共轭) |
ctranspose |
A' |
共轭转置 |
diag |
d = diag(A); / D = diag(v); |
提取/生成对角矩阵 |
triu / tril |
U = triu(A); |
上/下三角矩阵 |
rot90 |
R = rot90(A,2); |
逆时针旋转 180° |
fliplr / flipud |
B = fliplr(A); |
左右/上下翻转 |
permute |
B = permute(A,[2 1 3]); |
维度置换 |
reshape, squeeze |
A = squeeze(B); |
去除单例维度 |
bsxfun / 隐式扩展 |
C = A + B; (A: m×1, B: 1×n) |
自动广播(R2016b+) |
稀疏矩阵
|
|
特殊容器
| 类型 | 创建方式 | 常用操作 |
|---|---|---|
| Cell array | C = {1, 'text', [1 2]}; |
{} 访问,C{2} 取内容,C(2) 取子单元 |
| Struct array | s(1).name = 'Alice'; s(1).age = 28; |
s(1).name, s(2).age |
| Table | T = table(A,B,'VariableNames',{'A','B'}); |
T.A, T{:,2} |
| Categorical | cat = categorical({'red','blue','red'}); |
categories(cat), ismember(cat,'red') |
运算符与常用函数
基本算术运算
| 运算符 | 说明 |
|---|---|
+ - * / ^ |
加、减、乘、除、乘方(矩阵运算) |
.* ./ .^ |
对应元素的点运算 |
\ |
左除(求解线性方程 AX = B) |
* 为矩阵乘法,.* 为对应元素相乘
/ 为右除(A/B = A*inv(B)),./ 为对应元素除法
点运算示例
|
|
关系与逻辑运算
| 运算符 | 示例 | 说明 |
|---|---|---|
< > <= >= == ~= |
A > 0 |
关系比较,返回逻辑矩阵 |
& | |
A & B |
按元素的逻辑与/或 |
&& || |
if a && b |
短路逻辑,仅用于标量 |
~ |
~A |
逻辑非 |
位运算(整数)
| 运算符 | 示例 | 说明 |
|---|---|---|
bitand, bitor, bitxor |
bitand(a,b) |
位与、位或、位异或 |
bitshift |
bitshift(a,2) |
左移 2 位 |
bitcmp |
bitcmp(a) |
位取反 |
常用数学函数
| 类别 | 常用函数 | 示例 |
|---|---|---|
| 指数/对数 | exp, log, log10, log2 |
y = exp(x); |
| 三角函数 | sin, cos, tan, asin, acos, atansind, cosd, tand(角度) |
y = sin(pi/4);y = sind(45); |
| 双曲函数 | sinh, cosh, tanh |
y = sinh(x); |
| 特殊函数 | erf, erfc, gamma, psi |
y = erf(x); |
| 统计函数 | mean, median, std, var, mode, skewness, kurtosis |
m = mean(v); |
| 线性代数 | det, rank, trace, norm, cond, pinv |
d = det(A); |
| 随机数 | rand, randn, randi, randperm |
r = randi([1,10],5,1); |
| 离散卷积 | conv, deconv, filter, conv2 |
y = conv(x,h); |
| 多项式 | poly, polyval, polyfit, roots, polyder, polyint |
p = polyfit(x,y,3); |
| 插值 | interp1, interp2, interp3, griddedInterpolant, scatteredInterpolant |
yi = interp1(x,y,xi,'spline'); |
| 求根 | fzero, roots, vpasolve (Symbolic) |
r = fzero(@(x) x^3-2,1); |
| 求和/累积 | sum, cumsum, prod, cumprod |
s = sum(A,2); |
format 用于控制显示精度,常用选项有 format short, format long, format bank, format rat
它不影响数值的内部存储,只影响命令窗口的显示
控制结构
条件语句
|
|
switch 语句
|
|
循环语句
|
|
错误捕获
|
|
函数编程
函数文件结构
|
|
注意,文件名必须与函数名相同(myFun.m),注释可用于 help
匿名函数与函数句柄
|
|
可变参数
|
|
对应的输出参数可使用 varargout
持久化变量与全局变量
|
|
|
|
子函数、私有函数、类
同一文件中,主函数下方的额外函数称为子函数,仅在该文件内部可见
私有函数放在 private 子文件夹中,仅同一文件夹下的函数可调用
可以使用 classdef 定义类,支持属性、方法、事件等面向对象高级特性(MATLAB OOP)
绘图与可视化
基本二维绘图
|
|
-
常用绘图属性
属性 示例 说明 'Color''r'/[0.2 0.6 0.8]颜色 'LineStyle''--'线型 'Marker''o'数据点标记 'MarkerSize'8标记大小 'MarkerFaceColor''y'标记填充颜色 -
常用图形属性与导出
命令 说明 axis equal坐标轴等比例 axis tight紧凑坐标范围 grid minor次网格 box on/box off边框 saveas(gcf,'myFig.png')保存为 PNG exportgraphics(gcf,'myFig.pdf','ContentType','vector')高质量矢量图 -
颜色映射、光照、视角
1 2 3 4 5 6 7 8 9 10% 颜色映射 cmap = jet(256); colormap(cmap); caxis([-1 1]); % 颜色范围 % 光照与材质 lighting gouraud; material shiny; camlight headlight;
子图布局
|
|
三维绘图
|
|
数据分析与统计
描述统计
| 函数 | 说明 |
|---|---|
max, min |
最大/最小值(可返回索引) |
sum, prod |
求和/乘积 |
cumsum, cumprod |
累计求和/乘积 |
corrcoef |
皮尔逊相关系数矩阵 |
cov |
协方差矩阵 |
prctile |
百分位数 |
histogram, boxplot |
可视化分布 |
均值 mean(data) |
数据的算术平均值 |
中位数 median(data) |
数据的中间值 |
标准差 std(data) |
数据的标准差 |
极差 range(data) |
最大值与最小值之差 |
偏度 skewness(data) |
数据分布的偏斜程度 |
峰度 kurtosis(data) |
数据分布的峰态 |
线性回归与多项式拟合
|
|
插值与样条
|
|
高级统计(Statistics Toolbox)
| 功能 | 示例 |
|---|---|
ttest, ttest2 |
单样本/双样本 t 检验 |
anova1, anova2 |
方差分析 |
fitlm |
线性模型(含系数显著性) |
fitglm |
广义线性模型 |
kmeans |
K 均值聚类 |
pca |
主成分分析 |
数值计算
微分与积分
|
|
quad、quadl 已被 integral、integral2、integral3 取代,后者支持向量化、奇异点、无限区间等
求解方程
| 目标 | 函数 | 示例 |
|---|---|---|
| 单变量根 | fzero |
r = fzero(@(x) x^3-2,1); |
| 多变量非线性方程组 | fsolve (Optimization Toolbox) |
x = fsolve(@myfun, x0); |
| 线性方程组 | \(左除) |
x = A\b; |
| 多项式根 | roots |
r = roots([1 -5 6]); |
优化
优化问题的核心是定义目标函数和约束条件,然后调用合适的求解器进行求解
无约束最小化(Unconstrained Minimization)
|
|
fun 是一个匿名函数,表示目标函数:$(x-2)^2 + \sin(5x)$,这是我们想要最小化的函数
fminunc 是用于求解无约束优化问题的函数,第二个参数 0 是初始猜测值,即从 $x=0$ 开始搜索最优解
返回值 xmin 是使目标函数取得最小值的 $x$,fval 是对应的最小函数值
注意,
fminunc在实际使用中通常需要配合optimoptions设置优化选项,比如算法类型、容差等,以确保收敛和性能
有约束最小化(Constrained Minimization)
|
|
fmincon 用于求解带约束的非线性优化问题
[1 1] 是变量的初始猜测值
A 和 b 定义了线性不等式约束:$A \cdot x \leq b$,具体为:
$$ \begin{cases} 1 \cdot x_1 + 2 \cdot x_2 \leq 4 \ -1 \cdot x_1 + 2 \cdot x_2 \leq 2 \end{cases} $$
[] 表示没有线性等式约束
lb = [0 0] 是变量的下界约束,即 $x_1 \geq 0, x_2 \geq 0$
其他参数为空,表示无上界或非线性约束
返回值 xc 是满足约束条件并使目标函数最小的变量值,fvalc 是对应的最小函数值
常微分方程(ODE)
|
|
常用求解器:
| 求解器 | 适用场景 |
|---|---|
ode45 |
非刚性(中等精度) |
ode23 |
低精度、快速 |
ode15s |
刚性问题 |
ode23t |
事件驱动、刚性 |
ode113 |
高精度、光滑问题 |
ode15i |
隐式微分代数方程 (DAE) |
可通过 odeset 设置容差、事件函数、输出函数等。
矩阵分解与特征
| 分解 | 函数 | 备注 |
|---|---|---|
| LU | [L,U,P] = lu(A) |
用于求解线性方程 |
| QR | [Q,R] = qr(A) |
正交化 |
| Cholesky | R = chol(A) |
对称正定矩阵 |
| SVD | [U,S,V] = svd(A) |
奇异值分解,适用于任意矩阵 |
| 特征值 | [V,D] = eig(A) |
eig(A,'vector') 返回特征值向量 |
| 逆 | inv(A) |
推荐用 A\B 代替 inv(A) |
为什么推荐用 A\B 代替 inv(A)?
直接计算矩阵的逆 inv(A) 会显著放大数值误差,尤其当 矩阵接近奇异或条件数较大 时,误差更明显
A\B 是 MATLAB 推荐的求解线性方程组的方法,它底层使用高效且稳定的 矩阵分解(如 LU 分解)来求解 $Ax = B$,避免了显式计算逆矩阵
|
|
这里 eye(size(A)) 是与 A 同尺寸的单位矩阵,A \ I 实际上是求解 $AX = I$,解 $X$ 就是 $A$ 的逆矩阵
-
用
inv(A)和A\B来解线性方程组,以及如何用A\eye(size(A))来计算逆矩阵1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30% 构造一个方阵 A 和向量 b A = [3, 1, 2; 6, 3, 4; 3, 1, 5]; b = [0.5; 1; 1.5]; % 1. 用 inv(A) 显式求逆,再乘以 b 求解 x x_inv = inv(A) * b; % 2. 用 A\b 直接求解线性方程组 x_backslash = A \ b; % 3. 计算矩阵 A 的逆矩阵(不推荐,但演示用) A_inv = A \ eye(size(A)); % 验证 A * A_inv 是否接近单位矩阵 identity_approx = A * A_inv; % 显示结果 disp('用 inv(A)*b 求解结果 x_inv:'); disp(x_inv); disp('用 A\b 求解结果 x_backslash:'); disp(x_backslash); disp('用 A\eye(size(A)) 计算的逆矩阵 A_inv:'); disp(A_inv); disp('A * A_inv(应接近单位矩阵):'); disp(identity_approx);x_inv和x_backslash两者结果非常接近,但A\b更稳定且速度更快
A_inv是矩阵A的逆矩阵,理论上满足A * A_inv = I,identity_approx会非常接近单位矩阵
在实际应用中,求解线性方程组建议用A\b,而不是先求逆再乘
符号计算(Symbolic Math Toolbox)
MATLAB 的符号计算工具箱允许你对数学表达式进行符号操作,而不是数值计算
这样你可以进行微分、积分、方程求解等数学推导,得到的是 解析表达式而非数值结果,适合需要解析解的数学、工程和科学计算任务
|
|
-
示例:求解微分方程的解析解
假设我们有一个简单的常微分方程 $\frac{dy}{dx} + y = \sin(x)$
要求解函数 $y(x)$1 2 3 4 5 6 7 8 9 10 11syms y(x) % 定义微分方程 ode = diff(y, x) + y == sin(x); % 求解析解 sol = dsolve(ode); % 显示结果 disp('微分方程的解析解为:'); pretty(sol)运行后,MATLAB 会返回一个解析解,通常是一个符号表达式,类似于:
$$ y(x) = \frac{1}{2} \left(\sin(x) - \cos(x)\right) + C e^{-x} $$
$\frac{1}{2}(\sin(x) - \cos(x))$ 是该微分方程的一个特解
$C e^{-x}$ 是齐次方程对应的通解,$C$ 是积分常数
性能优化与调试
预分配
|
|
向量化
|
|
并行计算
|
|
前提:需要 Parallel Computing Toolbox
Profiling 与计时
|
|
调试技巧
| 命令 | 说明 |
|---|---|
dbstop if error |
出错时自动进入调试模式 |
keyboard |
手动进入交互调试 |
dbcont, dbquit |
继续或退出调试 |
disp, fprintf |
打印变量值 |
mlint / codeAnalyzer |
静态代码检查 |
常见错误与注意事项
| 常见错误 | 说明 | 纠正方式 |
|---|---|---|
| 索引越界 | A(5) 超出矩阵维度 |
使用 size(A) 检查,或 end 关键字 |
| 点运算忘记 | A*B(矩阵乘)误写为 A.*B(对应元素乘) |
根据需求选择 * 或 .* |
format 与存储混淆 |
format long 只影响显示,数值本身不变 |
|
clear all 过度使用 |
会清除路径、函数缓存,导致性能下降 | 使用 clearvars,或 clear 指定变量 |
| 循环中动态增长数组 | 速度极慢 | 预分配或使用 cell/struct 进行累积 |
使用 == 比较浮点数 |
直接相等判断不可靠 | 使用 abs(a-b) < eps 或 isequaln |
| 未开启向量化 | 代码慢 | 利用矩阵运算、bsxfun、隐式扩展 |
for 循环中的 i 与 $\sqrt{-1}$ 冲突 |
i 被重新定义为变量 |
在 MATLAB 中 i 和 j 默认是复数单位,表示 $\sqrt{-1}$。但 i 和 j 也可以被当作普通变量名使用,故需要避免使用 i/j 作为循环计数器 |
| 路径冲突 | 同名函数被自定义文件覆盖 | 使用 which -all funcName 检查路径优先级 |
实例代码
模拟退火算法
下面是模拟退火(Simulated Annealing)的通用实现,并用其求解 Rastrigin 函数的全局最小值
核心函数 simulatedAnnealing.m
|
|
T0 为初始温度,alpha 为冷却系数(常取 0.8~0.99),maxIterPerTemp 为每个温度的内部迭代次数
采用 高斯扰动 x_new = x_curr + sigma*randn,其中 sigma 随温度线性衰减,使得在高温时搜索范围大,低温时搜索更细致
若新解更好则必接受;否则以概率 exp(-ΔE/T) 接受,模拟“热运动”
简单的几何降温 T = alpha * T,也可以改为对数或指数等更复杂的调度
温度低于 T_min 或迭代次数超过上限 maxIter 时终止迭代
-
邻域解投影(clip)
若提供了变量上下界bounds,则对产生的邻域解进行投影
目的是确保解始终满足变量的上下界约束假设变量 $x$ 的每个分量 $x_i$ 都有对应的下界 $lb_i$ 和上界 $ub_i$,即:$lb_i \leq x_i \leq ub_i$
算法在搜索新解时,通常会对当前解做扰动(比如加上一个随机噪声),这可能导致新解某些分量超出预设的上下界1 2 3 4if ~isempty(options.bounds) x_new = max(x_new, options.bounds(:,1)); % 将所有小于下界的分量拉回到下界 x_new = min(x_new, options.bounds(:,2)); % 将所有大于上界的分量拉回到上界 end通过对每个分量分别进行限制:如果 $x_i^{new} < lb_i$,就将其设为 $lb_i$;如果 $x_i^{new} > ub_i$,就将其设为 $ub_i$;否则保持不变
这样保证了新解始终在允许的搜索空间内
使用示例:Rastrigin 函数(常用的多峰基准函数)
|
|
-
运行结果(示例)
1 2 3 4 5 6Iter = 500, T = 2.3782e-02, f_best = 1.234567e-03 Iter = 1000, T = 5.6471e-03, f_best = 3.456789e-04 ... === 结果 === 最优解 x* = [0.00123, -0.00087] 对应目标值 f(x*) = 0.000123 -
如何在实际问题中使用
-
定义目标函数
对于 连续 优化问题,只需返回标量目标值即可
若是 离散 或 组合 优化(如旅行商问题),只需改写邻域生成方式(例如交换两个城市的顺序)以及约束处理 -
设置参数
T0越大,初始搜索范围越广,但收敛速度会变慢
alpha越接近 1,降温更慢,搜索更细致;但迭代次数会增多
maxIterPerTemp与stepSize共同决定每个温度层的“探索强度”常用经验:
T0 ≈ (ΔE_max) / log(acceptance_rate),其中ΔE_max为目标函数在随机点的最大差值,acceptance_rate设为 0.8~0.9 -
约束
若有 边界约束,直接使用options.bounds,函数会自动投影
对于 更复杂的约束(如线性/非线性不等式),可以在生成新解后使用 罚函数 或 投影 方法自行处理 -
调参技巧
先在 小规模(低维、松弛的约束)上调试参数,观察收敛曲线
若出现 早熟收敛(很快停在局部最优),可以尝试增大T0或alpha(放慢降温);增加maxIterPerTemp(在每个温度层多搜索);使用 自适应步长:sigma = sigma0 * (1 + c*iter/ maxIter)
MATLAB 自带的
simulannealbnd已实现了更为完善的退火调度、约束处理和并行加速
其他考虑的方向:比如加入 自适应冷却、多点并行搜索、或是针对特定离散问题的邻域设计 -
模块化
如果有多个 .m 文件,想要实现模块化调用,可以通过函数调用的方式来组织代码
将代码封装成函数
每个功能模块写成一个函数,保存在单独的 .m 文件中,文件名和函数名一致
-
文件
moduleA.m1 2 3 4function output = moduleA(input) % 这里写模块A的代码 output = input^2; % 示例操作 end -
文件
moduleB.m1 2 3 4function result = moduleB(x, y) % 模块B的代码 result = x + y; end
路径管理
确保所有模块函数所在的文件夹都在 MATLAB 的路径中。可以通过:
|
|
或者在 MATLAB 界面中使用“Set Path”工具添加路径
在主程序中调用这些函数
主程序可以是一个脚本或者函数,调用这些模块函数:
|
|
使用类(可选)
如果模块之间关系复杂,可以考虑用面向对象编程(OOP),定义类和方法
|
|
调用:
|
|