资讯详情

NumPy 矩阵库 numpy.matlib 完全指南:matrix 子类与 8 个矩阵创建函数的源码级剖析

📅 2026/9/20 10:27:50 | 华诺云谱 👁 阅读
NumPy 矩阵库 numpy.matlib 完全指南:matrix 子类与 8 个矩阵创建函数的源码级剖析
NumPy 矩阵库 numpy.matlib 完全指南matrix 子类与 8 个矩阵创建函数的源码级剖析【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpynumpy.matlib是 NumPy 中专门为偏好矩阵matrix语义的开发者提供的子模块它复制了numpy命名空间中的全部函数并把empty、zeros、ones、eye、identity、repmat、rand、randn这 8 个创建类函数替换为返回matrix二维专用 ndarray 子类而非普通ndarray的版本。阅读本文后你将掌握 matlib 的完整 API、每个替换函数的参数语义与源码实现原理、单维形状自动扩展为行矩阵的细节以及该模块自 NumPy 1.19.0 起被标记弃用后的正确迁移姿势。模块定位matlib 在 NumPy 中的角色官方参考文档 routines.matlib.rst 对numpy.matlib的定义非常简洁明确该模块包含numpy命名空间中的所有函数但其中的部分函数被替换为返回matrix矩阵而非ndarray多维数组的版本。从源码 numpy/matlib.py 可以看到它实现这一点的直接手段——先以通配符导入整个 numpy 命名空间再覆盖其中的矩阵创建函数import numpy as np # Matlib.py contains all functions in the numpy namespace with a few # replacements. See doc/source/reference/routines.matlib.rst for details. # Need * as were copying the numpy namespace. from numpy import * from numpy.matrixlib.defmatrix import asmatrix, matrix模块的__all__同样由两部分拼接而成numpy/matlib.py__all__ [rand, randn, repmat] __all__ np.__all__即rand、randn、repmat三个是 matlib 独有的“新增”函数其余全部继承自 numpy 命名空间。需要特别说明的访问方式在 numpy/init.py 中matlib是通过__getattr__惰性加载的子模块因此既可以使用import numpy.matlib显式导入也可以直接通过np.matlib.xxx触达首次访问时自动导入但np.matlib并不会在import numpy时立即被加载。返回矩阵的 numpy 命名空间函数matrix、asmatrix、bmatmatlib 的第一组核心内容是三个同样位于 numpy 命名空间、却专门产出矩阵的函数。它们定义在 numpy/matrixlib/defmatrix.py文件顶部__all__ [matrix, bmat, asmatrix]即为此三人组。matrix永远保持二维的 ndarray 子类matrix是ndarray的一个特殊子类defmatrix.py 定义class matrix(N.ndarray)核心特性是在运算过程中始终保持二维形态并且为线性代数提供特殊运算符*表示矩阵乘法、**表示矩阵幂defmatrix.py。 import numpy as np a np.matrix(1 2; 3 4) # 字符串解析空格/逗号分列分号分行 a matrix([[1, 2], [3, 4]]) np.matrix([[1, 2], [3, 4]]) matrix([[1, 2], [3, 4]])参数方面defmatrix.py参数类型说明dataarray_like 或 str传入字符串时以逗号或空格分隔列、以分号分隔行进行解析dtypedata-type输出矩阵的数据类型copybool若data已是 ndarray控制是复制数据默认还是构造视图*运算符的矩阵乘法语义在源码中有明确实现defmatrix.py当other是 ndarray、list 或 tuple 时会先将一维向量提升为行向量再调用numpy.dot执行矩阵乘法**则委托给matrix_powerdefmatrix.py来自numpy.linalg。此外__getitem__defmatrix.py会保证索引结果仍是二维的列索引得到列矩阵(sh, 1)否则得到行矩阵(1, sh)sum、squeeze等方法也都重写为返回矩阵形态。asmatrix不复制数据的视图式转换asmatrix(data, dtypeNone)与matrix的关键区别在于如果输入已经是 matrix 或 ndarrayasmatrix不会复制数据等价于matrix(data, copyFalse)defmatrix.py。其实现只有一行defmatrix.pyreturn matrix(data, dtypedtype, copyFalse)因此对asmatrix的结果修改会反映到原数组上 x np.array([[1, 2], [3, 4]]) m np.asmatrix(x) x[0, 0] 5 m matrix([[5, 2], [3, 4]])asmatrix是 matlib 内部实现eye、rand、randn的核心工具详见下文。bmat从字符串、嵌套序列或数组构建分块矩阵bmat(obj, ldictNone, gdictNone)用于构建分块矩阵defmatrix.py。obj可以是字符串可引用当前作用域中的变量名、嵌套序列或数组ldict和gdict可选地用于在字符串模式下替换局部/全局操作数。 A np.asmatrix(1 1; 1 1) B np.asmatrix(2 2; 2 2) C np.asmatrix(3 4; 5 6) D np.asmatrix(7 8; 9 0) np.bmat([[A, B], [C, D]]) # 嵌套列表 np.bmat(A,B; C,D) # 字符串形式 matrix([[1, 1, 2, 2], [1, 1, 2, 2], [3, 4, 7, 8], [5, 6, 9, 0]])从实现上看defmatrix.py字符串输入会解析为块引用逐行concatenate后按行拼接元组/列表输入则对每一行做水平拼接axis-1再垂直拼接axis0数组输入直接转 matrix。作为对比对 N 维数组更通用的替代是numpy.block它返回普通 ndarray。matlib 替换函数逐个详解文档中autosummary列出的 8 个替换函数均实现在 numpy/matlib.py。它们可以分为三类填充类empty/zeros/ones、特殊结构类eye/identity/repmat、随机数类rand/randn。empty / zeros / ones三种填充模式的矩阵创建这三个函数签名完全一致empty(shape, dtypeNone, orderC)、zeros(shape, dtypeNone, orderC)、ones(shape, dtypeNone, orderC)参数含义如下numpy/matlib.py参数类型说明shapeint 或 int 元组矩阵的形状dtypedata-type可选输出数据类型默认float64order{C, F}可选内存布局C 风格行优先或 Fortran 风格列优先默认 C它们的源码实现都基于ndarray.__new__(matrix, ...)区别仅在于是否显式填充numpy/matlib.py 与 L107-L109# empty不初始化速度略快但内容是任意值 return ndarray.__new__(matrix, shape, dtype, orderorder) # ones / zeros创建后分别 fill(1) / fill(0) a ndarray.__new__(matrix, shape, dtype, orderorder) a.fill(1) # 或 a.fill(0) return a使用示例 import numpy.matlib np.matlib.empty((2, 2)) # 内容为随机内存数据 matrix([[6.76425276e-320, 9.79033856e-307], # random [7.39337286e-309, 3.22135945e-309]]) np.matlib.ones((2, 3)) matrix([[1., 1., 1.], [1., 1., 1.]]) np.matlib.zeros(2) # 标量/一维形状 → (1, 2) 行矩阵 matrix([[0., 0.]])重要形状规则若shape长度为一即(N,)或直接传标量N输出都会变成形状为(1, N)的单行矩阵numpy/matlib.py这与普通np.zeros(N)得到一维数组的行为截然不同是 matrix 保持二维语义的体现。empty的一个特殊注意点是与zeros、ones不同它不初始化元素值新分配矩阵中的值是任意的若要可复现结果必须先逐元素赋值numpy/matlib.py。identity / eye单位矩阵与广义对角矩阵identity(n, dtypeNone)返回n x n单位方阵主对角线为 1、其余为 0默认dtype为floatnumpy/matlib.py。其实现不直接调用np.identity而是先构造[1, 0, 0, ...]数组铺满扁平视图numpy/matlib.pya array([1] n * [0], dtypedtype) b empty((n, n), dtypedtype) b.flat a return b np.matlib.identity(3, dtypenp.int_) matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]])eye(n, MNone, k0, dtypefloat, orderC)是更通用的版本numpy/matlib.py参数类型说明nint输出行数Mint可选输出列数默认等于nkint可选对角线索引0 为主对角线正值为上对角线负值为下对角线dtypedtype可选返回矩阵的数据类型order{C, F}可选内存中的行优先C 风格或列优先Fortran 风格顺序它的实现与identity不同是直接包装 numpy 的np.eye再转换为矩阵numpy/matlib.pyreturn asmatrix(np.eye(n, MM, kk, dtypedtype, orderorder)) np.matlib.eye(3, k1, dtypenp.float64) matrix([[0., 1., 0.], [0., 0., 1.], [0., 0., 0.]])repmat沿两个轴重复 0~2 维数组或矩阵repmat(a, m, n)将 0 维到 2 维的数组或矩阵在第一个轴重复m次、第二个轴重复n次numpy/matlib.py。与 MATLAB 的repmat语义一致它是 matlib 三个“新增”函数之一不在 numpy 主命名空间。 a0 np.array(1) np.matlib.repmat(a0, 2, 3) # 0 维标量视为 (1,1) array([[1, 1, 1], [1, 1, 1]]) a1 np.arange(4) np.matlib.repmat(a1, 2, 2) # 1 维数组视为 (1,4) 行 array([[0, 1, 2, 3, 0, 1, 2, 3], [0, 1, 2, 3, 0, 1, 2, 3]]) a2 np.asmatrix(np.arange(6).reshape(2, 3)) np.matlib.repmat(a2, 2, 3) # matrix 输入 → matrix 输出 matrix([[0, 1, 2, 0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5, 3, 4, 5], [0, 1, 2, 0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5, 3, 4, 5]])从源码看其维度规约逻辑numpy/matlib.py0 维输入按(1, 1)处理1 维输入按(1, a.shape[0])处理2 维以上直接取a.shape随后将数组展平为(1, size)依次沿轴repeat最终reshape(rows, cols)得到(m*origrows, n*origcols)的结果。注意repmat的返回值类型跟随输入ndarray 输入返回 ndarraymatrix 输入返回 matrix。rand / randn均匀分布与标准正态分布随机矩阵rand(*args)返回在[0, 1)区间上均匀分布的随机矩阵randn(*args)返回均值为 0、方差为 1 的标准正态分布随机矩阵numpy/matlib.py 与 L279-L284。两者的形状参数*args接受两种形式N 个整数分别指定每个维度大小或传入一个完整形状的元组。当第一个参数是元组时其余参数会被忽略numpy/matlib.py 与 L328-L330def rand(*args): if isinstance(args[0], tuple): args args[0] return asmatrix(np.random.rand(*args)) np.random.seed(123) np.matlib.rand(2, 3) # 两个整数指定 2x3 matrix([[0.69646919, 0.28613933, 0.22685145], [0.55131477, 0.71946897, 0.42310646]]) np.matlib.rand((2, 3), 4) # 元组优先(2,3) 生效4 被忽略 matrix([[0.43857224, 0.0596779 , 0.39804426], [0.73799541, 0.18249173, 0.17545176]])randn还给出了从标准正态分布变换到任意均值mu、标准差sigma正态分布的配方numpy/matlib.pysigma * np.matlib.randn(...) mu 2.5 * np.matlib.randn((2, 4)) 3 # 均值 3、标准差 2.5 的 2x4 矩阵 matrix([[1.92771843, 6.16484065, 0.83314899, 1.30278462], [2.76322758, 6.72847407, 1.40274501, 1.8900451 ]])两个函数都依赖全局随机状态np.random.rand/np.random.randn因此可用np.random.seed(...)控制可复现性底层等价于numpy.random.RandomState.rand/randn。矩阵形态保证的源码原理为什么结果总是二维matlib 全部替换函数产出的结果都严格保持二维这背后是两层机制共同作用的结果。第一层创建路径。empty/zeros/ones直接以ndarray.__new__(matrix, ...)构造 matrix 实例eye/rand/randn先调用 numpy 的 ndarray 版本再经asmatrix即matrix(data, copyFalse)包装。而在matrix.__new__中defmatrix.py0 维输入会被重塑为(1, 1)一维输入被重塑为(1, shape[0])超过 2 维则直接抛出ValueError(matrix must be 2-dimensional)。第二层运算保持。matrix.__array_finalize__defmatrix.py在任何操作产生新数组时都会把结果拉回二维——0 维变(1, 1)1 维变(1, N)__getitem__则保证切片/索引结果同样保持二维形态。这正是 numpy/tests/test_matlib.py 中断言的要点def test_rand(): x numpy.matlib.rand(3) # check matrix type, array would have shape (3,) assert_(x.ndim 2) def test_randn(): x np.matlib.randn(3) # check matrix type, array would have shape (3,) assert_(x.ndim 2)即matlib.rand(3)返回的是(1, 3)矩阵而np.random.rand(3)返回(3,)一维数组——这是两类接口最直观的行为差异。兼容性警示1.19.0 起的弃用状态与迁移建议使用 matlib 必须了解它的历史包袱。导入该模块会立即触发PendingDeprecationWarningnumpy/matlib.pywarnings.warn(Importing from numpy.matlib is deprecated since 1.19.0. The matrix subclass is not the recommended way to represent matrices or deal with linear algebra ... Please adjust your code to use regular ndarray. , PendingDeprecationWarning, stacklevel2)同样matrix类的__new__自 2018 年起就带有PendingDeprecationWarningdefmatrix.py官方注释明确表示该矩阵子类“不再推荐使用即使是用于线性代数未来可能被移除”defmatrix.py。因此官方的迁移路径是用普通 ndarray 替代 matrix把a * b矩阵乘改写为a b把a ** k改写为np.linalg.matrix_power(a, k)把np.matrix(1 2; 3 4)改写为np.array([[1, 2], [3, 4]])把np.bmat改写为np.block。若仍需要矩阵语义应优先考虑显式使用二维 ndarray 并配合运算符而非依赖np.matlib。测试验证与可用性保障仓库中的 numpy/tests/test_matlib.py 为全部 8 个替换函数提供了覆盖测试可作为使用范本test_emptyL6-L9校验返回类型为np.matrix且(2,)形状输入得到(1, 2)test_ones/test_zerosL11-L23校验填充值与单行矩阵形状(1, 2)test_identity/test_eyeL25-L42校验对角线值、k偏移以及orderC/F对应的c_contiguous/f_contiguous内存标志test_rand/test_randnL44-L52校验输出ndim 2test_repmatL54-L59校验重复拼接后的精确数值。结合 numpy/matlib.pyi 中的类型标注repmat对 matrix 输入返回_Matrix[ScalarT]、对 ndarray 输入返回NDArray[ScalarT]这与实现中“返回类型跟随输入”的行为一致供类型检查场景参考。总结numpy.matlib是 NumPy 为 MATLAB 风格矩阵用户保留的兼容性子模块它以matrix二维子类为核心通过 numpy/matlib.py 中的 8 个替换函数empty、zeros、ones、eye、identity、repmat、rand、randn与 numpy 命名空间中的matrix、asmatrix、bmat构成完整矩阵工具集。它的设计核心是“永远保持二维”的矩阵语义一维形状自动提升为(1, N)行矩阵*为矩阵乘法。但自 NumPy 1.19.0 起整个模块已进入弃用流程新代码应使用普通 ndarray 与运算符理解 matlib 的价值更多在于解读存量代码、理解 matrix 语义的历史成因以及从源码层面把握 ndarray 子类化的实现技巧。【免费下载链接】numpyThe fundamental package for scientific computing with Python.项目地址: https://gitcode.com/gh_mirrors/nu/numpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。