繁体   English   中英

如何使用 cython 创建自定义 numpy dtype

[英]How to create a custom numpy dtype using cython

有创建用C定制numpy的dtypes例子在这里

此外, 似乎可以在 cython 中创建自定义 ufunc:

似乎也应该可以使用 cython 创建一个 dtype(然后为其创建自定义 ufunc)。 是否可以? 如果是这样,你能发布一个例子吗?

使用案例:

我想做一些生存分析。 基本数据元素是生存时间(浮点数)和相关审查值(假如果相关时间代表失败时间,真如果它代表审查时间(即,在观察期间没有发生故障))。

显然我可以只使用两个 numpy 数组来存储这些值:一个用于时间的浮点数组和一个用于检查器值的 bool 数组。 但是,我想考虑一个事件多次发生的可能性(这是一个很好的模型,例如,心脏病发作 - 您可以有多个)。 在这种情况下,我需要一个我称之为MultiEvent的对象数组。 每个MultiEvent包含一系列浮点数(未经审查的故障时间)和一个观察期(也是一个浮点数)。 请注意,所有MultiEvent的失败次数并不相同。

我需要能够对MultiEvent数组执行一些操作:

  1. 获取每个失败的次数

  2. 获取审查时间(即观察时间减去所有失败时间的总和)

  3. 根据额外的参数数组(例如危险值数组)计算对数似然。 例如,单个MultiEvent M和恒定危险值h对数似然类似于:

    sum(log(h) + h*t for t in M.times) - h*(M.period - sum(M.times))

其中M.times是故障时间的列表(数组,无论如何), M.period是总观察期。 我希望应用适当的 numpy 广播规则,以便我可以:

log_lik = logp(M_vec,h_vec)

只要M_vech_vec的尺寸兼容,它就会起作用。

我当前的实现使用numpy.vectorize 这工作得很好1和2,但实在是太慢了3.另请注意,我不能做这个,因为故障在我的多数据对象的数量是不是提前知道。

Numpy 数组最适合固定大小的数据类型。 如果数组中的对象不是固定大小(例如您的 MultiEvent),则操作会变得更慢。

我建议您将所有生存时间存储在具有 3 个字段的一维线性记录数组中:event_id、time、period。 每个事件可以在数组中出现多次:

>>> import numpy as np
>>> rawdata = [(1, 0.4, 4), (1, 0.6, 6), (2,2.6, 6)]
>>> npdata = np.rec.fromrecords(rawdata, names='event_id,time,period')
>>> print npdata
[(1, 0.40000000000000002, 4) (1, 0.59999999999999998, 6) (2, 2.6000000000000001, 6)]

要获取特定索引的数据,您可以使用花哨的索引:

>>> eventdata = npdata[npdata.event_id==1]
>>> print eventdata
[(1, 0.40000000000000002, 4) (1, 0.59999999999999998, 6)]

这种方法的优点是您可以轻松地将它与基于 ndarray 的函数集成。 您还可以按照手册中的说明从 cython 访问此数组:

cdef packed struct Event:
    np.int32_t event_id
    np.float64_t time
    np.float64_6 period

def f():
    cdef np.ndarray[Event] b = np.zeros(10,
        dtype=np.dtype([('event_id', np.int32),
                        ('time', np.float64),
                        ('period', np.float64)]))
    <...>

我很抱歉没有直接回答这个问题,但我以前也遇到过类似的问题,如果我理解正确的话,您现在遇到的真正问题是您拥有可变长度的数据,这真的,真的不是其中之一numpy 的优势,这就是您遇到性能问题的原因。 除非您事先知道多事件的最大条目数,否则您会遇到问题,即便如此,对于那些不是多事件的事件,您也会浪费大量充满零的内存/磁盘空间。

您拥有包含多个字段的数据点,其中一些与其他字段相关,而其中一些需要分组识别。 这强烈暗示您应该考虑某种形式的数据库来存储此信息,出于性能、内存、磁盘空间和健全性原因。

对于一个不熟悉你的代码的人来说,理解一个简单的数据库模式比一个复杂的、被黑客攻击的 numpy 结构要容易得多,后者会令人沮丧地缓慢和臃肿。 相比之下,SQL 查询编写起来又快又容易。

根据我对您的解释的理解,我建议使用 Event 和 MultiEvent 表,其中每个 Event 条目在相关的 MultiEvent 表中都有一个外键。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM