- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 python 开发一个小型卷积神经网络框架。卷积节点的代码已经可以运行(速度很慢),我想加快速度。热点是卷积滤波器在图像上移动的循环。我选择使用 cython 来加速这些循环。
明显的小注释,所有局部变量的 cdef 和删除边界检查,几乎使我的运行时间减少了 10%。这对我来说似乎很奇怪,根据我在网上读到的内容,cython 应该已经能够发挥其魔力。
不幸的是,代码位于类内部,并且严重依赖于该类的属性。我决定将其转换为 cdef 类。这意味着所有类属性都必须使用 cdef 声明。显然 cython 不支持 numpy 数组,所以我将所有 numpy 数组声明为 double[:,:,...]
到目前为止,代码运行良好,所有单元测试都通过了。现在对 .pyd 的编译(我在 Windows 下工作)仍然有效。但运行代码会产生类型错误:
TypeError: only length-1 arrays can be converted to Python scalars
这是一些代码。这是我的卷积节点的整个前向方法,可能太多并且不容易阅读。您可能只需要最后一行。这就是错误发生的原因:
@cython.boundscheck(False)
@cython.nonecheck(False)
def forward(self):
# im2col: x -> in_cols
# padding
cdef np.ndarray[DTYPE_t, ndim=4] x_padded = np.zeros((self.batch_size, self.in_colors, self.in_width + self.padding*2, self.in_height + self.padding*2))
if self.padding>0:
x_padded[:, :, self.padding:self.in_width+self.padding, self.padding:self.in_height+self.padding] = self.x
else:
x_padded[:]=self.x
# allocating new field
cdef np.ndarray[DTYPE_t, ndim=4] rec_fields = np.empty((self.filter_size**2* self.in_colors, self.batch_size, self.out_width, self.out_height))
# copying receptive fields
cdef int w,h
for w, h in np.ndindex((self.out_width, self.out_height)):
rec_fields[:, :, w, h] = x_padded[:, :, w*self.stride:w*self.stride + self.filter_size, h*self.stride:h*self.stride + self.filter_size] \
.reshape((self.batch_size, self.filter_size**2* self.in_colors)) \
.T
self.in_cols = rec_fields.reshape((self.filter_size**2 * self.in_colors, self.batch_size * self.out_width * self.out_height))
# linear node: in_cols -> out_cols
cdef np.ndarray[DTYPE_t, ndim=2] out_cols=np.dot(self.W,self.in_cols)+self.b
# col2im: out_cols -> out_image -> y
cdef np.ndarray[DTYPE_t, ndim=4] out_image = out_cols.reshape((self.out_colors, self.batch_size, self.out_width, self.out_height))
self.y[:] = out_image.transpose(1, 0, 2, 3)
最后一次对转置的调用在异常中被标记。我无法解释这一点。转置时内存 View 的行为是否有所不同?
更新:
我确定尺寸定义正确。如果存在尺寸不匹配,则会产生不同的运行时错误。现在无法检查,但它类似于“得到 4 维,预期 2 维”。我不得不说 cython 的类型系统给我留下了深刻的印象。 python 异常中的这种运行时类型信息非常有用。遗憾的是,它没有解释为什么上面的转置失败。
更新:
数组有些复杂:它们不能被覆盖,只能用作引用。
有点难以解释:神经网络的核心是一个循环,它在网络中的所有节点上连续调用方法forward()。
for node in self.nodes:
node.forward()
在此方法中,节点查看其输入数据,进行一些计算并写入其输出。它依赖于输入已经包含正确数据的事实。
为了设置我的网络,我以正确的顺序存储节点。我手动连接它们。
node2.x=node1.y
现在如果我写
self.y[:]= data
在node1的forward方法中,node2自动获得了正确的输入。这需要仔细编程:必须以正确的顺序调用前向方法,并且输出绝不能被覆盖,只能写入。
替代方案是一个巨大的结构,我在其中存储每个节点的输出并传递这些数据。这会创建大量样板代码并扰乱前向和后向传递。
更新:
forward 中的最后几行现在看起来像这样:
cdef np.ndarray[DTYPE_t, ndim=4] out_image = out_cols.reshape((self.out_colors, self.batch_size, self.out_width, self.out_height))
cdef double[:,:,:,:] temp
temp=out_image.transpose(1,0,2,3)
self.y[...] = temp
对 temp 的分配失败,并显示相同的 TypeError 消息。
最佳答案
self.y[...] = some_array
# or equivalently self.y[:,:,:,:] = some_array
将 some_array
复制到 self.y
中,该副本必须已初始化为正确的大小。它似乎也只有在 some_array
已经是一个内存 View 时才起作用(这对我来说没有多大意义,但情况似乎就是如此)。
(self.y[:] = some_array
仅适用于一维数组)
如果你只想让 self.y
“查看”你只想做的 numpy 数组
self.y = some_array
# in your case:
# self.y = out_image.transpose(1, 0, 2, 3)
这很可能适合您的目的!
<小时/>如果您特别热衷于制作副本(可能如果您使用了指向 self.y
或类似内容的 C 指针),那么您必须强制 some_array
成为内存 View 。你会做类似的事情
cdef double[:,:,:,:] temporary_view_of_transpose
# temporary_view_of_transpose now "looks at" the memory allocated by transpose
# no square brackets!
temporary_view_of_transpose = out_image.transpose(1, 0, 2, 3)
# data is copied from temporary_view_of_transpose to self.y
self.y[...] = temporary_view_of_transpose # (remembering that self.y must be the correct shape before this assignment).
<小时/>
我同意看到的错误消息没有帮助!
<小时/>编辑:以下是对我有用的最小完整示例(Cython 0.24、Python 3.5.1、Linux - 我无法轻松在 Anaconda 上进行测试)现阶段我不清楚您的代码有什么不同。
# memview.pyx
cimport numpy as np
import numpy as np
cdef class MemviewClass:
cdef double[:,:,:,:] y
def __init__(self):
self.y = np.zeros((2,3,4,5))
def do_something(self):
cdef np.ndarray[np.float64_t,ndim=4] out_image = np.ones((3,2,4,5))
cdef double[:,:,:,:] temp
temp = out_image.transpose(1,0,2,3)
self.y[...] = temp
def print_y(self):
# just to check it gets changed
print(np.asarray(self.y))
和 test_script.py 来显示它的工作原理:
# use pyximport for ease of testing
import numpy
import pyximport; pyximport.install(setup_args=dict(include_dirs=numpy.get_include()))
import memview
a = memview.MemviewClass()
a.print_y() # prints a big array of 0s
a.do_something()
a.print_y() # prints a big array of 1s
关于python - Cython MemoryView 转置 : Typeerror,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37174074/
c 不做边界检查。那么cython是如何检查是否编译成c的呢? %%cython --annotate cimport cython @cython.boundscheck(True) cpdef m
可以直接声明用于 Cython 构造函数? 据我了解,这是可能的: # Cython cdef int[3] li = [1, 2, 3] # C++ int[3] li = {1, 2, 3} 但
所以,如果你有一个头文件。 %%file test.h struct mystruct{ int i; int j; }; 然后你将它包装在 Cython 中: cdef extern fr
我正在构建一个独立于平台的 cython 项目,我想根据正在使用的编译器传递编译器参数。我可以猜测基于平台的编译器,或者假设它与用于 Python 的编译器相同,但不能保证匹配。通常我注入(injec
我使用诗歌构建我的 cython 包。我在所有函数和类中都有 NumPy 风格的文档字符串。我现在要做的是添加 Sphinx 自动文档并发布在 Read the Docs。 我已阅读此主题 How d
赛通 libcpp模块包含 priority_queue 的模板,这很好,除了一件事:我不能通过自定义比较器(或者,至少,我不知道如何)。 我需要这个,因为我需要 priority_queue做一个a
以下代码定义了一个简单的 Cython 函数(为方便起见,使用 Ipython 魔法)。 %load_ext cython %%cython def f(float x, float y=2):
我正在尝试使用 cython 进行复数计算。在示例代码中,我想计算复数的复指数函数。问题是我不知道如何将我的整数乘以虚数单位。python的虚数单位1.0j乘以cython执行时报错。 这是我的代码:
在这里停留在一些基本的 Cython 上 - 在 Cython 中定义字符串数组的规范且有效的方法是什么? 具体来说,我想定义一个定长常量数组char . (请注意,此时我不想引入 NumPy。) 在
是否有可能,如果是,如何确定 Cython 中整数数据类型的大小(以位为单位)? 我正在尝试做这样的事情,以获得整数大小: cdef WORD_BITS = 0 IF sizeof(unsigned
我只是想打印 cython 变量的地址,但我无法绕过错误消息: cdef int myvar print &myvar 抛出 Cannot convert 'int *' to Python obje
我有一个 C 头文件,它在宏中定义了一个函数。我需要从 Cython 调用它。有没有办法在 Cython 中使用宏并使其完全扩展?我已经有了 C 类型的参数。 我尝试像使用函数一样使用 cdef,我认
令人惊讶的是,我似乎找不到通过名称获取结构体元素的单个示例(无论是在网络上还是在 cython 示例中)。 所以我收到了一个指向 C 函数结构体的指针,并且想要一一访问这些元素并将它们重新打包到 py
我尝试围绕 C++ 库编写一个 Cython 包装器 http://primesieve.org/ 它包装了一个函数count。到目前为止,它可以正确安装 python setup.py instal
我正在尝试将 cython 模块 data.pyx 导入另一个 cython 模块 user.pyx。一切都编译得很好,但是当我尝试在 python 模块中调用 user.pyx 时,我收到错误“Im
更新:内存 View 获胜。Cython 使用类型化内存 View :0.0253449 特别感谢 lothario,他指出了几个关键的变化。 荒谬。当然现在的问题是,似乎不能对它们做太多算术(加法和
我有一个使用 memoryview 数组的 cython 模块,即... double[:,:] foo 我想使用多处理并行运行这个模块。但是我得到了错误: PicklingError: Can't
我正在尝试使用 Cython 加速 PEP 484 类型的 python 脚本。我想保持一些语义和可读性。 之前,我有一个 Flags = int def difference(f1: Flags,
这个问题已经有答案了: Collapse multiple submodules to one Cython extension (5 个回答) 已关闭 3 年前。 我在一个包中有多个 .py 文件
我已经能够在我的 .pyx 脚本上使用 cython 在 linux 上创建一个 .so 文件。我也可以成功地在我的 python 解释器上进行导入。 我的问题是如何在不使用 cython 的情况下将
我是一名优秀的程序员,十分优秀!