如何对特征向量编号并压缩存储大尺寸特征向量?
大矩阵特征向量存储压缩与定位解决方案
问题背景
我用以下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
相关产品推荐
相关产品推荐

