You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch协方差矩阵对称化后非半正定?精度问题咨询

协方差矩阵对称化后失去正半正定的原因及解决办法

核心原因:浮点精度误差

理论上a.T @ a的结果是严格对称的,但在浮点运算(尤其是默认的float32精度下),计算过程中会产生微小的非对称偏差。执行(cov_mat + cov_mat.T)/2时,这些偏差经过运算后可能导致矩阵出现极小的负特征值,从而破坏正半定性。

验证方式

你可以通过检查特征值来确认这一点:

import torch

a = torch.randn(64, 512)
cov_mat = (a.T @ a) / (a.size(0) - 1)
# 查看原始矩阵的特征值
eigvals_original = torch.linalg.eigvalsh(cov_mat)
print("原始矩阵最小特征值:", eigvals_original.min().item())

# 对称化后
cov_mat_sym = (cov_mat + cov_mat.T) / 2
eigvals_sym = torch.linalg.eigvalsh(cov_mat_sym)
print("对称化后最小特征值:", eigvals_sym.min().item())

运行后会发现,对称化后的最小特征值大概率是接近0的负数,这就是浮点精度误差导致的结果。

解决办法

  1. 省略额外对称化步骤:a.T @ a的非对称偏差极小,完全可以忽略,不需要额外做对称化处理,直接使用原始计算结果即可保证正半定性。
  2. 修正数值误差:如果必须保证矩阵对称且正半正定,可以在对称化后截断极小的负特征值:
cov_mat_sym = (cov_mat + cov_mat.T) / 2
# 分解特征值与特征向量
eigvals, eigvecs = torch.linalg.eigh(cov_mat_sym)
# 将小于阈值的特征值设为0(阈值可根据需求调整,比如1e-8)
eigvals = torch.clamp(eigvals, min=1e-8)
# 重构正半正定的对称矩阵
cov_mat_fixed = eigvecs @ torch.diag(eigvals) @ eigvecs.T
  1. 使用更高精度计算:将张量转换为float64类型,能大幅降低浮点误差的影响:
a = torch.randn(64, 512, dtype=torch.float64)
cov_mat = (a.T @ a) / (a.size(0) - 1)
cov_mat_sym = (cov_mat + cov_mat.T) / 2
# 此时特征值的负偏差会显著缩小

补充说明

torch.mm和@运算符在矩阵乘法逻辑上完全一致,所以换用torch.mm(a.T, a)也无法解决精度问题,核心矛盾还是浮点运算的固有误差。

内容的提问来源于stack exchange,提问作者seankung99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:14:59