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

如何对特征向量编号并压缩存储大尺寸特征向量?

大矩阵特征向量存储压缩与定位解决方案

问题背景

我用以下Python代码计算文本文件中矩阵的特征向量:

import numpy as np
from numpy import *
from matplotlib.pyplot import *
import re
import scipy.linalg as la

# 加载第一个矩阵
data=loadtxt('matKSMMF.txt',skiprows=8)
s = len(data)
print(s)
n=6567
kmat = [[0 for _ in range(n)] for _ in range(n)]
for x in range(s):
    m=data[x:x+1,:]
    kmat[int(m[0,0])-1][int(m[0,1])-1]=m[0,2]
K=np.array(kmat)
print(K)

# 加载第二个矩阵
data=loadtxt('matMSMMF.txt',skiprows=8)
s = len(data)
print(s)
Mmat = [[0 for _ in range(n)] for _ in range(n)]
for x in range(s):
    m=data[x:x+1,:]
    Mmat[int(m[0,0])-1][int(m[0,1])-1]=m[0,2]
M=np.array(Mmat)
print(M)

inv_M = np.linalg.inv(M)
print(inv_M)
L= la.eig(inv_M @ K)
EI=L[1]
print(EI)
np.savetxt('test.doc', EI)

但原始矩阵尺寸为6567×6567,生成的特征向量矩阵数据量过大无法存储,同时需要对特征向量编号以便后续处理(如相乘或存储特定向量),想知道如何压缩数据存储,以及如何定位第n个特征向量。


一、数据压缩存储方案

针对大尺寸特征向量的存储问题,有以下几种实用方案:

1. 只存储关键特征向量(按需计算)

大矩阵的特征向量中,通常只有前几个对应最大特征值的向量有实际分析价值,无需存储全部6567个向量。可以用scipy.sparse.linalg.eigs直接计算指定数量的特征向量(比如前20个),跳过无意义的向量,同时用稀疏矩阵重构原始矩阵,大幅节省内存:

import scipy.sparse as sp
import scipy.sparse.linalg as spla

# 用稀疏矩阵重构K和M(比密集矩阵省90%以上内存)
data_k = np.loadtxt('matKSMMF.txt', skiprows=8)
rows_k = data_k[:,0].astype(int)-1
cols_k = data_k[:,1].astype(int)-1
vals_k = data_k[:,2]
K = sp.coo_matrix((vals_k, (rows_k, cols_k)), shape=(6567,6567)).tocsr()

data_m = np.loadtxt('matMSMMF.txt', skiprows=8)
rows_m = data_m[:,0].astype(int)-1
cols_m = data_m[:,1].astype(int)-1
vals_m = data_m[:,2]
M = sp.coo_matrix((vals_m, (rows_m, cols_m)), shape=(6567,6567)).tocsr()

# 计算前20个模最大的特征值对应的特征向量
eig_vals, eig_vecs = spla.eigs(K, M=M, k=20, which='LM')

这样得到的eig_vecs只有20列,存储压力骤降。

2. 使用二进制压缩格式存储

numpy的文本存储格式(如savetxt)空间利用率极低,改用二进制压缩格式,体积可缩小10倍以上:

# 压缩存储全部特征向量(如果必须存的话)
np.savez_compressed('eigenvectors_compressed.npz', eig_vecs=EI)
# 读取时
loaded_data = np.load('eigenvectors_compressed.npz')
EI = loaded_data['eig_vecs']

3. 降低数据精度存储

如果业务允许牺牲部分精度,可以将特征向量从默认的float64转成float32甚至float16,直接减半或减至1/4体积:

EI_compressed = EI.astype(np.float32)
np.savez_compressed('eigenvectors_float32.npz', eig_vecs=EI_compressed)

4. 稀疏矩阵格式存储

如果特征向量本身是稀疏的(大部分元素为0),可以用稀疏矩阵格式存储:

EI_sparse = sp.csr_matrix(EI)
sp.save_npz('eigenvectors_sparse.npz', EI_sparse)

二、特征向量编号与定位

1. 默认索引规则

scipy.linalg.la.eig返回的特征向量矩阵EI中,每一列对应一个特征向量,Python采用0索引:

  • 第0个特征向量(默认顺序):EI[:, 0]
  • 第n个特征向量(1-based编号):EI[:, n-1]

对应的特征值存在L[0]中,L[0][i]与EI[:,i]一一对应。

2. 按特征值排序后的定位

如果需要按特征值大小给向量编号(比如最大特征值对应第1号),先排序再定位:

eig_vals, eig_vecs = la.eig(inv_M @ K)
# 按特征值绝对值从大到小排序,得到索引
sorted_idx = np.argsort(np.abs(eig_vals))[::-1]
# 排序后的特征向量矩阵,第0列是最大特征值对应的向量
sorted_eig_vecs = eig_vecs[:, sorted_idx]

# 获取第5个(1-based)特征向量
target_vec = sorted_eig_vecs[:, 4]

3. 存储时保留编号映射

如果只存储部分向量,可以将向量编号和对应向量绑定存储:

# 存储前10个排序后的向量,编号为vec_1到vec_10
top_vecs = {f'vec_{i+1}': sorted_eig_vecs[:,i] for i in range(10)}
np.savez_compressed('top_10_eigenvectors.npz', **top_vecs)

# 读取时直接按编号提取
loaded = np.load('top_10_eigenvectors.npz')
vec_3 = loaded['vec_3']

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:43:19