【Numpy】 第三部分:矩阵运算与线性代数(计算篇)

第三部分:矩阵运算与线性代数(计算篇)

矩阵计算与线性代数是科学计算的核心。在摆脱传统商业软件、转向 Python 科学计算生态时,深刻理解 NumPy 的底层代数运算规则是构建高效仿真系统(如状态空间求解、系统参数辨识)的关键所在。本篇将全面解析从标量广播到高级矩阵分解的核心方法。

1. 广播机制(Broadcasting)

广播是 NumPy 最强大的特性之一。当两个形状不完全相同的数组进行算术运算时,NumPy 会自动触发广播机制,通过在虚拟层面上"复制"较小数组的维度,使其形状与较大数组对齐,从而避免了显式的 Python 循环。

核心规则:从右往左比对数组的形状维度。如果两个维度相等,或者其中一个维度为 1,则它们是兼容的。

  • 广播运算示例:

    在多智能体系统仿真中,常需要给一批智能体的状态矩阵加上同一个全局偏移向量。

    python 复制代码
    import numpy as np
    
    # 3 个智能体的二维坐标矩阵,形状 (3, 2)
    agent_states = np.array([[10.0, 20.0], 
                             [15.0, 25.0], 
                             [5.0, 10.0]])
    
    # 全局坐标偏移向量,形状 (2,)
    offset = np.array([-5.0, 5.0])
    
    # 触发广播:(2,) 会被看作 (1, 2),然后在第 0 维复制 3 次匹配 (3, 2)
    updated_states = agent_states + offset 
    
    print(updated_states)
    # [[ 5. 25.]
    #  [10. 30.]
    #  [ 0. 15.]]

2. 逐元素运算

所有的加减乘除(+, -, *, /)以及数学函数默认都是逐元素(Element-wise)执行的。这与线性代数中的矩阵乘法完全不同。

  • 四则运算与非线性激活:

    python 复制代码
    A = np.array([[1, 2], [3, 4]])
    B = np.array([[2, 2], [2, 2]])
    
    # 逐元素乘法(哈达玛积),对应位置元素相乘
    element_mul = A * B 
    print(element_mul)
    # [[2 4]
    #  [6 8]]
    
    # 常见非线性数学函数
    exp_A = np.exp(A)    # e^x
    log_A = np.log(A)    # ln(x)
    sqrt_A = np.sqrt(A)  # 根号 x

3. 点积与矩阵乘法

这是控制理论与信号处理中最频繁的操作,用于计算状态转移 xk+1=Axk+Bukx_{k+1} = Ax_k + Bu_kxk+1=Axk+Buk 或构建增益矩阵。

  • np.dot, @, np.matmul:

    这三者在处理二维矩阵时功能等价,都执行标准的矩阵乘法。工程实践中,最推荐使用 Python 3.5 引入的 @ 运算符,代码最具可读性。对于高维张量(Batch 运算),@ 和 np.matmul 会将最后两个维度视为矩阵进行批量乘法。

    python 复制代码
    A = np.array([[1, 2], [3, 4]]) # 状态矩阵 (2, 2)
    x = np.array([[1], [2]])       # 状态向量 (2, 1)
    
    # 标准矩阵乘法
    x_next = A @ x  # 等价于 np.matmul(A, x) 或 np.dot(A, x)
    print(x_next)
    # [[ 5]
    #  [11]]
  • np.inner 与 np.outer:

    内积用于计算向量投影或误差标量,外积(张量积)常用于自适应算法中基于单个误差向量对权重矩阵进行秩一更新。

    python 复制代码
    u = np.array([1, 2, 3])
    v = np.array([0, 1, 0])
    
    # 内积:计算对应元素乘积之和
    inner_prod = np.inner(u, v) 
    print(inner_prod)
    # 2
    
    # 外积:u 作为列向量乘 v 作为行向量,生成 (3, 3) 矩阵
    outer_prod = np.outer(u, v)
    print(outer_prod)
    # [[0 1 0]
    #  [0 2 0]
    #  [0 3 0]]

4. 高级线性代数(np.linalg 模块)

np.linalg 封装了底层的 BLAS/LAPACK 库,用于处理复杂的矩阵代数运算。

  • 逆矩阵与伪逆(inv, pinv):

    当方阵满秩时使用 inv 求逆。在无模型自适应控制或数据驱动辨识中,输入输出数据矩阵往往不是方阵,此时需要通过广义逆(伪逆)来求解最小二乘参数估计。

    python 复制代码
    from numpy.linalg import inv, pinv
    
    # 满秩方阵求逆
    M = np.array([[1, 2], [3, 4]])
    M_inv = inv(M)
    
    # 非方阵求伪逆(例如 3 个样本,2 个特征的数据矩阵)
    Phi = np.array([[1, 0], [1, 1], [0, 1]])
    Phi_pinv = pinv(Phi)
    print(Phi_pinv)
    # [[ 0.66666667  0.33333333 -0.33333333]
    #  [-0.33333333  0.33333333  0.66666667]]
  • 特征值与特征向量(eig, eigh):

    用于分析系统状态矩阵的极点分布,判断动力学系统的稳定性。如果已知矩阵是对称阵(如李雅普诺夫方程中的 PPP 矩阵或协方差矩阵),使用 eigh 计算速度更快且在数值上更稳定。

    python 复制代码
    from numpy.linalg import eig, eigh
    
    A = np.array([[0, 1], [-2, -3]])
    
    # 计算特征值与特征向量
    eigenvalues, eigenvectors = eig(A)
    print("系统极点:", eigenvalues)
    # 系统极点: [-1. -2.]  (实部均小于0,连续系统稳定)
    
    # 对称阵的特征值计算
    P = np.array([[2, 1], [1, 2]])
    evals_sym, evecs_sym = eigh(P)
  • 矩阵分解与度量(svd, cholesky, norm, det):

    奇异值分解(SVD)常用于降维或能控/能观性分析;Cholesky 分解用于正定矩阵;范数用于衡量误差大小或协同控制中的相对距离;行列式用于判断矩阵是否可逆。

    python 复制代码
    from numpy.linalg import svd, cholesky, norm, det
    
    # 1. 奇异值分解 SVD
    # 将矩阵分解为 U, Sigma, V^T
    Data = np.array([[1, 2, 0], [0, 1, 1]])
    U, S, Vh = svd(Data)
    print("奇异值:", S)
    # 奇异值: [2.31295259 0.81232822]
    
    # 2. Cholesky 分解(要求方阵对称正定)
    # 分解为下三角矩阵 L,满足 P = L @ L.T
    L = cholesky(P) 
    
    # 3. 向量/矩阵范数(默认求解 2-范数/欧几里得距离)
    err = np.array([3, -4])
    error_norm = norm(err)
    print("误差 L2 范数:", error_norm)
    # 误差 L2 范数: 5.0
    
    # 4. 行列式计算
    matrix_det = det(M)
    print("行列式值:", matrix_det)
    # 行列式值: -2.0000000000000004
相关推荐
BK贝壳7 小时前
亿级用户签到位图选型复盘:用 bool-hybrid-array 扛冷启动打卡,也把它和 Roaring/Redis 的边界测清楚了
数据结构·python·性能优化·numpy
2601_966949658 小时前
如何根据研究的起止时间截取分钟级行情?Python 实战与 QuantDash 数据处理指南
开发语言·python·pandas·量化交易·1024程序员节·股票数据·quantdash
在世修行13 小时前
智学文枢:页面切换与跨页数据预填
python·桌面应用·signal·1024程序员节·pyside·跨页跳转·状态预填
2601_9628857213 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python
打工仔折腾 AI13 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
信誓旦旦的程序猿14 小时前
【Python量化实战宝典 #21】北向资金跟随手册:聪明钱择时信号(Python 可跑)
python·1024程序员节·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
严谨的麻辣烫14 小时前
静态 ISP 代理请求超时怎么排查?Python 与 curl 实战
python·http·requests·1024程序员节·网络排障
KeepRobots16 小时前
11-01 温哥华不回拨:用 60 行 Python 查你的工单系统会不会差一小时(KeepRobots 工程笔记)
python
xiao77mwq16 小时前
你以为 OCR 慢?实测 81.3 s 里全是故障代价:如何把「定格态」消掉,让耗时从 6.5 s 到 13 倍差距显出原形
python
深圳市益普科技有限公司16 小时前
半导体良率管理YMS:良率与设备参数的相关性,先拉哪几组数据
人工智能·python·算法