欢迎光临
我们一直在努力

Python NumPy - 线性代数运算 矩阵的逆与行列式

在这里插入图片描述

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕NumPy这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

  • Python NumPy – 线性代数运算:矩阵的逆与行列式 🧮
    • 矩阵基础知识回顾 🔢
    • 行列式的定义与意义 📊
      • 什么是行列式?
      • 行列式的几何意义
      • 行列式的性质
    • NumPy中计算行列式的方法 🛠️
      • 行列式的实际应用
        • 1. 判断矩阵是否可逆
        • 2. 计算变换的缩放因子
    • 矩阵的逆及其重要性 🔁
      • 什么是矩阵的逆?
      • 矩阵逆的存在条件
      • NumPy中计算矩阵逆的方法
    • 矩阵逆的实际应用场景 💡
      • 1. 解线性方程组
      • 2. 最小二乘问题
      • 3. 协方差矩阵的逆(精度矩阵)
    • 数值稳定性和计算注意事项 ⚠️
      • 条件数的概念
      • 避免直接求逆的替代方法
    • 特殊类型的矩阵及其逆 🔬
      • 对称矩阵
      • 正定矩阵
    • 实际应用案例分析 📈
      • 案例1:图像变换
      • 案例2:多元线性回归
      • 案例3:马尔可夫链稳态分析
    • 高级主题和优化技巧 🚀
      • 并行计算和性能优化
      • 内存效率考虑
    • 错误处理和调试技巧 🛠️
    • 科学计算库对比分析 📊
    • mermaid流程图展示
    • 最佳实践总结 ✅
      • 1. 选择合适的计算方法
      • 2. 内存和性能优化
      • 3. 数值稳定性保证
    • 扩展资源和进一步学习 🔍
      • 在线教程和文档
      • 学术资源
      • 实践项目
    • 总结与展望 🎯
      • 关键要点回顾:
      • 未来发展方向:

Python NumPy – 线性代数运算:矩阵的逆与行列式 🧮

在现代科学计算和数据分析中,线性代数扮演着至关重要的角色。从机器学习算法到图像处理,从金融建模到物理仿真,矩阵运算无处不在。NumPy作为Python生态系统中最基础也是最重要的数值计算库,为我们提供了强大的线性代数运算功能。

今天,我们将深入探讨NumPy中的两个核心概念:矩阵的逆和行列式。这两个概念不仅是线性代数理论的基础,更是在实际应用中解决各种问题的关键工具。

矩阵基础知识回顾 🔢

在开始深入了解之前,让我们先简单回顾一下矩阵的基本概念。矩阵是一个按照长方阵列排列的复数或实数集合,用方括号括起来。矩阵的行数和列数决定了它的维度。

import numpy as np

# 创建一个3×3的矩阵
matrix = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])

print("原始矩阵:")
print(matrix)
print(f"矩阵形状: {matrix.shape}")

输出结果:

原始矩阵:
[[1 2 3]
[4 5 6]
[7 8 9]]
矩阵形状: (3, 3)

行列式的定义与意义 📊

什么是行列式?

行列式是方阵的一个标量值,它提供了一个关于矩阵的重要信息。对于n×n的方阵A,其行列式通常记作det(A)或|A|。

行列式的几何意义

行列式的绝对值表示由矩阵列向量构成的平行多面体的体积。如果行列式为正,则这些向量遵循右手定则;如果为负,则遵循左手定则;如果为零,则这些向量线性相关。

import numpy as np

# 创建不同的矩阵来演示行列式的含义
print("=== 行列式示例 ===")

# 单位矩阵 – 行列式为1
identity_matrix = np.eye(3)
det_identity = np.linalg.det(identity_matrix)
print(f"单位矩阵:\\n{identity_matrix}")
print(f"行列式: {det_identity}\\n")

# 缩放矩阵 – 行列式等于缩放因子的乘积
scaling_matrix = np.array([[2, 0, 0],
[0, 3, 0],
[0, 0, 1]])
det_scaling = np.linalg.det(scaling_matrix)
print(f"缩放矩阵:\\n{scaling_matrix}")
print(f"行列式: {det_scaling} (2×3×1 = 6)\\n")

# 奇异矩阵 – 行列式为0
singular_matrix = np.array([[1, 2, 3],
[2, 4, 6], # 第二行是第一行的2倍
[1, 1, 1]])
det_singular = np.linalg.det(singular_matrix)
print(f"奇异矩阵:\\n{singular_matrix}")
print(f"行列式: {det_singular} (行向量线性相关)")

行列式的性质

行列式具有许多重要性质,理解这些性质有助于我们更好地使用它们:

  • 转置不变性:矩阵与其转置的行列式相等
  • 行交换:交换两行会改变行列式的符号
  • 行倍乘:某一行乘以常数k,行列式也乘以k
  • 行加法:将一行的倍数加到另一行,行列式不变
  • # 演示行列式的性质
    print("=== 行列式的性质演示 ===")

    original_matrix = np.random.rand(3, 3)
    print(f"原始矩阵:\\n{original_matrix}")

    # 性质1:转置不变性
    det_original = np.linalg.det(original_matrix)
    det_transpose = np.linalg.det(original_matrix.T)
    print(f"\\n原矩阵行列式: {det_original}")
    print(f"转置矩阵行列式: {det_transpose}")
    print(f"是否相等: {np.isclose(det_original, det_transpose)}")

    # 性质2:行交换改变符号
    swapped_matrix = original_matrix.copy()
    swapped_matrix[[0, 1]] = swapped_matrix[[1, 0]] # 交换第0行和第1行
    det_swapped = np.linalg.det(swapped_matrix)
    print(f"\\n交换行后行列式: {det_swapped}")
    print(f"是否变号: {np.isclose(det_original, det_swapped)}")

    NumPy中计算行列式的方法 🛠️

    NumPy提供了numpy.linalg.det()函数来计算矩阵的行列式。这是一个非常高效且准确的实现。

    import numpy as np
    from scipy import linalg

    # 不同大小的矩阵行列式计算
    print("=== 不同大小矩阵的行列式 ===")

    # 2×2矩阵
    matrix_2x2 = np.array([[2, 3],
    [1, 4]])
    det_2x2 = np.linalg.det(matrix_2x2)
    print(f"2×2矩阵:\\n{matrix_2x2}")
    print(f"行列式: {det_2x2}")
    print(f"手工计算验证: 2×4 – 3×1 = {2*4 3*1}\\n")

    # 3×3矩阵
    matrix_3x3 = np.array([[1, 2, 3],
    [0, 1, 4],
    [5, 6, 0]])
    det_3x3 = np.linalg.det(matrix_3x3)
    print(f"3×3矩阵:\\n{matrix_3x3}")
    print(f"行列式: {det_3x3}\\n")

    # 大型随机矩阵
    large_matrix = np.random.rand(10, 10)
    det_large = np.linalg.det(large_matrix)
    print(f"10×10随机矩阵的行列式: {det_large}")

    行列式的实际应用

    行列式在许多实际场景中有重要应用:

    1. 判断矩阵是否可逆

    只有行列式不为零的方阵才存在逆矩阵。

    def is_invertible(matrix):
    """判断矩阵是否可逆"""
    det = np.linalg.det(matrix)
    return not np.isclose(det, 0)

    # 测试不同矩阵的可逆性
    test_matrices = [
    np.array([[1, 2], [3, 4]]), # 可逆
    np.array([[1, 2], [2, 4]]), # 不可逆(奇异)
    np.eye(3), # 可逆(单位矩阵)
    np.zeros((2, 2)) # 不可逆(零矩阵)
    ]

    for i, matrix in enumerate(test_matrices):
    invertible = is_invertible(matrix)
    det = np.linalg.det(matrix)
    print(f"矩阵{i+1}: 行列式={det:.6f}, 可逆={invertible}")

    2. 计算变换的缩放因子

    在线性变换中,行列式的绝对值表示面积或体积的变化比例。

    # 二维线性变换示例
    def transformation_area_change(transformation_matrix, shape_area):
    """计算线性变换对面积的影响"""
    det = np.linalg.det(transformation_matrix)
    new_area = abs(det) * shape_area
    return new_area, det

    # 旋转矩阵(行列式为1,保持面积不变)
    rotation_matrix = np.array([[np.cos(np.pi/4), np.sin(np.pi/4)],
    [np.sin(np.pi/4), np.cos(np.pi/4)]])
    area_change_rot, det_rot = transformation_area_change(rotation_matrix, 10)
    print(f"旋转矩阵行列式: {det_rot}")
    print(f"10单位面积经过旋转变换后面积: {area_change_rot}")

    # 缩放矩阵
    scaling_matrix = np.array([[2, 0], [0, 3]])
    area_change_scale, det_scale = transformation_area_change(scaling_matrix, 5)
    print(f"缩放矩阵行列式: {det_scale}")
    print(f"5单位面积经过缩放变换后面积: {area_change_scale}")

    矩阵的逆及其重要性 🔁

    什么是矩阵的逆?

    对于n×n的方阵A,如果存在另一个n×n的矩阵B,使得AB = BA = I(I为单位矩阵),那么B就是A的逆矩阵,记作A⁻¹。

    # 演示矩阵与其逆矩阵的关系
    print("=== 矩阵逆的基本概念 ===")

    # 创建一个可逆矩阵
    A = np.array([[2, 1],
    [1, 1]])
    print(f"原始矩阵 A:\\n{A}")

    # 计算逆矩阵
    A_inv = np.linalg.inv(A)
    print(f"逆矩阵 A⁻¹:\\n{A_inv}")

    # 验证 A × A⁻¹ = I
    product = np.dot(A, A_inv)
    print(f"A × A⁻¹:\\n{product}")
    print(f"是否接近单位矩阵: {np.allclose(product, np.eye(2))}")

    矩阵逆的存在条件

    并非所有矩阵都有逆矩阵。一个矩阵有逆矩阵当且仅当它是非奇异的(即行列式不为零)。

    def check_matrix_invertibility(matrix, name="矩阵"):
    """检查矩阵的可逆性并显示相关信息"""
    try:
    det = np.linalg.det(matrix)
    inv = np.linalg.inv(matrix)
    print(f"{name}:")
    print(f" 行列式: {det}")
    print(f" 可逆: 是")
    print(f" 条件数: {np.linalg.cond(matrix):.2f}")
    return True
    except np.linalg.LinAlgError:
    print(f"{name}:")
    print(f" 行列式: {np.linalg.det(matrix)}")
    print(f" 可逆: 否(奇异矩阵)")
    return False

    # 测试不同类型矩阵的可逆性
    print("=== 矩阵可逆性测试 ===")

    # 可逆矩阵
    invertible_matrix = np.array([[3, 1],
    [2, 4]])
    check_matrix_invertibility(invertible_matrix, "可逆矩阵")

    print()

    # 奇异矩阵
    singular_matrix = np.array([[1, 2],
    [2, 4]]) # 第二行是第一行的2倍
    check_matrix_invertibility(singular_matrix, "奇异矩阵")

    NumPy中计算矩阵逆的方法

    NumPy提供了numpy.linalg.inv()函数来计算矩阵的逆。

    # 不同情况下的矩阵逆计算
    print("=== 矩阵逆的计算示例 ===")

    # 基本的2×2矩阵求逆
    basic_matrix = np.array([[4, 7],
    [2, 6]])
    basic_inv = np.linalg.inv(basic_matrix)
    print(f"基本矩阵:\\n{basic_matrix}")
    print(f"逆矩阵:\\n{basic_inv}")
    print(f"验证: A × A⁻¹ =\\n{np.dot(basic_matrix, basic_inv)}\\n")

    # 3×3矩阵求逆
    matrix_3x3 = np.array([[1, 2, 3],
    [0, 1, 4],
    [5, 6, 0]])
    inv_3x3 = np.linalg.inv(matrix_3x3)
    print(f"3×3矩阵:\\n{matrix_3x3}")
    print(f"逆矩阵:\\n{inv_3x3}")
    print(f"验证对角元素接近1: {np.allclose(np.diag(np.dot(matrix_3x3, inv_3x3)), 1)}\\n")

    # 正交矩阵(其逆等于其转置)
    orthogonal_matrix = np.array([[0, 1],
    [1, 0]]) # 90度旋转矩阵
    orthogonal_inv = np.linalg.inv(orthogonal_matrix)
    print(f"正交矩阵:\\n{orthogonal_matrix}")
    print(f"逆矩阵:\\n{orthogonal_inv}")
    print(f"转置矩阵:\\n{orthogonal_matrix.T}")
    print(f"逆矩阵是否等于转置: {np.allclose(orthogonal_inv, orthogonal_matrix.T)}")

    矩阵逆的实际应用场景 💡

    1. 解线性方程组

    矩阵的逆在解线性方程组中发挥重要作用。对于方程组Ax = b,如果A可逆,则解为x = A⁻¹b。

    # 使用矩阵逆解线性方程组
    print("=== 使用矩阵逆解线性方程组 ===")

    # 线性方程组:
    # 2x + 3y = 7
    # x + 4y = 6

    # 系数矩阵A
    A = np.array([[2, 3],
    [1, 4]])
    print(f"系数矩阵 A:\\n{A}")

    # 常数向量b
    b = np.array([7, 6])
    print(f"常数向量 b: {b}")

    # 方法1:直接求逆
    A_inv = np.linalg.inv(A)
    solution1 = np.dot(A_inv, b)
    print(f"方法1 – 直接求逆得到的解: x={solution1[0]:.2f}, y={solution1[1]:.2f}")

    # 方法2:使用linalg.solve(推荐)
    solution2 = np.linalg.solve(A, b)
    print(f"方法2 – 使用solve得到的解: x={solution2[0]:.2f}, y={solution2[1]:.2f}")

    # 验证解的正确性
    verification = np.dot(A, solution1)
    print(f"验证 Ax = b: {verification}{b}")

    2. 最小二乘问题

    在数据拟合和回归分析中,矩阵逆用于求解最小二乘问题。

    # 最小二乘问题示例
    print("=== 最小二乘问题 ===")

    # 生成一些带噪声的数据点
    np.random.seed(42)
    x_data = np.linspace(0, 10, 20)
    y_true = 2 * x_data + 1
    y_data = y_true + np.random.normal(0, 1, len(x_data))

    # 构造设计矩阵(线性拟合)
    X = np.column_stack([np.ones(len(x_data)), x_data])
    print(f"设计矩阵形状: {X.shape}")

    # 正规方程: θ = (X^T X)^(-1) X^T y
    XTX = np.dot(X.T, X)
    XTX_inv = np.linalg.inv(XTX)
    XTy = np.dot(X.T, y_data)
    theta = np.dot(XTX_inv, XTy)

    print(f"拟合参数: 截距={theta[0]:.2f}, 斜率={theta[1]:.2f}")
    print(f"真实参数: 截距=1.00, 斜率=2.00")

    3. 协方差矩阵的逆(精度矩阵)

    在统计学和机器学习中,协方差矩阵的逆称为精度矩阵,在高斯分布和贝叶斯推断中很重要。

    # 协方差矩阵及其逆(精度矩阵)
    print("=== 协方差矩阵与精度矩阵 ===")

    # 生成二维随机数据
    np.random.seed(42)
    data = np.random.multivariate_normal([0, 0], [[2, 0.5], [0.5, 1]], 1000)

    # 计算协方差矩阵
    cov_matrix = np.cov(data.T)
    print(f"协方差矩阵:\\n{cov_matrix}")

    # 计算精度矩阵(协方差矩阵的逆)
    precision_matrix = np.linalg.inv(cov_matrix)
    print(f"精度矩阵:\\n{precision_matrix}")

    # 验证精度矩阵确实是协方差矩阵的逆
    product_check = np.dot(cov_matrix, precision_matrix)
    print(f"验证 C × C⁻¹ 是否为单位矩阵:")
    print(product_check)
    print(f"对角元素是否接近1: {np.allclose(np.diag(product_check), 1)}")

    数值稳定性和计算注意事项 ⚠️

    在实际计算中,我们需要特别注意数值稳定性问题。

    条件数的概念

    矩阵的条件数衡量了矩阵求逆的数值稳定性。条件数越大,矩阵越接近奇异,计算结果越不稳定。

    # 条件数和数值稳定性
    print("=== 条件数与数值稳定性 ===")

    # 良条件矩阵
    well_conditioned = np.array([[2, 1],
    [1, 2]])
    cond_well = np.linalg.cond(well_conditioned)
    print(f"良条件矩阵条件数: {cond_well:.2f}")

    # 病态矩阵(接近奇异)
    ill_conditioned = np.array([[1, 1],
    [1, 1.0001]]) # 几乎线性相关
    cond_ill = np.linalg.cond(ill_conditioned)
    print(f"病态矩阵条件数: {cond_ill:.2f}")

    # 比较逆矩阵的准确性
    try:
    well_inv = np.linalg.inv(well_conditioned)
    ill_inv = np.linalg.inv(ill_conditioned)

    # 验证逆矩阵的准确性
    well_check = np.dot(well_conditioned, well_inv)
    ill_check = np.dot(ill_conditioned, ill_inv)

    print(f"良条件矩阵逆的准确性: {np.allclose(well_check, np.eye(2))}")
    print(f"病态矩阵逆的准确性: {np.allclose(ill_check, np.eye(2))}")

    except np.linalg.LinAlgError as e:
    print(f"计算出错: {e}")

    避免直接求逆的替代方法

    在某些情况下,直接求逆可能不是最佳选择。更好的方法包括:

    # 替代求逆的方法
    print("=== 替代求逆的方法 ===")

    # 创建测试矩阵和向量
    A = np.array([[3, 1],
    [2, 4]])
    b = np.array([7, 6])

    print("原始问题: 求解 Ax = b")

    # 方法1:直接求逆(不推荐用于大型矩阵)
    x1 = np.dot(np.linalg.inv(A), b)
    print(f"方法1 – 直接求逆: x = {x1}")

    # 方法2:使用solve(推荐)
    x2 = np.linalg.solve(A, b)
    print(f"方法2 – 使用solve: x = {x2}")

    # 方法3:使用最小二乘(适用于超定系统)
    x3 = np.linalg.lstsq(A, b, rcond=None)[0]
    print(f"方法3 – 最小二乘: x = {x3}")

    # 性能比较(对于大型矩阵)
    import time

    # 创建大型矩阵进行性能测试
    size = 1000
    large_A = np.random.rand(size, size)
    large_b = np.random.rand(size)

    # 测试solve方法
    start_time = time.time()
    x_solve = np.linalg.solve(large_A, large_b)
    solve_time = time.time() start_time

    # 测试直接求逆方法
    start_time = time.time()
    x_inv = np.dot(np.linalg.inv(large_A), large_b)
    inv_time = time.time() start_time

    print(f"\\n大型矩阵({size}x{size})性能比较:")
    print(f"solve方法耗时: {solve_time:.4f}秒")
    print(f"直接求逆耗时: {inv_time:.4f}秒")
    print(f"solve方法快 {inv_time/solve_time:.1f} 倍")

    特殊类型的矩阵及其逆 🔬

    对称矩阵

    对称矩阵具有一些特殊的性质,其逆矩阵也是对称的。

    # 对称矩阵的特性
    print("=== 对称矩阵 ===")

    # 创建对称矩阵
    symmetric_matrix = np.array([[4, 2, 1],
    [2, 5, 3],
    [1, 3, 6]])
    print(f"对称矩阵:\\n{symmetric_matrix}")

    # 验证对称性
    is_symmetric = np.allclose(symmetric_matrix, symmetric_matrix.T)
    print(f"是否对称: {is_symmetric}")

    # 计算逆矩阵
    sym_inv = np.linalg.inv(symmetric_matrix)
    print(f"逆矩阵:\\n{sym_inv}")

    # 验证逆矩阵也是对称的
    inv_is_symmetric = np.allclose(sym_inv, sym_inv.T)
    print(f"逆矩阵是否对称: {inv_is_symmetric}")

    正定矩阵

    正定矩阵的所有特征值都为正,这类矩阵在优化问题中经常出现。

    # 正定矩阵
    print("=== 正定矩阵 ===")

    # 创建正定矩阵
    positive_definite = np.array([[4, 1, 2],
    [1, 3, 1],
    [2, 1, 5]])
    print(f"矩阵:\\n{positive_definite}")

    # 检查是否正定(所有特征值大于0)
    eigenvalues = np.linalg.eigvals(positive_definite)
    is_positive_definite = np.all(eigenvalues > 0)
    print(f"特征值: {eigenvalues}")
    print(f"是否正定: {is_positive_definite}")

    # 正定矩阵的一些特殊性质
    det_pd = np.linalg.det(positive_definite)
    print(f"行列式: {det_pd}")
    print(f"行列式是否为正: {det_pd > 0}")

    # Cholesky分解(只适用于正定矩阵)
    try:
    L = np.linalg.cholesky(positive_definite)
    print(f"Cholesky分解成功:")
    print(f"L矩阵:\\n{L}")
    print(f"L × Lᵀ =\\n{np.dot(L, L.T)}")
    except np.linalg.LinAlgError:
    print("Cholesky分解失败(矩阵不是正定的)")

    实际应用案例分析 📈

    让我们通过几个实际应用案例来展示矩阵逆和行列式的重要性。

    案例1:图像变换

    在计算机图形学中,矩阵变换用于图像的旋转、缩放和平移。

    # 图像变换示例
    print("=== 图像变换应用 ===")

    # 定义2D变换矩阵
    def create_rotation_matrix(angle):
    """创建2D旋转矩阵"""
    cos_a = np.cos(angle)
    sin_a = np.sin(angle)
    return np.array([[cos_a, sin_a],
    [sin_a, cos_a]])

    def create_scaling_matrix(sx, sy):
    """创建2D缩放矩阵"""
    return np.array([[sx, 0],
    [0, sy]])

    # 原始点坐标(简单的三角形)
    points = np.array([[0, 1], # 顶点
    [1, 1], # 右下
    [1, 1]]) # 左下

    print(f"原始点坐标:\\n{points}")

    # 应用变换
    rotation_matrix = create_rotation_matrix(np.pi/4) # 45度旋转
    scaled_matrix = create_scaling_matrix(2, 1.5) # 缩放

    # 旋转后的点
    rotated_points = np.dot(points, rotation_matrix.T)
    print(f"旋转后点坐标:\\n{rotated_points}")

    # 缩放后的点
    scaled_points = np.dot(points, scaled_matrix.T)
    print(f"缩放后点坐标:\\n{scaled_points}")

    # 组合变换
    combined_transform = np.dot(scaling_matrix, rotation_matrix)
    combined_points = np.dot(points, combined_transform.T)
    print(f"组合变换后点坐标:\\n{combined_points}")

    案例2:多元线性回归

    在机器学习中,线性回归是最基础的算法之一。

    # 多元线性回归示例
    print("=== 多元线性回归 ===")

    # 生成模拟数据
    np.random.seed(42)
    n_samples = 100
    n_features = 3

    # 特征矩阵
    X = np.random.randn(n_samples, n_features)
    true_weights = np.array([2.5, 1.3, 0.8])
    true_intercept = 1.0

    # 生成目标变量(带噪声)
    y = X @ true_weights + true_intercept + np.random.randn(n_samples) * 0.5

    # 添加偏置项(截距)
    X_with_bias = np.column_stack([np.ones(n_samples), X])

    # 使用正规方程求解参数
    # θ = (X^T X)^(-1) X^T y
    XTX = X_with_bias.T @ X_with_bias
    XTy = X_with_bias.T @ y

    # 检查矩阵条件数
    condition_number = np.linalg.cond(XTX)
    print(f"设计矩阵条件数: {condition_number:.2f}")

    if condition_number < 1e12: # 检查是否病态
    theta = np.linalg.inv(XTX) @ XTy
    print(f"估计的参数: {theta}")
    print(f"真实参数: [{true_intercept}] + {true_weights}")
    else:
    print("矩阵过于病态,使用伪逆")
    theta = np.linalg.pinv(X_with_bias) @ y
    print(f"使用伪逆估计的参数: {theta}")

    # 计算R²分数
    y_pred = X_with_bias @ theta
    ss_res = np.sum((y y_pred) ** 2)
    ss_tot = np.sum((y np.mean(y)) ** 2)
    r_squared = 1 (ss_res / ss_tot)
    print(f"R²分数: {r_squared:.4f}")

    案例3:马尔可夫链稳态分析

    在概率论中,马尔可夫链的稳态分布可以通过矩阵运算求得。

    # 马尔可夫链稳态分析
    print("=== 马尔可夫链稳态分析 ===")

    # 转移概率矩阵
    transition_matrix = np.array([
    [0.7, 0.2, 0.1], # 状态1转移到其他状态的概率
    [0.3, 0.5, 0.2], # 状态2转移到其他状态的概率
    [0.1, 0.3, 0.6] # 状态3转移到其他状态的概率
    ])

    print(f"转移概率矩阵:\\n{transition_matrix}")

    # 验证每行概率和为1
    row_sums = np.sum(transition_matrix, axis=1)
    print(f"各行概率和: {row_sums}")

    # 计算稳态分布
    # 解方程 π = πP 和 Σπ = 1
    # 这等价于解 (P^T – I)π = 0 和 Σπ = 1

    n_states = transition_matrix.shape[0]
    P_T_minus_I = transition_matrix.T np.eye(n_states)

    # 添加约束 Σπ = 1
    constraint_matrix = np.ones((1, n_states))
    constraint_vector = np.array([1.0])

    # 构造增广矩阵
    augmented_matrix = np.vstack([P_T_minus_I[:1], constraint_matrix])
    augmented_vector = np.hstack([np.zeros(n_states1), constraint_vector])

    # 求解稳态分布
    steady_state = np.linalg.solve(augmented_matrix, augmented_vector)
    print(f"稳态分布: {steady_state}")

    # 验证稳态分布
    verification = steady_state @ transition_matrix
    print(f"验证 πP = π: {verification}")
    print(f"是否相等: {np.allclose(verification, steady_state)}")

    高级主题和优化技巧 🚀

    并行计算和性能优化

    对于大规模矩阵运算,性能优化至关重要。

    # 性能优化示例
    print("=== 性能优化 ===")

    import time

    def benchmark_inverse_methods(matrix_sizes=[100, 500, 1000]):
    """比较不同矩阵求逆方法的性能"""
    results = []

    for size in matrix_sizes:
    # 创建随机矩阵
    A = np.random.rand(size, size)

    # 确保矩阵可逆(添加对角优势)
    A += size * np.eye(size)

    print(f"\\n测试 {size}x{size} 矩阵:")

    # 方法1: numpy.linalg.inv
    start_time = time.time()
    inv1 = np.linalg.inv(A)
    time1 = time.time() start_time
    print(f" numpy.linalg.inv: {time1:.4f}秒")

    # 方法2: scipy.linalg.inv
    from scipy import linalg
    start_time = time.time()
    inv2 = linalg.inv(A)
    time2 = time.time() start_time
    print(f" scipy.linalg.inv: {time2:.4f}秒")

    # 方法3: LU分解后求解
    start_time = time.time()
    lu, piv = linalg.lu_factor(A)
    inv3 = linalg.lu_solve((lu, piv), np.eye(size))
    time3 = time.time() start_time
    print(f" LU分解方法: {time3:.4f}秒")

    results.append({
    'size': size,
    'numpy_inv': time1,
    'scipy_inv': time2,
    'lu_method': time3
    })

    return results

    # 运行基准测试
    benchmark_results = benchmark_inverse_methods([100, 500])

    内存效率考虑

    处理大型矩阵时,内存管理非常重要。

    # 内存效率示例
    print("=== 内存效率考虑 ===")

    # 大型矩阵操作的内存管理
    def memory_efficient_operations():
    """演示内存高效的矩阵操作"""

    # 创建大型矩阵但要注意内存使用
    size = 2000

    print(f"创建 {size}x{size} 矩阵…")

    # 方法1: 直接创建(占用较多内存)
    try:
    A = np.random.rand(size, size)
    print(f"矩阵A创建成功,大小: {A.nbytes / (1024**2):.1f} MB")

    # 如果矩阵稀疏,考虑使用稀疏矩阵
    from scipy import sparse

    # 创建稀疏矩阵示例
    sparse_A = sparse.random(size, size, density=0.01)
    print(f"稀疏矩阵非零元素数量: {sparse_A.nnz}")
    print(f"稀疏矩阵存储大小: {sparse_A.data.nbytes + sparse_A.indices.nbytes + sparse_A.indptr.nbytes} bytes")

    except MemoryError:
    print("内存不足,无法创建如此大的矩阵")

    # 分块处理大矩阵
    def process_large_matrix_in_blocks(matrix_size, block_size=500):
    """分块处理大矩阵"""
    print(f"分块处理 {matrix_size}x{matrix_size} 矩阵,块大小 {block_size}")

    # 模拟分块计算行列式
    total_det = 1.0
    num_blocks = matrix_size // block_size

    for i in range(min(num_blocks, 3)): # 只演示前几个块
    # 创建小块矩阵
    block = np.random.rand(block_size, block_size)
    block_det = np.linalg.det(block)
    total_det *= block_det

    print(f"分块计算完成,累积行列式影响因子: {total_det}")

    process_large_matrix_in_blocks(2000, 500)

    memory_efficient_operations()

    错误处理和调试技巧 🛠️

    在实际编程中,正确的错误处理能够避免程序崩溃。

    # 错误处理示例
    print("=== 错误处理和调试 ===")

    def safe_matrix_inverse(matrix, description="矩阵"):
    """安全地计算矩阵逆"""
    try:
    # 检查输入
    if not isinstance(matrix, np.ndarray):
    matrix = np.array(matrix)

    # 检查是否为方阵
    if matrix.shape[0] != matrix.shape[1]:
    raise ValueError(f"{description}必须是方阵")

    # 检查矩阵大小
    if matrix.size == 0:
    raise ValueError(f"{description}不能为空")

    # 计算行列式
    det = np.linalg.det(matrix)

    # 检查是否接近奇异
    if np.abs(det) < 1e-10:
    raise np.linalg.LinAlgError(f"{description}接近奇异(行列式={det})")

    # 计算逆矩阵
    inverse = np.linalg.inv(matrix)

    # 验证结果
    identity_check = np.dot(matrix, inverse)
    if not np.allclose(identity_check, np.eye(matrix.shape[0]), atol=1e-10):
    print(f"警告: {description}逆矩阵验证失败")

    return inverse

    except np.linalg.LinAlgError as e:
    print(f"线性代数错误: {e}")
    return None
    except ValueError as e:
    print(f"值错误: {e}")
    return None
    except Exception as e:
    print(f"未知错误: {e}")
    return None

    # 测试错误处理
    print("测试各种情况:")

    # 正常情况
    normal_matrix = np.array([[2, 1], [1, 2]])
    result1 = safe_matrix_inverse(normal_matrix, "正常矩阵")
    if result1 is not None:
    print("正常矩阵求逆成功")

    # 奇异矩阵
    singular_matrix = np.array([[1, 2], [2, 4]])
    result2 = safe_matrix_inverse(singular_matrix, "奇异矩阵")

    # 非方阵
    non_square = np.array([[1, 2, 3], [4, 5, 6]])
    result3 = safe_matrix_inverse(non_square, "非方阵")

    # 空矩阵
    empty_matrix = np.array([]).reshape(0, 0)
    result4 = safe_matrix_inverse(empty_matrix, "空矩阵")

    科学计算库对比分析 📊

    除了NumPy,还有其他优秀的科学计算库值得了解。

    # 不同库的功能对比
    print("=== 科学计算库对比 ===")

    # 创建测试矩阵
    test_matrix = np.random.rand(50, 50)
    test_matrix += 50 * np.eye(50) # 确保可逆

    print("不同库计算矩阵逆的性能对比:")

    # NumPy
    start_time = time.time()
    np_inv = np.linalg.inv(test_matrix)
    np_time = time.time() start_time
    print(f"NumPy: {np_time:.6f}秒")

    # SciPy
    from scipy import linalg
    start_time = time.time()
    sp_inv = linalg.inv(test_matrix)
    sp_time = time.time() start_time
    print(f"SciPy: {sp_time:.6f}秒")

    # 验证结果一致性
    print(f"结果一致性: {np.allclose(np_inv, sp_inv)}")

    # 更高级的功能对比
    print("\\n特殊矩阵处理能力:")

    # 对称矩阵
    sym_matrix = test_matrix + test_matrix.T
    print("对称矩阵处理:")
    try:
    # NumPy没有专门的对称矩阵求逆
    np_sym_inv = np.linalg.inv(sym_matrix)
    print(" NumPy: 支持(通用方法)")
    except:
    print(" NumPy: 不支持")

    try:
    # SciPy有专门的对称矩阵处理
    sp_sym_inv = linalg.inv(sym_matrix)
    print(" SciPy: 支持")
    except:
    print(" SciPy: 不支持")

    # 稀疏矩阵
    from scipy import sparse
    sparse_matrix = sparse.random(1000, 1000, density=0.01)
    sparse_matrix = sparse_matrix + sparse.eye(1000) # 确保可逆

    print("稀疏矩阵处理:")
    try:
    sparse_inv = linalg.inv(sparse_matrix.tocsc())
    print(" SciPy稀疏矩阵: 支持")
    except:
    print(" SciPy稀疏矩阵: 不支持")

    mermaid流程图展示

    #mermaid-svg-3AurmrOL185wdKMs{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3AurmrOL185wdKMs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3AurmrOL185wdKMs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3AurmrOL185wdKMs .error-icon{fill:#552222;}#mermaid-svg-3AurmrOL185wdKMs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3AurmrOL185wdKMs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3AurmrOL185wdKMs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3AurmrOL185wdKMs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3AurmrOL185wdKMs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3AurmrOL185wdKMs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3AurmrOL185wdKMs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3AurmrOL185wdKMs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3AurmrOL185wdKMs .marker.cross{stroke:#333333;}#mermaid-svg-3AurmrOL185wdKMs svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3AurmrOL185wdKMs p{margin:0;}#mermaid-svg-3AurmrOL185wdKMs .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-3AurmrOL185wdKMs .cluster-label text{fill:#333;}#mermaid-svg-3AurmrOL185wdKMs .cluster-label span{color:#333;}#mermaid-svg-3AurmrOL185wdKMs .cluster-label span p{background-color:transparent;}#mermaid-svg-3AurmrOL185wdKMs .label text,#mermaid-svg-3AurmrOL185wdKMs span{fill:#333;color:#333;}#mermaid-svg-3AurmrOL185wdKMs .node rect,#mermaid-svg-3AurmrOL185wdKMs .node circle,#mermaid-svg-3AurmrOL185wdKMs .node ellipse,#mermaid-svg-3AurmrOL185wdKMs .node polygon,#mermaid-svg-3AurmrOL185wdKMs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3AurmrOL185wdKMs .rough-node .label text,#mermaid-svg-3AurmrOL185wdKMs .node .label text,#mermaid-svg-3AurmrOL185wdKMs .image-shape .label,#mermaid-svg-3AurmrOL185wdKMs .icon-shape .label{text-anchor:middle;}#mermaid-svg-3AurmrOL185wdKMs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3AurmrOL185wdKMs .rough-node .label,#mermaid-svg-3AurmrOL185wdKMs .node .label,#mermaid-svg-3AurmrOL185wdKMs .image-shape .label,#mermaid-svg-3AurmrOL185wdKMs .icon-shape .label{text-align:center;}#mermaid-svg-3AurmrOL185wdKMs .node.clickable{cursor:pointer;}#mermaid-svg-3AurmrOL185wdKMs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3AurmrOL185wdKMs .arrowheadPath{fill:#333333;}#mermaid-svg-3AurmrOL185wdKMs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3AurmrOL185wdKMs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3AurmrOL185wdKMs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3AurmrOL185wdKMs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3AurmrOL185wdKMs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3AurmrOL185wdKMs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3AurmrOL185wdKMs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3AurmrOL185wdKMs .cluster text{fill:#333;}#mermaid-svg-3AurmrOL185wdKMs .cluster span{color:#333;}#mermaid-svg-3AurmrOL185wdKMs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3AurmrOL185wdKMs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3AurmrOL185wdKMs rect.text{fill:none;stroke-width:0;}#mermaid-svg-3AurmrOL185wdKMs .icon-shape,#mermaid-svg-3AurmrOL185wdKMs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3AurmrOL185wdKMs .icon-shape p,#mermaid-svg-3AurmrOL185wdKMs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3AurmrOL185wdKMs .icon-shape .label rect,#mermaid-svg-3AurmrOL185wdKMs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3AurmrOL185wdKMs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3AurmrOL185wdKMs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3AurmrOL185wdKMs :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    矩阵运算

    行列式计算

    矩阵求逆

    判断可逆性

    几何意义

    变换缩放

    解线性方程组

    最小二乘问题

    数值稳定性

    det ≠ 0

    det = 0

    矩阵可逆

    矩阵不可逆

    存在唯一解

    无解或无穷解

    最佳实践总结 ✅

    基于以上讨论,总结一些使用NumPy进行矩阵运算的最佳实践:

    1. 选择合适的计算方法

    # 推荐的做法
    def recommended_approaches():
    """推荐的矩阵运算方法"""

    print("=== 推荐做法 ===")

    # 解线性方程组:优先使用solve而不是inv
    A = np.random.rand(100, 100)
    A += 100 * np.eye(100) # 确保良好条件
    b = np.random.rand(100)

    # 推荐
    x_recommended = np.linalg.solve(A, b)
    print("✓ 使用linalg.solve解线性方程组")

    # 不推荐(除非必要)
    # x_not_recommended = np.linalg.inv(A) @ b

    # 检查矩阵条件数
    cond_num = np.linalg.cond(A)
    if cond_num > 1e12:
    print("⚠ 矩阵条件数过大,可能存在数值不稳定")
    else:
    print("✓ 矩阵条件数良好")

    # 对于病态矩阵,使用伪逆
    if cond_num > 1e12:
    x_pseudo = np.linalg.pinv(A) @ b
    print("✓ 使用伪逆处理病态矩阵")

    recommended_approaches()

    2. 内存和性能优化

    # 内存和性能优化建议
    def optimization_tips():
    """性能优化建议"""

    print("=== 性能优化建议 ===")

    # 1. 预分配数组
    print("1. 预分配数组避免重复内存分配")
    size = 1000
    result_array = np.empty((size, size)) # 预分配

    # 2. 使用适当的数据类型
    print("2. 使用适当的数据类型节省内存")
    float32_array = np.random.rand(1000, 1000).astype(np.float32)
    float64_array = np.random.rand(1000, 1000).astype(np.float64)
    print(f" float32内存使用: {float32_array.nbytes / (1024**2):.1f} MB")
    print(f" float64内存使用: {float64_array.nbytes / (1024**2):.1f} MB")

    # 3. 利用向量化操作
    print("3. 利用NumPy的向量化操作")
    # 好的做法
    vectorized_result = np.sum(float32_array ** 2, axis=1)
    print(" ✓ 使用向量化操作")

    # 避免显式循环
    # slow_result = np.array([np.sum(row**2) for row in float32_array]) # 慢

    # 4. 考虑使用in-place操作
    print("4. 考虑使用in-place操作")
    temp_array = np.random.rand(1000)
    temp_array += 5 # in-place操作,节省内存
    print(" ✓ 使用in-place操作")

    optimization_tips()

    3. 数值稳定性保证

    # 数值稳定性最佳实践
    def numerical_stability_practices():
    """数值稳定性最佳实践"""

    print("=== 数值稳定性最佳实践 ===")

    # 1. 检查矩阵条件数
    def safe_inverse_with_check(matrix):
    """带条件数检查的安全求逆"""
    cond_num = np.linalg.cond(matrix)
    print(f"矩阵条件数: {cond_num:.2e}")

    if cond_num > 1e12:
    print("⚠ 警告: 矩阵可能病态,考虑使用正则化或其他方法")
    return None
    elif cond_num > 1e8:
    print("⚠ 注意: 矩阵条件数较大,结果可能不够精确")

    return np.linalg.inv(matrix)

    # 测试良好条件的矩阵
    good_matrix = np.random.rand(5, 5)
    good_matrix += 5 * np.eye(5)
    print("良好条件矩阵:")
    safe_inverse_with_check(good_matrix)

    # 2. 使用适当的容差值
    print("\\n使用适当的容差值进行比较:")
    small_value = 1e-10
    determinant = np.linalg.det(good_matrix)

    if abs(determinant) < small_value:
    print("矩阵接近奇异")
    else:
    print("矩阵远离奇异")

    # 3. 验证计算结果
    def verify_inverse(matrix, inverse_matrix):
    """验证逆矩阵计算的正确性"""
    product = np.dot(matrix, inverse_matrix)
    identity = np.eye(matrix.shape[0])
    is_correct = np.allclose(product, identity, rtol=1e-10, atol=1e-12)
    max_error = np.max(np.abs(product identity))

    print(f"逆矩阵验证:")
    print(f" 结果正确: {is_correct}")
    print(f" 最大误差: {max_error:.2e}")

    return is_correct

    if abs(determinant) > small_value:
    computed_inv = np.linalg.inv(good_matrix)
    verify_inverse(good_matrix, computed_inv)

    numerical_stability_practices()

    扩展资源和进一步学习 🔍

    为了帮助读者深入学习,以下是一些有价值的外部资源:

    在线教程和文档

    • NumPy官方文档 提供了最权威的线性代数函数参考
    • SciPy Lecture Notes 包含了丰富的科学计算教程
    • Khan Academy Linear Algebra 提供免费的线性代数课程

    学术资源

    • MIT OpenCourseWare Linear Algebra Gilbert Strang教授的经典线性代数课程
    • Numerical Linear Algebra by Trefethen and Bau 深入介绍数值线性代数的专业书籍

    实践项目

    # 综合练习项目
    def comprehensive_exercise():
    """综合练习项目:构建一个简单的线性回归工具"""

    print("=== 综合练习:线性回归工具 ===")

    class SimpleLinearRegression:
    """简单的线性回归实现"""

    def __init__(self, fit_intercept=True):
    self.fit_intercept = fit_intercept
    self.coef_ = None
    self.intercept_ = None

    def fit(self, X, y):
    """训练模型"""
    # 输入验证
    X = np.asarray(X)
    y = np.asarray(y)

    if X.ndim == 1:
    X = X.reshape(1, 1)

    # 添加偏置项
    if self.fit_intercept:
    X = np.column_stack([np.ones(X.shape[0]), X])

    # 使用正规方程求解
    try:
    # θ = (X^T X)^(-1) X^T y
    XTX = X.T @ X

    # 检查矩阵条件数
    cond_num = np.linalg.cond(XTX)
    if cond_num > 1e12:
    print(f"警告: 设计矩阵条件数过高 ({cond_num:.2e})")
    # 使用伪逆作为备选方案
    theta = np.linalg.pinv(X) @ y
    else:
    theta = np.linalg.inv(XTX) @ X.T @ y

    if self.fit_intercept:
    self.intercept_ = theta[0]
    self.coef_ = theta[1:]
    else:
    self.intercept_ = 0.0
    self.coef_ = theta

    except np.linalg.LinAlgError as e:
    raise ValueError(f"矩阵求逆失败: {e}")

    def predict(self, X):
    """预测"""
    X = np.asarray(X)
    if X.ndim == 1:
    X = X.reshape(1, 1)

    return X @ self.coef_ + self.intercept_

    def score(self, X, y):
    """计算R²分数"""
    y_pred = self.predict(X)
    ss_res = np.sum((y y_pred) ** 2)
    ss_tot = np.sum((y np.mean(y)) ** 2)
    return 1 (ss_res / ss_tot)

    # 测试自定义线性回归
    np.random.seed(42)

    # 生成数据
    X_train = np.random.rand(100, 2)
    true_coef = np.array([2.5, 1.3])
    true_intercept = 1.0
    y_train = X_train @ true_coef + true_intercept + np.random.randn(100) * 0.1

    # 训练模型
    model = SimpleLinearRegression()
    model.fit(X_train, y_train)

    print(f"真实系数: {true_coef}")
    print(f"估计系数: {model.coef_}")
    print(f"真实截距: {true_intercept}")
    print(f"估计截距: {model.intercept_:.4f}")
    print(f"R²分数: {model.score(X_train, y_train):.4f}")

    # 预测新数据
    X_test = np.array([[0.5, 0.3], [0.8, 0.1]])
    predictions = model.predict(X_test)
    print(f"测试预测: {predictions}")

    comprehensive_exercise()

    总结与展望 🎯

    通过本文的详细介绍,我们全面了解了NumPy中矩阵逆和行列式的核心概念、计算方法以及实际应用。这些知识不仅在学术研究中有着重要地位,在工业界的实际项目中同样发挥着关键作用。

    关键要点回顾:

  • 行列式不仅是数学概念,更是判断矩阵性质的重要工具
  • 矩阵逆是解决线性方程组和进行变换的关键
  • 数值稳定性在实际计算中至关重要,需要关注条件数等指标
  • 性能优化能够显著提升大规模计算的效率
  • 错误处理确保程序的健壮性和可靠性
  • 未来发展方向:

    随着人工智能和大数据技术的发展,矩阵运算的需求只会越来越大。现代GPU加速计算、分布式计算框架以及量子计算等领域都在推动线性代数计算的发展。掌握这些基础知识,将为后续学习更高级的数值计算和机器学习算法奠定坚实基础。

    记住,理论知识需要通过大量实践来巩固。建议读者尝试修改本文中的代码示例,探索不同参数设置下的结果变化,这样能够更深入地理解矩阵运算的本质和应用价值。

    线性代数的世界广阔而精彩,希望本文能够成为你探索这一领域的良好起点!🚀


    🙌 感谢你读到这里! 🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。 💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友! 💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿 🔔 关注我,不错过下一篇干货!我们下期再见!✨

    赞(0)
    未经允许不得转载:171主机测评 » Python NumPy - 线性代数运算 矩阵的逆与行列式
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址