0

0

如何子类化 NumPy 数组实现对称矩阵支持

霞舞

霞舞

发布时间:2026-01-09 15:26:28

|

960人浏览过

|

来源于php中文网

原创

如何子类化 NumPy 数组实现对称矩阵支持

本文介绍如何通过继承 `np.ndarray` 创建专用于对称矩阵的自定义数组类,自动强制对称性、保持赋值时的对称约束,并合理利用 `numpy.linalg.eigh` 进行特征分解,避免冗余存储。

在科学计算中,对称矩阵(如协方差矩阵、哈密顿量、图拉普拉斯等)具有重要性质:实对称矩阵必可正交对角化,且其特征值为实数、特征向量正交。为在 NumPy 生态中安全、高效地利用这些性质,推荐通过子类化 np.ndarray 构建专用类型——SymmetricArray。

该类需满足两个核心要求:

  1. 构造时自动对称化:将任意输入矩阵 $ M $ 映射为对称部分 $ \frac{1}{2}(M + M^\top) $;
  2. 赋值时保持对称性:对任意位置或切片的写入操作,同步更新其转置位置,确保结构不变。

以下是最简可行实现(兼容 2D 及高维批量矩阵,如 (N, D, D)):

import numpy as np

class SymmetricArray(np.ndarray):
    def __new__(cls, input_array):
        input_array = np.asarray(input_array)
        assert input_array.ndim >= 2 and input_array.shape[-1] == input_array.shape[-2], \
            "Last two dimensions must be square"
        # 对最后两维取对称部分;其余维度广播处理
        axes = list(range(input_array.ndim - 2)) + [-1, -2]
        transposed = input_array.transpose(axes)
        sym_part = 0.5 * (input_array + transposed)
        return sym_part.view(cls)

    def __setitem__(self, key, value):
        # 标准化索引为 tuple,补全至 ndim
        if not isinstance(key, tuple):
            key = (key,)
        if len(key) < self.ndim:
            key += (slice(None),) * (self.ndim - len(key))

        # 构造转置索引:仅交换最后两维的下标
        key_t = key[:-2] + (key[-1], key[-2])

        # 确保 value 与 key 兼容;若 value 是矩阵,也需对称赋值
        value = np.asarray(value)
        super().__setitem__(key, value)

        # 若 value 非标量且最后两维存在,对其转置后赋给对称位置
        if value.ndim >= 2 and len(key) >= 2:
            value_t = value.transpose(*list(range(value.ndim - 2)) + [-1, -2])
            super().__setitem__(key_t, value_t)
        elif value.ndim == 0 or len(key) < 2:
            super().__setitem__(key_t, value)

使用示例

稿定AI设计
稿定AI设计

AI自动去水印、背景消除、批量抠人像工具

下载
rng = np.random.default_rng(42)
A = SymmetricArray(rng.random((3, 3)))
print("初始对称矩阵:\n", A)
A[0, :] = [1, 2, 3]  # 自动同步更新第0列 → A[:, 0] = [1,2,3]
print("赋值后:\n", A)
# 输出保证 A[0,1]==A[1,0], A[0,2]==A[2,0], etc.

⚠️ 重要注意事项

  • 不建议将 U, D 作为实例属性缓存:特征分解结果依赖于当前数组值,而 NumPy 子类无法自动追踪底层数据变更(如 += 或切片赋值)。强行缓存易导致状态不一致。
  • 正确做法是按需调用 np.linalg.eigh:它专为实对称/复厄米特矩阵优化,返回正交特征向量和实特征值,且数值稳定:
    U, D = np.linalg.eigh(A)  # D 是一维数组,U 是正交矩阵
    # 验证重建:np.allclose(A, U @ np.diag(D) @ U.T)
  • 避免重载 __array_finalize__ 或 __array_wrap__:本实现仅需 __new__ 和 __setitem__ 即可满足核心需求;过度定制易引入不可预见的广播或视图行为。

总结:SymmetricArray 不是“魔法容器”,而是语义增强的契约型数组——它不改变 NumPy 的底层机制,而是通过构造与赋值阶段的显式约束,保障用户始终在对称流形上操作。配合 eigh、cholesky 等专用函数,可构建更健壮、可读性更强的数值代码。

相关专题

更多
go语言 数组和切片
go语言 数组和切片

本专题整合了go语言数组和切片的区别与含义,阅读专题下面的文章了解更多详细内容。

46

2025.09.03

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

25

2026.01.23

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

31

2026.01.23

yy漫画官方登录入口地址合集
yy漫画官方登录入口地址合集

本专题整合了yy漫画入口相关合集,阅读专题下面的文章了解更多详细内容。

119

2026.01.23

漫蛙最新入口地址汇总2026
漫蛙最新入口地址汇总2026

本专题整合了漫蛙最新入口地址大全,阅读专题下面的文章了解更多详细内容。

180

2026.01.23

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

16

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

70

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

63

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

64

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号