如何子类化numpy array实现对称矩阵专用类?
最简实现对称矩阵的NumPy子类
要实现满足你需求的NumPy子类,核心是继承np.ndarray并在构造阶段处理矩阵对称化,同时通过懒加载方式实现特征分解字段U和D。以下是最简实现:
完整代码
import numpy as np class SymmetricMatrix(np.ndarray): def __new__(cls, input_array): # 强制将输入矩阵转换为对称形式 symmetric_arr = 0.5 * (input_array + input_array.T) # 创建子类实例并转换视图 obj = np.asarray(symmetric_arr).view(cls) # 初始化特征分解缓存属性 obj._U = None obj._D = None return obj @property def U(self): # 懒加载:首次访问时计算特征分解 if self._U is None: # 针对对称矩阵,使用eigh效率更高(专门适配Hermitian/对称实矩阵) eig_vals, eig_vecs = np.linalg.eigh(self) # 反转顺序,让特征值从大到小排列(可选,根据需求调整) self._D = eig_vals[::-1] self._U = eig_vecs[:, ::-1] return self._U @property def D(self): # 复用U的计算逻辑,避免重复计算 if self._D is None: self.U # 触发U的计算,同时填充_D return self._D def __array_finalize__(self, obj): # 确保子类实例在视图转换、运算后保留缓存属性 if obj is None: return self._U = getattr(obj, '_U', None) self._D = getattr(obj, '_D', None)
关键细节说明
- 构造阶段对称化:重写
__new__方法(NumPy数组的构造逻辑在__new__中完成,而非__init__),通过0.5*(m+m.T)强制输入矩阵对称,避免非对称数据传入。 - 懒加载特征分解:用
@property实现U和D,仅在首次访问时调用np.linalg.eigh计算特征值和特征向量,避免不必要的计算开销。相比np.linalg.svd,eigh针对对称矩阵做了优化,速度更快、精度更高。 - 属性继承:
__array_finalize__方法确保子类在进行数组运算(如加法、乘法)或视图转换时,保留_U和_D的缓存状态,避免重复计算。
使用示例
# 测试非对称输入 raw_mat = np.array([[1, 3], [2, 4]]) sym_mat = SymmetricMatrix(raw_mat) # 验证矩阵对称 print("对称化后的矩阵:") print(sym_mat) # 输出: # [[1. 2.5] # [2.5 4. ]] # 获取特征向量和特征值 print("\n特征向量U:") print(sym_mat.U) print("\n特征值D:") print(sym_mat.D)
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

