【问题标题】:Cython: Buffer dtype mismatch, expected 'int' but got Python objectCython:缓冲区 dtype 不匹配,预期为“int”但得到 Python 对象
【发布时间】:2019-09-10 17:53:01
【问题描述】:

我有一个np.ndarray,看起来像这样:

print(x)
[[1 3 None None None None]
 [0 2 3 4 None None]
 [1 5 4 None None None]
 [1 6 0 4 None None]
 [7 6 5 1 3 2]
 [4 7 2 8 None None]
 [7 4 3 None None None]
 [4 6 8 5 None None]
 [7 5 None None None None]]

我将它提供给定义如下的 cython 函数:

cpdef y(int[:,::1] x):
...

这会引发错误:ValueError: Buffer dtype mismatch, expected 'int' but got Python object

这可能是因为数组中存在Nones,因为将它们修改为0s 可以消除错误。但是None 的存在应该不会造成问题,如下所示:Cython Extension Types

那么,到底发生了什么?有没有快速的解决方案?

【问题讨论】:

  • Numpy 数组如a = np.array([1, None])a.dtypeobject,这就是问题所在,int[:,::1] 期望一个 int 缓冲区,但得到一个对象缓冲区
  • 该文档看起来好像整个变量可以是None,而您有一个由intnon-int/None 值组成的数组,这是无效的。
  • 那么,有没有简单的修正方法呢?我可以将Nones 类型转换为整数吗?还是我只需要将 Nones 转换为一些 int 值?

标签: python cython


【解决方案1】:

np.array([1, None])等numpy数组的dtypeobjectint[:,::1] 期望缓冲区为 int,但得到的缓冲区为 object,这就是错误所说的。

如何纠正这个应该取决于上下文,具体来说,None 是什么意思?

  1. 您可以将Nones 设置为0,然后将数组转换为int 数组
a = np.array([[1, None]])
a[a==None] = 0
a = a.astype(np.int)
f(a) # then deal with 0
  1. 或者您可以将cython函数签名更改为f(double[:, ::1])
a = np.array([[1, None]])
a = a.astype(np.float)
# a will be np.array([1.0, nan]),
# then deal with nan...
f(a)
  1. 或者您可以将 cython 函数签名更改为 f(object[:, ::1])(这可能不是您的意图)

所以,这取决于上下文。

【讨论】:

    【解决方案2】:

    Numpys ma 模块(用于 Masked Array)可能会执行您想要的操作:

    x = np.ma.array([[1, 3, 0, 0, 0, 0],
                     [0, 2, 3, 4, 0, 0]],
                    dtype=np.int,
                    mask=[[0, 0, 1, 1, 1, 1],
                          [0, 0, 0, 0, 1, 1]]) # True is "masked out"
    

    在 Cython 中,您可以将其拆分为数据和掩码

    def y(x):
       cdef int[:,::1] x_data = x.data
       cdef int8_t[:,::1] x_mask = x.mask.view(dtype=np.int8)
    

    我将其视为 int8,因为 Cython 不能很好地处理 dtype=np.bool


    您还可以考虑创建自己的数据结构 - 例如,它看起来总是None 的行尾,因此您可以创建一个ints 的二维数组和一个一维数组行长度(ints 的一维数组)。然后,您将忽略超出行长度的任何内容。


    可能值得强调为什么不能将None 存储在int 数组中——为了获得使用int 数组的速度和空间效率,然后Numpy 只分配存储数字所需的空间.存储None 需要为每个数字分配一点额外的空间来表示“实际上这是一个不同的类型”,并且每个操作都需要在它之前检查“这个数字实际上是一个数字吗?”。正如您可以想象的那样,这很快就会变得低效。

    【讨论】:

      猜你喜欢
      • 2018-12-25
      • 1970-01-01
      • 2017-10-14
      • 2014-11-07
      • 2013-02-05
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      相关资源
      最近更新 更多