在第三方提供的numpy数据集上运行时,遇到了以下异常:
ValueError: When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array
在什么情况下numpy会引起这种情况?我的代码在numpy数组上应用视图,在这里尝试应用与行中元素数量匹配的结构化dtype
。
当在函数X.view([('', X.dtype)] * X.shape[1])
中调用语句f
时却遇到此错误-但不是在每次对该函数f
的调用中都这样:
ipdb> X.view([('', X.dtype)] * X.shape[1])
*** ValueError: When changing to a larger dtype, its size must be a divisor of the total size in bytes of the last axis of the array.
X
始终是具有两个轴的数组(len(X.shape)
始终是2),因此您希望结构化的dtype
长X.shape[1]
以适合最后一个轴(X.shape[1]
)。
并非所有数据集都不会发生该异常,那么是什么导致numpy为某些数组而不是其他数组抛出此异常?我什至看不到哪个.py numpy源代码引发此错误。
我发现很难为此生成MCVE,但是我已将其缩小为colab notebook,但仍要在此处发布。
这里的X
应该是iris
数据集的子集,我从scikit学习中获得了该数据集。
from sklearn.datasets import load_iris
X = load_iris().data
我的代码如下所示:
def f(X):
X_rows = X.view([('', X.dtype)] * X.shape[1])
def g(X):
f(X)
def h(X):
f(X)
# call the functions
g(X) # this runs without a problem
f(X) # this returns the error
参考方案
您正在尝试使用不兼容的内存布局在数组上创建视图,其中输出dtype
的itemsize不能完全满足内存中覆盖“ last”的全长所需的字节数源数组的轴。如果您只是直接在数组上设置.dtype
属性,而不仅仅是在ndarray.view()
上设置例外,则该例外也适用(这将在该新对象上设置ndarray
的情况下创建一个新的dtype
)。
就内存布局而言,此处的“最后一个”轴是“最里面的”尺寸。对于shape[-1]
的C顺序数组,对于shape[0]
的Fortran顺序数组。该尺寸大小乘以原始dtype.itemsize
必须由新的dtype.itemsize
整除,否则您将无法“遍历”内部存储器结构。
例如,对于形状为(4, 3, 5)
且dtype.itemsize
为8的C阶(行优先级)数组,“最后一个”轴占用5 * 8 == 40字节的内存,因此您可以创建带有10、20和40较大dtypes的视图。相同的数组,但以Fortran顺序(列大顺序)使用4 * 8 == 32字节的内存,将您的选择限制为较大dtypes仅16和32。
如果X.view([('', X.dtype)] * X.shape[1])
失败,则X.shape
的维数不只是2,或者它是使用Fortran排序的数组。您可以使用X.shape[-1]
校正第一个,也可以通过查看ndarray.flags['F_CONTIGUOUS']
检查纬度。将它们组合成一个表达式,如下所示:
X_rows = X.view([('', X.dtype)] * X.shape[0 if X.flags['F_CONTIGUOUS'] else -1])
但是,如ndarray.view()
documentation警告:
通常,在由切片,转置,fortran顺序等定义的数组上,应避免更改dtype
大小(每个条目的字节数)的视图。[。]
当您尝试更改Fortran顺序数组的dtype时,将发出警告:
DeprecationWarning: Changing the shape of an F-contiguous array by descriptor assignment is deprecated. To maintain the Fortran contiguity of a multidimensional Fortran array, use 'a.T.view(...).T' instead
因此最好转置数组,创建视图,然后再次转置结果视图:
if X.flags['F_CONTIGUOUS']:
X_rows = X.T.view([('', X.dtype)] * X.shape[0]).T
您仍然需要在这里坚持X.shape[0]
,即转置数组的shape[-1]
。
不支持在Fortran顺序数组上更改dtype
的事实也可以解释该异常对“最后一个轴”的引用,这在C顺序数组方面是很自然的,但在应用于Fortran时感觉与直觉相反顺序数组。
我什至看不到哪个.py numpy源代码引发此错误。
Numpy主要是用C编写的(带有Fortran 77),因此您需要深入研究已编译组件的源代码。在dtype
descriptor setter function中引发错误,当PyArray_View()
function调用PyObject_SetAttrString()
函数以从dtype
method调用ndarray.view()
属性时将其设置为X.flags['C_CONTIGUOUS']
。
根据源代码,不仅不建议更改Fortran顺序数组的dtype,而且完全不支持非连续数组的视图(这意味着如果X.flags['F_CONTIGUOUS']
和False
均为dtype
,则可以完全不要更改)。
我在Angular工作,正在使用Http请求和响应。是否可以在“响应”中发送多个参数。角度文件:this.http.get("api/agent/applicationaware").subscribe((data:any)... python文件:def get(request): ... return Response(seriali…
Python exchangelib在子文件夹中读取邮件 - python我想从Outlook邮箱的子文件夹中读取邮件。Inbox ├──myfolder 我可以使用account.inbox.all()阅读收件箱,但我想阅读myfolder中的邮件我尝试了此页面folder部分中的内容,但无法正确完成https://pypi.python.org/pypi/exchangelib/ 参考方案 您需要首先掌握Folder的myfo…
R'relaimpo'软件包的Python端口 - python我需要计算Lindeman-Merenda-Gold(LMG)分数,以进行回归分析。我发现R语言的relaimpo包下有该文件。不幸的是,我对R没有任何经验。我检查了互联网,但找不到。这个程序包有python端口吗?如果不存在,是否可以通过python使用该包? python参考方案 最近,我遇到了pingouin库。
如何用'-'解析字符串到节点js本地脚本? - python我正在使用本地节点js脚本来处理字符串。我陷入了将'-'字符串解析为本地节点js脚本的问题。render.js:#! /usr/bin/env -S node -r esm let argv = require('yargs') .usage('$0 [string]') .argv; console.log(argv…
TypeError:'str'对象不支持项目分配,带有json文件的python - python以下是我的代码import json with open('johns.json', 'r') as q: l = q.read() data = json.loads(l) data['john'] = '{}' data['john']['use…