Julia 学习笔记——线性代数
数组是 Julia 的核心内容之一,而线性代数则是它真正发力的主场。虽然前面的数组笔记已经涉及了一些矩阵和广播,但如果不单独整理一篇,很多线性代数语义还是容易和“普通数组运算”混在一起。
概述
Julia 的线性代数体验和 Python/Numpy、MATLAB 既相似又不同:
- 和 MATLAB 一样,矩阵乘法直接使用
*; - 和 Python/Numpy 一样,元素访问写成
A[i, j]; - 但 Julia 的标准库
LinearAlgebra还引入了很多特殊矩阵类型和分解对象,它们不是简单的“二维数组”。
因此看 Julia 里的线性代数代码时,需要同时区分:
- 这是普通数组操作;
- 还是线性代数意义上的操作;
- 结果是立即物化的数组,还是带语义的特殊对象。
LinearAlgebra 标准库
线性代数相关功能主要来自标准库:
1 | using LinearAlgebra |
它不是默认自动导入的,但属于 Julia 自带标准库,不需要额外安装。
向量与矩阵
创建
1 | x = [1, 2, 3] # Vector |
这里要特别注意:Julia 的 Vector 是真正的一维数组,而不是 MATLAB 那种伪装成矩阵的行向量/列向量。
尺寸
1 | size(x) # (3,) |
基本线性代数运算
矩阵乘法
1 | A = [1 2; 3 4] |
这和 MATLAB 相同,但和 Numpy 不同。Numpy 中 * 默认是逐元素乘法,Julia 里 * 默认就是线性代数乘法。
向量内积
常见做法:
1 | x = [1, 2, 3] |
虽然也可以写某些转置乘法形式,但日常更推荐直接用 dot,语义最清楚。
逐元素运算
如果想做逐元素乘法,仍然要使用点语法:
1 | x .* y |
不要把线性代数乘法和逐元素乘法混在一起。
转置与共轭转置
'
在 Julia 里:
1 | A' |
表示 adjoint,也就是实数情形下的转置、复数情形下的共轭转置。
这和 MATLAB 的 ' 非常接近。
transpose
如果只想做单纯转置,不希望共轭参与,更适合显式使用:
1 | transpose(A) |
对于复数矩阵,这一点尤其需要注意。
adjoint
也可以直接写:
1 | adjoint(A) |
这比单独写 ' 更明确。
单位矩阵与特殊矩阵
I
Julia 提供了一个很特别的单位矩阵对象:
1 | I |
它不是普通的稠密矩阵,而是 UniformScaling 对象。
例如:
1 | A = [1 2; 3 4] |
如果需要具体尺寸的矩阵,可以显式构造:
1 | Matrix(I, 3, 3) |
Diagonal
1 | D = Diagonal([1, 2, 3]) |
这不是普通 Matrix,而是带结构信息的对角矩阵类型。
三角矩阵
1 | U = UpperTriangular([1 2; 3 4]) |
这些类型保留了矩阵结构信息,后续求解和分解时往往更高效。
线性方程组
反斜杠 \
Julia 中求解线性方程组最常见的写法是:
1 | A = [3.0 1.0; 1.0 2.0] |
这表示求解:
1 | A * x = b |
这和 MATLAB 的 \ 写法非常接近。
重要的是:通常不建议先求逆再相乘。也就是不要轻易写成:
1 | inv(A) * b |
无论是数值稳定性还是性能,通常都不如直接 A \ b。
范数与迹
norm
1 | norm([3, 4]) # 5.0 |
默认通常是 2-范数或 Frobenius 范数,具体取决于对象类型。
tr
矩阵迹:
1 | tr([1 2; 3 4]) # 5 |
行列式与秩
1 | det(A) |
这些接口都比较直接,但要注意:
- 浮点数情形下,秩和奇异性判断都依赖数值阈值;
- 不要把它们想成完全符号意义上的精确数学对象。
特征值与特征向量
1 | vals = eigvals(A) |
eigen(A) 返回的不只是向量,还包括特征值和特征向量等信息。
例如:
1 | E.values |
矩阵分解
Julia 在线性代数里一个很有代表性的设计是:分解结果通常不是直接返回若干裸数组,而是返回带语义的分解对象。
LU 分解
1 | F = lu(A) |
可以访问:
1 | F.L |
QR 分解
1 | F = qr(A) |
Cholesky 分解
适用于对称正定矩阵:
1 | F = cholesky(A) |
SVD
1 | F = svd(A) |
这些对象风格和 MATLAB、Numpy 都略有不同,但一旦适应之后会觉得很自然,因为它们把“分解结果是一个对象”这件事表达得更完整。
结构矩阵与惰性语义
Julia 很强调“保留结构信息”。
例如:
- 对角矩阵不是普通稠密矩阵;
- 三角矩阵不是普通稠密矩阵;
- 单位矩阵
I甚至连尺寸都可以按上下文推断。
这意味着:
- 代码语义更清晰;
- 某些操作不需要立刻物化完整矩阵;
- 性能和内存通常也更有优势。
广播与线性代数不要混淆
这是初学 Julia 线性代数时很容易犯错的地方。
例如:
1 | A * B # 线性代数乘法 |
这套区分和 MATLAB 很像,但如果来自 Python/Numpy,就必须反复提醒自己。
小结
Julia 的线性代数写法有几个地方很像 MATLAB,但真正用起来又比 MATLAB 更强调对象语义和结构信息。*、\、' 这些操作不能按普通数组运算去理解,LinearAlgebra 里很多结果也不只是“返回一个数组”,而是返回带结构的对象,这一点需要尽快适应。
