ValueError:更改为较大的dtype时,其大小必须为数组最后一个轴的总大小(以字节为单位)的除数 - python

在第三方提供的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),因此您希望结构化的dtypeX.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,则可以完全不要更改)。

在返回'Response'(Python)中传递多个参数 - python

我在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…