我正在为C ++使用dlib优化库,特别是以下功能:
template <
typename search_strategy_type,
typename stop_strategy_type,
typename funct,
typename funct_der,
typename T
>
double find_max (
search_strategy_type search_strategy,
stop_strategy_type stop_strategy,
const funct& f,
const funct_der& der,
T& x,
double max_f
);
函数f和der被设计为获取要修改的数据参数的向量,以获得函数的最大值。但是,被最大化的函数有四个参数(一个是我的数据集,另一个是我固定的)。但是,由于它们应该具有的格式,我无法将它们作为输入传递给f和der函数。如何将这些数据输入到函数中?我目前正在尝试以下操作(我对变量c进行了硬设置,但是对于矢量xgrequ,每次处理该函数时,我都会从文件中读取数据。
//Function to be minimized
double mleGPD(const column_vector& p)
{
std::ifstream infile("Xm-EVT.csv");
long double swapRet;
std::string closeStr;
std::vector<double> histRet;
//Read in historical swap data file
if (infile.is_open())
{
while (!infile.eof())
{
infile >> swapRet;
histRet.push_back(swapRet);
}
}
sort(histRet.begin(), histRet.end());
std::vector<double> negRet;
//separate out losses
for (unsigned c = 0; c < histRet.size(); c++)
{
if (histRet[c] < 0)
{
negRet.push_back(histRet[c]);
}
}
std::vector<double> absValRet;
//make all losses positive to fit with EVT convention
for (unsigned s = 0; s < negRet.size(); s++)
{
absValRet.push_back(abs(negRet[s]));
}
std::vector<double> xminusu, xmu, xgrequ;
int count = absValRet.size();
double uPercent = .9;
int uValIndex = ceil((1 - uPercent)*count);
int countAbove = count - uValIndex;
double c = (double)absValRet[uValIndex - 1];
//looking at returns above u
for (unsigned o = 0; o < uValIndex; ++o)
{
xmu.push_back(absValRet[o] - c);
if (xmu[o] >= 0)
{
xgrequ.push_back(absValRet[o]);
xminusu.push_back(xmu[o]);
}
}
double nu = xgrequ.size();
double sum = 0.0;
double a = p(0);
double b = p(1);
for (unsigned h = 0; h < nu; ++h)
{
sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
}
return sum;
}
//Derivative of function to be minimized
const column_vector mleGPDDer(const column_vector& p)
{
std::ifstream infile("Xm-EVT.csv");
long double swapRet;
std::string closeStr;
std::vector<double> histRet;
//Read in historical swap data file
if (infile.is_open())
{
while (!infile.eof())
{
infile >> swapRet;
histRet.push_back(swapRet);
}
}
sort(histRet.begin(), histRet.end());
std::vector<double> negRet;
//separate out losses
for (unsigned c = 0; c < histRet.size(); c++)
{
if (histRet[c] < 0)
{
negRet.push_back(histRet[c]);
}
}
std::vector<double> absValRet;
//make all losses positive to fit with EVT convention
for (unsigned s = 0; s < negRet.size(); s++)
{
absValRet.push_back(abs(negRet[s]));
}
std::vector<double> xminusu, xmu, xgrequ;
int count = absValRet.size();
double uPercent = .9;
int uValIndex = ceil((1 - uPercent)*count);
int countAbove = count - uValIndex;
double c = (double)absValRet[uValIndex - 1];
//looking at returns above u
for (unsigned o = 0; o < uValIndex; ++o)
{
xmu.push_back(absValRet[o] - c);
if (xmu[o] >= 0)
{
xgrequ.push_back(absValRet[o]);
xminusu.push_back(xmu[o]);
}
}
column_vector res(2);
const double a = p(0);
const double b = p(1);
double nu = xgrequ.size();
double sum1 = 0.0;
double sum2 = 0.0;
for (unsigned h = 0; h < nu; ++h)
{
sum1 += ((xgrequ[h]-c)/b)/(1-a*((xgrequ[h]-c)/b));
sum2 += log(1 - a*((xgrequ[h] - c) / b));
}
res(0) = sum1;//df/da
res(1) = sum2;//df/db
return res;
}
这是我实际的函数调用的样子:
//Dlib max finding
column_vector start(2);
start = .1, .1; //starting point for a and b
find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), mleGPD, mleGPDDer, start,100);
std::cout << "solution" << start << std::endl;
这种API非常常见。几乎总是可以实现f
和调用der
任何可调用函数,而不仅仅是静态函数。也就是说,您可以将带有运算符()的自定义类对象传递给它。
例如
struct MyF {
//int m_state;
// or other state variables, such as
std::vector<double> m_histRet;
// (default constructors will do)
double operator()(const column_vector& p) const {
return some_function_of(p, m_state);
}
};
int main(){
. . .
MyF myf{42};
// or
MyF myf{someVectorContainingHistRet};
// then use myf as you would have used mleGPD
}
您需要以相同的状态启动MyF和MyDer(std::vector<double> histRet
我认为是)。作为副本或对相同状态的(常量)引用。
编辑:更完整的示例:
struct MLGDPG_State {
std::vector<double> xgrequ;
// . . . and more you need in f or fder
}
MLGDPG_State makeMLGDPG_State(const std::string& filename){
std::ifstream infile(filename);
std::ifstream infile("Xm-EVT.csv");
long double swapRet;
std::string closeStr;
std::vector<double> histRet;
//Read in historical swap data file
if (infile.is_open())
{
while (!infile.eof())
{
infile >> swapRet;
histRet.push_back(swapRet);
}
}
sort(histRet.begin(), histRet.end());
std::vector<double> negRet;
//separate out losses
for (unsigned c = 0; c < histRet.size(); c++)
{
if (histRet[c] < 0)
{
negRet.push_back(histRet[c]);
}
}
std::vector<double> absValRet;
//make all losses positive to fit with EVT convention
for (unsigned s = 0; s < negRet.size(); s++)
{
absValRet.push_back(abs(negRet[s]));
}
std::vector<double> xminusu, xmu, xgrequ;
int count = absValRet.size();
double uPercent = .9;
int uValIndex = ceil((1 - uPercent)*count);
int countAbove = count - uValIndex;
double c = (double)absValRet[uValIndex - 1];
//looking at returns above u
for (unsigned o = 0; o < uValIndex; ++o)
{
xmu.push_back(absValRet[o] - c);
if (xmu[o] >= 0)
{
xgrequ.push_back(absValRet[o]);
xminusu.push_back(xmu[o]);
}
}
return {std::move(xgrequ)};
// Or just 'return MleGPD(xgrequ)' if you are scared of {} and move
}
//Functor Class, for ion to be minimized
struct MleGPD{
MLGDPG_State state;
double operator()(const column_vector& p) const {
auto mu = state.xgrequ.size();
double sum = 0.0;
double a = p(0);
double b = p(1);
for (unsigned h = 0; h < nu; ++h)
{
sum += log((1 / b)*pow(1 - a*((xgrequ[h] - c) / b), -1 + (1 / a)));
}
return sum;
};
对struct使用相同的模式MleGPD_Derivative
。
用法:
const auto state = makeMLGDPG_State("Xm-EVT.csv");
const auto f = MleGPD{state};
const auto der = MleGPD_Derivative{state};
start = .1, .1; //starting point for a and b
find_max(bfgs_search_strategy(), objective_delta_stop_strategy(1e-6), f, der, start,100);
std::cout << "solution" << start << std::endl;
请注意,对于像这样的简单结构,通常可以使用默认构造函数,复制构造函数等。也请注意http://en.cppreference.com/w/cpp/language/aggregate_initialization
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句