這是我的完整解決方案,爲您的娛樂。複製,粘貼和修改。顯然,我面臨的問題比上述問題稍微複雜一些。我用了一些 Dan Foreman Mackay's online code。
我的代碼的目標是返回一個協方差矢量(不管是什麼)。我有一個名爲aux.c
C文件,返回一個新分配的數組:
#include "aux.h"
#include <math.h>
#include <stdlib.h>
double *covVec(double *X, double *x, int nvecs, int veclen) {
double r = 1.3;
double d = 1.0;
double result;
double dist;
int n;
double *k;
k = malloc(nvecs * sizeof(double));
int row;
for(row = 0 ; row < nvecs ; row++) {
result = 0.0;
for (n = 0; n < veclen; n++) {
dist = x[n] - X[row*veclen + n];
result += dist * dist;
}
result = d*exp( -result/(2.0*r*r) );
k[row] = result;
}
return k;
}
然後,我需要一個名爲aux.h
很短的頭文件:
double *covVec(double *X, double *x, int nvecs, int veclen);
爲了把這個包到Python我有_aux.c
:
#include <Python.h>
#include <numpy/arrayobject.h>
#include "aux.h"
#include <stdio.h>
static char module_docstring[] =
"This module provides an interface for calculating covariance using C.";
static char cov_vec_docstring[] =
"Calculate the covariances between a vector and a list of vectors.";
static PyObject *_aux_covVec(PyObject *self, PyObject *args);
static PyMethodDef module_methods[] = {
{"cov_vec", _aux_covVec, METH_VARARGS, cov_vec_docstring},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC init_aux(void) {
PyObject *m = Py_InitModule3("_aux", module_methods, module_docstring);
if (m == NULL)
return;
/* Load `numpy` functionality. */
import_array();
}
static PyObject *_aux_covVec(PyObject *self, PyObject *args)
{
PyObject *X_obj, *x_obj;
/* Parse the input tuple */
if (!PyArg_ParseTuple(args, "OO", &X_obj, &x_obj))
return NULL;
/* Interpret the input objects as numpy arrays. */
PyObject *X_array = PyArray_FROM_OTF(X_obj, NPY_DOUBLE, NPY_IN_ARRAY);
PyObject *x_array = PyArray_FROM_OTF(x_obj, NPY_DOUBLE, NPY_IN_ARRAY);
/* If that didn't work, throw an exception. */
if (X_array == NULL || x_array == NULL) {
Py_XDECREF(X_array);
Py_XDECREF(x_array);
return NULL;
}
/* What are the dimensions? */
int nvecs = (int)PyArray_DIM(X_array, 0);
int veclen = (int)PyArray_DIM(X_array, 1);
int xlen = (int)PyArray_DIM(x_array, 0);
/* Get pointers to the data as C-types. */
double *X = (double*)PyArray_DATA(X_array);
double *x = (double*)PyArray_DATA(x_array);
/* Call the external C function to compute the covariance. */
double *k = covVec(X, x, nvecs, veclen);
if (veclen != xlen) {
PyErr_SetString(PyExc_RuntimeError,
"Dimensions don't match!!");
return NULL;
}
/* Clean up. */
Py_DECREF(X_array);
Py_DECREF(x_array);
int i;
for(i = 0 ; i < nvecs ; i++) {
printf("k[%d] = %f\n",i,k[i]);
if (k[i] < 0.0) {
PyErr_SetString(PyExc_RuntimeError,
"Covariance should be positive but it isn't.");
return NULL;
}
}
npy_intp dims[1] = {nvecs};
PyObject *ret = PyArray_SimpleNew(1, dims, NPY_DOUBLE);
memcpy(PyArray_DATA(ret), k, nvecs*sizeof(double));
free(k);
return ret;
}
我有一個python文件名爲setup_cov.py
:
from distutils.core import setup, Extension
import numpy.distutils.misc_util
setup(
ext_modules=[Extension("_aux", ["_aux.c", "aux.c"])],
include_dirs=numpy.distutils.misc_util.get_numpy_include_dirs(),
)
我使用python2.7 setup_cov.py build_ext --inplace
從命令行進行編譯。 然後我運行下面的Python測試文件:
import numpy as np
import _aux as a
nvecs = 6
veclen = 9
X= []
for _ in range(nvecs):
X.append(np.random.normal(size= veclen))
X = np.asarray(X)
x = np.random.normal(size=veclen)
k = a.cov_vec(X,x)
print(k)
您編輯的調用應該是'PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE,vector)'。它不是這樣工作嗎? – Jaime
'dims [1] = 2'是一個索引錯誤 –