gpt4 book ai didi

c++ - 通过 pybind11 从 C++ 使用 scipy

转载 作者:行者123 更新时间:2023-11-30 03:21:52 56 4
gpt4 key购买 nike

我希望能够使用来自 C++ 的 python 模块,例如 numpyscipy 等。以下代码尝试调用 scipy.optimize.curve_fit 来拟合抛物线函数。调用 curve_fit 时出现问题。此处抛出异常。

#include <iostream>
#include <pybind11/embed.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h> // mandatory for myPyObject.cast<std::vector<T>>()
#include <pybind11/functional.h> // mandatory for py::cast( std::function )

namespace py = pybind11;

int main()
{
try {
py::scoped_interpreter guard{};

py::module np = py::module::import("numpy");
py::object random = np.attr("random");

py::module scipy = py::module::import("scipy.optimize");

// create some data for fitting
std::vector<double> xValues(11, 0);
std::vector<double> yValues(11, 0);
for (int i = -5; i < 6; ++i) {
xValues[i + 5] = i;
yValues[i + 5] = i*i;
}

// cast it to numpy arrays
py::array_t<double> pyXValues = py::cast(xValues);
py::array_t<double> pyYValues = py::cast(yValues);

// add some noise to the yValues using numpy -> Works!
py::array_t<double> pyYValuesNoise = np.attr("add")(pyYValues, random.attr("randn")(11));

// create a function f_a(x) = a*x^2
std::function<std::vector<double>(std::vector<double>, double)> squared = [](std::vector<double> x, double a) {
std::vector<double> retvals(x);
std::transform(x.begin(), x.end(), retvals.begin(), [a](double val) { return a*val*val; });
return retvals;
};

// cast it to a python function
py::function pySquared = py::cast(squared);

// get scipy.optimize.curve_fit
py::function curve_fit = scipy.attr("curve_fit");

// call curve_fit -> throws exception
/* py::object = */ curve_fit(pySquared, pyXValues, pyYValues);

}
catch (std::exception error) {
std::cout << error.what() << std::endl;
}
system("pause");
return 0;
}

异常给出信息:

ValueError: no signature found for builtin < built-in method of PyCapsule object at 0x00000204FFE9C630>

At:
D:\Programs\python36_6_x64\Lib\inspect.py(2090): _signature_from_builtin D:\Programs\python36_6_x64\Lib\inspect.py(2266): _signature_from_callable D:\Programs\python36_6_x64\Lib\inspect.py(2802): from_callable D:\Programs\python36_6_x64\Lib\inspect.py(3052): signature D:\Programs\python36_6_x64\lib\site-packages\scipy_lib_util.py(290): getargspec_no_self
D:\Programs\python36_6_x64\lib\site-packages\scipy\optimize\minpack.py(685): curve_fit

如何从 C++ 正确调用 curve_fit?

最佳答案

基于 Jens Munk 的 comment我创建了一个 Python 模块“MyPythonModule”,其中包含文件“MyFunctionality.py”,函数为

def python_square_function(x, a):
return a*x**2

我将此模块的路径添加到环境变量 PYTHONPATH 中。 C++ 代码更改为:

#include <iostream>
#include <pybind11/embed.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h> // for myPyObject.cast<std::vector<T>>()

namespace py = pybind11;

int main()
{
py::scoped_interpreter guard{};

py::module np = py::module::import("numpy");
py::object random = np.attr("random");
py::module scipy = py::module::import("scipy.optimize");

// Load created module containing f_a(x) = a*x^2
py::module myModule = py::module::import("MyPythonModule.MyFunctionality");

// Create some data for fitting
std::vector<double> xValues(11, 0);
std::vector<double> yValues(11, 0);
for (int i = -5; i < 6; ++i) {
xValues[i + 5] = i;
yValues[i + 5] = i*i;
}

// Cast data to numpy arrays
py::array_t<double> pyXValues = py::cast(xValues);
py::array_t<double> pyYValues = py::cast(yValues);

// Add some noise to the yValues using numpy
py::array_t<double> pyYValuesNoise = np.attr("add")(pyYValues, random.attr("randn")(11));

// Get the function f_a(x) = a*x^2 we want to fit
py::function pySquareFunction = myModule.attr("python_square_function");

// Load scipy.optimize.curve_fit
py::function curve_fit = scipy.attr("curve_fit");

// Call curve_fit
py::object retVals = curve_fit(pySquareFunction, pyXValues, pyYValuesNoise);

// The return value contains the optimal values and the covariance matrix.
// Get the optimal values
py::object optVals = retVals.attr("__getitem__")(0);

// Cast return value back to std::vector and show the result
std::vector<double> retValsStd = optVals.cast<std::vector<double>>();
std::cout << "Fitted parameter a = " << retValsStd[0] << std::endl;

return 0;
}

此代码导致预期行为:拟合参数 a = 0.978144

不幸的是,这仍然是一种解决方法,它使用了一些外部 Python 代码。如果能够在 C++ 源代码中定义所有内容,那就太好了。

关于c++ - 通过 pybind11 从 C++ 使用 scipy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51762140/

56 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com