25

这里有使用 C 创建自定义 numpy dtypes 的示例:

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

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

用例:

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

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

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

  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_vec工作h_vec

我当前的实现使用numpy.vectorize. 这对于 1 和 2 来说效果很好,但对于 3 来说太慢了。还要注意,我不能这样做因为我的 MultiData 对象中的失败次数事先不知道。

4

2 回答 2

1

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

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

>>> 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)]))
    <...>
于 2012-11-11T16:32:12.163 回答
0

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

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

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

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

于 2012-11-09T06:26:04.600 回答