【发布时间】:2014-10-09 18:31:57
【问题描述】:
我正在尝试使用 numpy API 制作一个通用的 ufunc。输入是一个(n x m) 矩阵和一个标量,输出是两个矩阵((n x p) 和(p x m))。但我不知道该怎么做。有人可以帮助我吗?
在初始化函数中,我使用带有签名的PyUFunc_FromFuncAndDataAndSignature 函数:
"(n,m),()->(n,p),(p,m)"
我可以读取输入(矩阵和标量),但我想使用标量输入,例如签名中的维度 p。有可能吗?
这是一个仅打印输入的示例代码:
#include "Python.h"
#include "math.h"
#include "numpy/ndarraytypes.h"
#include "numpy/ufuncobject.h"
static PyMethodDef nmfMethods[] = {
{NULL, NULL, 0, NULL}
};
static void double_nmf(char **args, npy_intp *dimensions,
npy_intp* steps, void* data)
{
npy_intp i, j,
n = dimensions[1], //dimensions of input matrix
m = dimensions[2]; //
printf("scalar: %d\n",*(int*)args[1]); // input scalar
// just print input matrix
printf("Input matrix:\n");
for(i=0;i<n;i++){
for(j=0;j<m;j++){
printf("%.1f ",*(double*)(args[0]+8*(i*m+j)));
}
printf("\n");
}
return;
}
static PyUFuncGenericFunction nmf_functions[] = { double_nmf };
static void * nmf_data[] = { (void *)NULL };
static char nmf_signatures[] = { PyArray_DOUBLE, PyArray_INT, PyArray_DOUBLE, PyArray_DOUBLE };
char *nmf_signature = "(n,m),()->(n,p),(p,m)";
PyMODINIT_FUNC initnmf(void)
{
PyObject *m, *d, *version, *nmf;
m = Py_InitModule("nmf", nmfMethods);
if (m == NULL) {
return;
}
import_array();
import_umath();
d = PyModule_GetDict(m);
version = PyString_FromString("0.1");
PyDict_SetItemString(d, "__version__", version);
Py_DECREF(version);
nmf = PyUFunc_FromFuncAndDataAndSignature(nmf_functions, nmf_data, nmf_signatures, 1,
2, 2, PyUFunc_None, "nmf",
"", 0, nmf_signature);
PyDict_SetItemString(d, "nmf", nmf);
Py_DECREF(nmf);
}
此代码可以编译并运行。 python脚本在这里:
#/usr/bin/python
import numpy as np
import nmf
x = np.array([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]])
y,z = nmf.nmf(x,2)
print "Shapes of outputs: ", y.shape, z.shape
终端输出为:
scalar: 2
Input matrix:
1.0 2.0 3.0 4.0 5.0
6.0 7.0 8.0 9.0 10.0
11.0 12.0 13.0 14.0 15.0
16.0 17.0 18.0 19.0 20.0
Shapes of outputs: (4, 1) (1, 5)
我的疑问是如何使用标量输入(在这种情况下为 2),如输出矩阵的维度 p。在示例中 p = 1,我没有设置它。
【问题讨论】:
-
请显示原始数组、标量和最终数组的最小示例。
-
很遗憾,这不可能。 gufuncs 的签名解析器的工作方式,你的输出数组总是有
p == 1。如果您想要任何其他值,实现它的唯一方法是预先分配输出数组,并使用您的 gufunc 的out关键字参数传递它们。 NumPy 1.10 可能会带来额外的功能,可以让你尝试做的事情。 -
您是说您希望
p由标量输入的值 确定吗?如果是这样,那么您的 gufunc 不是您想要的——只需创建一个常规函数即可。 gufunc 的想法是它可以通过参数广播,但假设我想传入两个不同的标量 [3, 4] - 输出形状不能是 (2,n,3),(2,3 ,m) 和 (2,n,4),(2,4,m) 同时进行。 (2 来自通过输入向量进行广播。)
标签: python c numpy python-c-api