很多人学线性代数的时候,最头疼的就是明明理解了概念,却要手工做大量矩阵乘法、求逆、求特征值的计算。一旦数据变成 4 阶、5 阶,草稿纸就不够用了。而 MATLAB 本身就以矩阵为基本运算单位,天然适合用来验证定理、完成计算,甚至解决工程中的数据拟合、图像压缩、主成分分析等问题。本文围绕“大谦MATLAB:线性代数”这条学习主线,整理一份免费的 MATLAB 教程式笔记,从环境准备、矩阵基础操作,一直讲到线性方程组、特征值分解、最小二乘和图像矩阵实战,同时给出常见的报错排查方法和工程最佳实践。无论你是正在学线性代数的学生,还是想用 MATLAB 快速做矩阵计算的工程师,都可以照着本文一步步操作。
1. 为什么要用 MATLAB 学线性代数
1.1 线性代数的工程价值
线性代数不只是数学系的一门基础课,它是控制理论、信号处理、机器学习、计算流体力学、图像处理、结构分析等方向的底层工具。理解矩阵、向量、特征值、特征向量这些概念,能帮助你读懂很多成熟算法:搜索引擎的 PageRank 依赖特征向量,人脸识别中的 PCA 依赖协方差矩阵分解,电路仿真中的节点分析法最终也归结为线性方程组求解。
不过,很多人在学习时容易卡在“计算过程”上。一个 3 阶行列式还能手算,一个 10 阶矩阵求逆就很容易算错。于是学习变成了背公式,而不是理解矩阵背后的几何含义。MATLAB 把“矩阵计算”变成了接近自然语言的命令,矩阵乘法和数学教材中的记号几乎一致,因此是很好的验证工具。你可以把例题输入命令行,立刻得到结果,然后反过来观察规律。
1.2 MATLAB 在线性代数学习中的优势
MATLAB 的变量类型里面,矩阵是最核心的数据结构。你不需要像 C 语言那样用双重循环去实现矩阵乘法,也不需要像 Python 那样显式导入 numpy 库,它原生就支持矩阵运算。比如:
A = [1 2; 3 4]; B = [5 6; 7 8]; C = A * B;这里的A * B就是数学意义上的矩阵乘法。在 MATLAB 中,这种表达方式和教科书上的写法高度一致,学习成本低。
另外,MATLAB 内置了大量线性代数函数,包括行列式det、逆矩阵inv、秩rank、特征值eig、奇异值分解svd、QR 分解qr等。学习者不需要自己造轮子,只需要关注每个函数背后的数学意义以及适用条件。
1.3 本教程的内容安排
本文不追求把所有线性代数知识一次性讲完,而是围绕最基础、最常用的算子展开。内容安排如下:
- 环境准备:安装与命令行基础;
- 核心操作:矩阵创建、索引、四则运算、点运算;
- 线性代数函数:行列式、秩、逆矩阵、特征值、线性方程组求解;
- 实战案例:插值拟合、最小二乘、PCA、图像矩阵处理;
- 常见问题:维度错误、奇异矩阵、浮点误差等;
- 最佳实践:向量化、用左除代替求逆、代码组织。
这样的顺序可以让零基础读者先熟悉 MATLAB 的基本交互方式,再逐步过渡到有数学背景的线性代数计算。
2. 环境准备与基础操作
2.1 MATLAB 安装与版本说明
要运行本文的代码,你首先需要有一个可用的 MATLAB 环境。官方正版渠道包括:校园授权版、个人试用版、MATLAB Online 在线版。如果你所在学校或单位已经购买了 Toolbox 授权,直接通过官网账户安装即可。这里不做安装包和破解类说明,版本方面也不刻意指定旧版,建议使用近几年的正式发布版本,例如 R2022b、R2023b 以及之后的版本。
需要特别留意的是,本文某些示例会用到符号变量或者图像处理函数。如果报错提示找不到syms、rgb2gray,说明当前安装内容不完整,通常需要补充 Symbolic Math Toolbox 或 Image Processing Toolbox。如果只是完成线性代数基础计算,核心产品下的det、inv、eig已经足够。
如果你的电脑暂时无法安装 MATLAB,也可以考虑 GNU Octave,它的语法和 MATLAB 高度兼容,适合练习本文大部分代码。不过部分工具箱差异较大,遇到问题时建议回到 MATLAB 官方文档确认。
2.2 命令行窗口与脚本基础
安装完成后,打开 MATLAB,你会看到命令行窗口和当前文件夹。最简单的使用方式是在命令行窗口中直接输入表达式,回车得到结果。例如:
>> 1 + 2 ans = 3MATLAB 中默认变量名是ans,用来保存上一次的计算结果。为了更清晰地管理数据,我们通常把代码写入脚本文件。点击“新建脚本”,保存为test_linear_algebra.m,然后在脚本中写完代码后点击“运行”,或者直接按 F5。
脚本文件便于保存和修改,也便于复现计算结果。本文后续代码都建议放在脚本文件中执行,而不是一行行复制到命令行,这样当矩阵维度变化时,修改参数后可以重新运行整个流程。
2.3 创建矩阵的基础方法
MATLAB 创建矩阵主要有两个思路:手动输入,或者调用内置函数生成。手动输入时,方括号[]用来界定矩阵,空格或逗号分隔同一行的元素,分号分隔不同行。例如:
% 3 行 3 列矩阵 A = [1 2 3; 4 5 6; 7 8 9]; % 行向量 row = [10 20 30]; % 列向量 col = [1; 2; 3];除了手动输入,还可以使用内置函数快速生成特殊矩阵。常见的有:
Z = zeros(3); % 3x3 全 0 矩阵 O = ones(2, 4); % 2 行 4 列全 1 矩阵 I = eye(4); % 4 阶单位矩阵 R = rand(3); % 3x3 均匀分布随机数矩阵 N = randn(3); % 3x3 标准正态分布随机数矩阵 H = hilb(4); % 4 阶 Hilbert 矩阵,常用于病态矩阵实验这里需要注意:zeros(3)默认生成 3×3 方阵,zeros(2,4)则生成 2 行 4 列矩阵。单位矩阵eye非常常用,因为它对应线性代数中的单位元,很多推导中都离不开它。
3. MATLAB 中的线性代数核心操作
3.1 矩阵的转置、索引与变形
转置在线性代数中就是把矩阵的行和列互换。MATLAB 中有两种写法:
A = [1 2 3; 4 5 6]; B = A.'; % 普通转置 C = A'; % 共轭转置当矩阵元素是实数时,B和C结果相同。但如果 A 是复数矩阵,A'会同时取共轭,而A.'只做行列互换。这是一个容易踩坑的地方。
矩阵索引则是从矩阵中取出子块。MATLAB 索引从 1 开始,和 C 语言从 0 开始不同。常用方式如下:
A = [1 2 3; 4 5 6; 7 8 9]; A(2, 3) % 第 2 行第 3 列元素 A(1, :) % 第 1 行所有元素 A(:, 2) % 第 2 列所有元素 A(1:2, 2:3) % 前两行、第 2 到第 3 列组成的子矩阵 A([1 3], [2 3]) % 第 1 行和第 3 行、第 2 列和第 3 列交叉位置的元素这里冒号:用来表示“全部”或“范围”。如果你需要取出某矩阵的最后一列,可以写成A(:, end),end表示该维度的最后一个索引。
3.2 矩阵四则运算与点运算
矩阵乘法和标量乘法很容易理解,但 MATLAB 中有一个高频困惑点:*与.*的区别。
A * B是标准矩阵乘法,要求 A 的列数等于 B 的行数;A .* B是元素对应相乘,要求 A 和 B 尺寸完全一致。
看一个例子:
A = [1 2; 3 4]; B = [2 0; 1 2]; % 矩阵乘法 M = A * B; % 元素对应乘法 P = A .* B;A * B的结果是:
4 4 10 8而A .* B的结果是:
2 0 3 8类似地,除法和幂运算也有点运算版本:
Q = A ./ B; % 元素对应相除 E = A .^ 2; % 每个元素平方如果不小心把.*写成*,MATLAB 通常会提示维度不匹配。这个错误在初学者中非常常见。
3.3 行列式、秩、迹与逆矩阵
线性代数教材里的核心运算,在 MATLAB 中都有一一对应的函数。以下矩阵均以 3×3 为例:
A = [2 1 0; 1 3 2; 0 1 4]; d = det(A); % 行列式 r = rank(A); % 矩阵的秩 t = trace(A); % 矩阵的迹,主对角线元素之和 B = inv(A); % 逆矩阵需要理解的是,MATLAB 在计算这些函数时采用数值算法,并不是通过展开行列式公式来计算。det(A)返回的是浮点数,因此当结果非常接近 0 时,不能直接断定矩阵不可逆,更好的办法是观察rank或者计算条件数cond(A)。条件数越大,矩阵越接近奇异,求逆结果也越不可靠。
判断一个矩阵是否可逆,不建议使用det(A) == 0这样的写法,因为浮点误差会干扰判断。推荐结合rank和cond来做稳定性评估。
3.4 特征值与特征向量
特征值和特征向量是线性代数中最重要的概念之一。对可对角化矩阵A,特征向量矩阵V和特征值对角矩阵D满足:
A = [2 1; 1 2]; [V, D] = eig(A);运行后,D的对角线元素就是特征值,V的每一列是对应的特征向量。可以验证:
B = A * V; C = V * D;理论上B与C相等,但由于浮点误差,二者之差会在非常小的量级。
如果只需要特征值,可以写成:
e = eig(A);这里有一个容易混淆的点:eig求的是稠密矩阵的全部特征值;如果矩阵规模很大而且是稀疏的,通常使用eigs来求一部分极值特征值。eigs依赖较复杂的迭代算法,初学者不需要深究细节,但要清楚两者的适用场景。
3.5 解线性方程组与最小二乘
线性方程组是线性代数最直接的应用。考虑:
2x + y = 5 x + 3y = 8写成矩阵形式A * x = b:
A = [2 1; 1 3]; b = [5; 8]; x = A \ b;点得到的x就是方程组的解。这里的反斜杠运算符非常重要,它代表“左除”,相当于求解A * x = b。MATLAB 会根据矩阵性质自动选择合适算法,比如高斯消元、LU 分解、QR 分解等,而不是直接计算逆矩阵。推荐使用A \ b而不是x = inv(A) * b,因为左除在数值稳定性和计算效率上都更好。
如果方程组是超定方程组,也就是方程数量多于未知数,通常不存在精确解,此时A \ b会返回最小二乘意义下的解。这个特性在数据拟合中极其有用。
4. 线性代数实战案例
4.1 案例 1:二次多项式插值
假设我们知道三个点(0, 1)、(1, 3)、(2, 7),想找到一个二次多项式f(x) = a x^2 + b x + c精确经过这三个点。把三个点代入后,可以得到一个包含 3 个方程的线性方程组:
x = [0; 1; 2]; y = [1; 3; 7]; % 构造范德蒙德矩阵 V = [x.^2, x, ones(3, 1)]; coeff = V \ y;代码里的x.^2是对x的每一个元素做平方,生成的矩阵V第一列是x^2,第二列是x,第三列是全 1。解出的coeff是[a; b; c]。
运行后得到:
coeff = 1 1 1说明插值多项式是f(x) = x^2 + x + 1。可以快速验证:x = 0时结果为 1,x = 1时为 3,x = 2时为 7。这种构造线性方程组求解系数的方式,是插值和拟合的基础。
4.2 案例 2:最小二乘数据拟合
工程中很少要求曲线精确穿过每个数据点,更多情况是数据带噪声。假设有一组近似满足y = 2t + 1的数据,我们通过线性回归来估计参数:
rng(0); % 固定随机数种子,保证结果可复现 t = linspace(0, 1, 20)'; y = 2 * t + 1 + 0.1 * randn(20, 1); % 构造设计矩阵 X = [t, 1] X = [t, ones(20, 1)]; theta = X \ y;这里的theta(1)是斜率估计值,theta(2)是截距估计值。由于数据噪声存在,估计结果不会严格等于 2 和 1,但会很接近。
背后原理是最小二乘解:
theta_ls = (X' * X) \ (X' * y);和X \ y等价,但直接用左除通常更稳定。通过这个案例,可以直观看出线性代数在回归分析中的核心地位。
4.3 案例 3:PCA 主成分分析
主成分分析是数据降维的经典方法,本质上也是特征值分解的应用。我们生成一组二维数据,然后旋转它,使其存在明显相关性:
rng(1); data = [3 * randn(100, 1) + 2, 0.5 * randn(100, 1) + 3]; % 旋转数据 theta_rot = pi / 6; R = [cos(theta_rot), -sin(theta_rot); sin(theta_rot), cos(theta_rot)]; data = data * R; % 数据中心化 data = data - mean(data); % 协方差矩阵 C = (data' * data) / (size(data, 1) - 1); % 特征值分解 [V, D] = eig(C); [~, idx] = sort(diag(D), 'descend'); V = V(:, idx); % 投影到主成分方向 score = data * V;这个例子把“协方差矩阵”和“特征分解”串在了一起。协方差矩阵C的对角线表示每个维度的方差,特征值表示投影到特征向量方向后方差的大小。排序后,第一个主成分方向就是数据变化最大的方向。PCA 本质上就是在做这样一次坐标系旋转和降维选择。
如果对可视化感兴趣,可以在脚本中加上:
figure; plot(data(:,1), data(:,2), 'o'); hold on; quiver(0, 0, V(1,1), V(2,1), 'r', 'LineWidth', 2); quiver(0, 0, V(1,2), V(2,2), 'b', 'LineWidth', 2); axis equal; legend('data', 'PC1', 'PC2');图中两条箭头就是两个主成分方向。可以看到,数据沿红色箭头方向的波动更大。
4.4 案例 4:图像作为矩阵的简单处理
图像的本质就是一个像素值矩阵。灰度图是二维矩阵,彩色图是三维数组。利用矩阵运算,我们可以快速实现图像裁剪、亮度调整、缩放等操作。
先读取图像并转为灰度矩阵:
img = imread('peppers.png'); % 使用 MATLAB 自带的示例图 gray = rgb2gray(img); M = double(gray);由于imread读入的是无符号 8 位整数类型,直接做加法、乘法可能溢出,所以用double转成浮点型矩阵。现在,裁剪左上角 64×64 区域:
block = M(1:64, 1:64);把整张图变亮 40 个灰度级:
bright = M + 40;把整张图对比度降低,也就是乘以一个小数:
dark = M * 0.6;如果要把结果保存或显示出来,需要先把数值限制在 0 到 255 之间:
dark = max(min(dark, 255), 0); imshow(uint8(dark));这个案例把“图像就是矩阵”这一观念落实到代码中。理解这一点之后,卷积、傅里叶变换、图像压缩等更高级内容,都能从矩阵运算的角度去理解。
5. 常见问题与排查思路
5.1 高频错误对照表
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
Matrix dimensions must agree. | 矩阵乘法或数组运算维度不匹配 | 用size检查矩阵尺寸,确认该用*还是.* |
Matrix must be square. | 对非方阵调用det、inv、eig | 改用pinv求伪逆,或检查矩阵是否应该为方阵 |
Matrix is singular to working precision. | 矩阵接近奇异或严格奇异 | 用rank、cond判断,考虑用pinv或正则化 |
Undefined function 'syms' | 缺少符号数学工具箱 | 安装 Symbolic Math Toolbox 或改用数值方法 |
Unable to read file | 文件路径存在中文或文件不存在 | 把路径改为英文,使用fullfile拼接路径 |
结果出现1.2246e-16 | 浮点计算误差导致 | 不要用==0判断,设置阈值,如abs(x) < 1e-10 |
5.2 数值精度问题
线性代数计算中,浮点误差是不可避免的。比如:
sin(pi)理论上是 0,但 MATLAB 返回1.2246e-16,因为pi本身只是圆周率的浮点近似值。再比如计算行列式时,理论上奇异矩阵的行列式应为 0,但数值结果可能是一个极小的数。此时应使用rank或cond来判断矩阵性质。
如果需要查看更高精度的显示结果,可以用:
format long这只是改变显示精度,不会改变内部计算精度。如果确实需要任意精度计算,就需要符号数学工具箱中的vpa和syms。不过对于大多数工程应用,双精度浮点数已经足够,过多追求高精度反而会影响运行速度。
5.3 工具箱缺失问题
MATLAB 的功能由许多工具箱组成。基础线性代数核心函数不需要额外安装,但一旦用到syms、rgb2gray、eigs等,就可能依赖特定工具箱。遇到报错后,可以先在命令行执行:
which syms which rgb2gray如果输出显示“未找到”,说明缺少对应工具箱。解决方式是安装对应工具箱,或者改写为不依赖该工具箱的实现。比如图像灰度化可以手动计算加权平均值,但没有rgb2gray时手动转换仍然需要矩阵操作,这也可以作为强化矩阵练习的好机会。
5.4 转置和点运算混淆
很多初学者会在需要逐元素运算时,错误使用矩阵乘法。判断标准很简单:如果两个矩阵尺寸完全相同,且你希望对应位置相乘,使用.*;如果希望按线性代数中的矩阵乘法进行行列交互求积,使用*。同理,sin(A)是对 A 的每个元素取正弦,而不是矩阵的“矩阵正弦”函数。如果你确实需要矩阵函数意义上的正弦,需要使用funm(A, @sin),但这个概念在线性代数课程中较少出现,初学阶段不必纠结。
6. 最佳实践与工程建议
6.1 尽量使用向量化运算
MATLAB 对矩阵运算做了大量底层优化。能写成A .* B或A * B的地方,尽量不要用双层 for 循环去逐元素计算。向量化不仅代码更短,而且可读性更好,运行速度也更快。例如计算数组平方和,不要写:
s = 0; for i = 1:length(x) s = s + x(i)^2; end可以一次性写成:
s = x(:)' * x(:);这本质就是向量内积,同时也是线性代数在编程中的体现。
6.2 用左除代替显式求逆
在求解A * x = b时,推荐写成A \ b,不要写inv(A) * b。显式求逆会增加计算量,并且放大数值误差。如果矩阵是奇异或欠秩的,A \ b会给出最小二乘解并附带警告,而inv(A)通常会直接失败或给出不可靠结果。
如果需要求解x * A = b,则对应右除b / A。右除使用场景相对较少,但规则和左除对称。
6.3 代码组织与注释习惯
建议把代码写进脚本或函数文件,而不是在命令行窗口直接粘贴长代码。脚本文件建议使用这样的开头:
%% 清理工作区 clear; close all; clc;不过在实际工程中,不要随手清理所有变量,因为协同开发时其他人的工作区也可能受到影响。更推荐在脚本内部使用局部变量名,并使用function封装核心逻辑。函数文件便于复用,也能避免变量污染。
注释方面,可以在关键矩阵运算前说明它的数学含义,例如“构造设计矩阵 X”,这样一段时间后再读代码,依然能快速理解当时的思路。
6.4 善用帮助文档和调试工具
遇到不熟悉的函数时,命令行执行:
doc inv doc eig doc mldivideMATLAB 自带官方文档是很好的学习资料。调试脚本时,可以在某个行号左侧点击设置断点,然后逐步执行,观察每个变量的尺寸和数值。很多矩阵维度错误,通过在工作区中查看变量大小就能快速定位。
6.5 关于有效数字和格式化输出
有时候我们需要把数值保留两位有效数字。可以直接使用格式化函数:
x = 1234.5678; s = sprintf('%.2g', x); y = str2double(s);%.2g表示保留两位有效数字。如果你的 MATLAB 版本较新,也可以尝试:
y = round(x, 2, 'significant');如果当前版本不支持该语法,MATLAB 会提示错误,这时改用sprintf方式即可。这种方法适合在生成报告、拼接标题时使用,并不会改变数据本身的精度。
6.6 安全与数据管理意识
涉及数据文件读写时,养成备份原始数据的习惯。尤其是做矩阵处理时,如果对原矩阵进行覆盖性赋值,例如直接写M = M * 0.6,一旦结果不理想,原始数据就找不回来了。建议保留原始变量,或者使用save保存副本:
save('data_original.mat', 'M');之后任何时候想恢复,都可以:
load('data_original.mat');这个习惯在实验和工程项目中都非常重要。
7. 延伸方向与学习建议
到这里,你已经能熟练使用 MATLAB 完成线性代数中最常见的计算:矩阵输入、转置、乘法、行列式、秩、逆、特征值以及线性方程组求解。接下来可以继续深入的方向包括:
- 理解 QR 分解、LU 分解、SVD 分解的数值意义;
- 在数据科学中继续学习协方差矩阵、PCA、LDA 等线性方法;
- 在信号处理中学习傅里叶变换与滤波器的矩阵形式;
- 在数值计算中研究病态矩阵、条件数和正则化方法。
如果觉得抽象,可以把 3Blue1Brown 的《线性代数的本质》系列视频作为几何直观补充,再用 MATLAB 把视频中提到的线性变换写成矩阵,自己观察变换效果。比如二维旋转矩阵:
theta = pi / 4; R = [cos(theta), -sin(theta); sin(theta), cos(theta)]; points = [1 0; 0 1]; rotated = points * R';这种“先看几何,再用代码验证”的方式,能让你对矩阵乘法的意义有更深理解。不要怕报错,也别急着追求复杂算法,先从二维小矩阵开始,逐步扩展到高维数据和真实工程问题。掌握几行代码并不难,难的是把线性代数的几何直觉和数值实现连成一条线,这条线一旦打通,后面看很多算法都会轻松不少。