VisibleDeprecationWarning含义解析及Python特征矩阵提取代码报错修复
MMF矩阵特征提取代码的警告与错误解析及修复
问题背景
用户尝试用以下Python代码提取两个MMF矩阵文本的特征矩阵(EI):
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) n = 6567 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) print('Eigen vector matrices is', L) EI = np.array(L) print(EI)
运行代码时出现如下警告与错误:
VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray. EI=np.array(L) Traceback (most recent call last): File "mmf.py", line 30, in <module> EI=np.array(L) ValueError: could not broadcast input array from shape (6567,6567) into shape (6567,)
警告与错误含义
警告含义
VisibleDeprecationWarning的触发原因是:scipy.linalg.eig()返回的是一个元组,包含两个形状完全不同的数组:
- 第一个元素是特征值数组,形状为
(6567,)(一维数组) - 第二个元素是特征向量矩阵,形状为
(6567,6567)(二维数组)
当你直接用np.array(L)尝试把这个元组转成numpy数组时,因为两个子数组形状不匹配,属于"不规则嵌套序列",numpy会抛出这个 deprecation 警告,提示这种用法未来会被禁用。
错误含义
ValueError的本质是numpy无法将两个形状不同的数组广播成一个统一的数组:特征值是一维的,特征向量是二维的,两者维度不兼容,无法合并成一个单一的numpy数组,因此报错。
修复方案
核心修复:正确处理la.eig()的返回值
scipy.linalg.eig()的返回值是(特征值数组, 特征向量矩阵)的元组,不需要强行合并成一个数组,应该根据需求分别提取:
方案1:分别提取特征值和特征向量(推荐)
这是最合理的处理方式,因为特征值和特征向量是不同用途的数据,分开使用更灵活:
# 替换原代码中L=la.eig(...)及之后的代码 eigenvalues, eigenvectors = la.eig(inv_M @ K) # 如果EI指的是特征向量矩阵,直接赋值即可 EI = eigenvectors print("特征向量矩阵EI的形状:", EI.shape) print(EI) # 如需保存特征值,可单独处理 # print("特征值数组:", eigenvalues)
方案2:强行合并为对象数组(不推荐)
如果确实需要将两者放在一个数组中,可以通过指定dtype=object来避免警告和错误,但这种方式会让数组操作变得不灵活,仅在特殊场景下使用:
EI = np.array(L, dtype=object) print(EI)
代码优化建议
原代码存在一些可以简化和高效化的地方:
- 避免全局导入:去掉
from numpy import *和from matplotlib.pyplot import *,防止命名冲突,使用np.前缀调用numpy方法即可。 - 用numpy直接初始化矩阵:替换列表推导式初始化矩阵的方式,使用
np.zeros((n,n))更高效:
M矩阵的初始化和赋值可以做同样的修改。# 替换原代码中kmat的初始化和赋值逻辑 kmat = np.zeros((n, n)) for x in range(s): row = int(data[x, 0]) - 1 col = int(data[x, 1]) - 1 kmat[row, col] = data[x, 2] K = kmat # 无需再转成数组
内容的提问来源于stack exchange,提问作者Md Salem
相关产品推荐
相关产品推荐

